34 #define YAML_VERSION_MAJOR 1
35 #define YAML_VERSION_MINOR 1
39 #define RECURSION_LIMIT 128
44 #define DEFAULT_NAME_LEN 16
46 #define MANGLE_ERRORS_MAX 10
47 static int mangle_errors = 0;
49 static char *conf_dirname = NULL;
51 static int ConfYamlParse(yaml_parser_t *parser,
ConfNode *parent,
int inseq,
int rlevel);
72 while ((c = strchr(
string,
'_')))
84 ConfYamlSetConfDirname(
const char *filename)
88 ep = strrchr(filename,
'\\');
90 ep = strrchr(filename,
'/');
94 if (conf_dirname == NULL) {
96 "ERROR: Failed to allocate memory while loading configuration.");
101 if (conf_dirname == NULL) {
103 "ERROR: Failed to allocate memory while loading configuration.");
105 conf_dirname[ep - filename] =
'\0';
119 ConfYamlHandleInclude(
ConfNode *parent,
const char *filename)
121 yaml_parser_t parser;
122 char include_filename[PATH_MAX];
126 if (yaml_parser_initialize(&parser) != 1) {
132 strlcpy(include_filename, filename,
sizeof(include_filename));
135 snprintf(include_filename,
sizeof(include_filename),
"%s/%s",
136 conf_dirname, filename);
139 file = fopen(include_filename,
"r");
142 "Failed to open configuration include file %s: %s",
143 include_filename, strerror(errno));
147 yaml_parser_set_input_file(&parser, file);
149 if (ConfYamlParse(&parser, parent, 0, 0) != 0) {
151 "Failed to include configuration file %s", filename);
158 yaml_parser_delete(&parser);
175 ConfYamlParse(yaml_parser_t *parser,
ConfNode *parent,
int inseq,
int rlevel)
179 memset(&event, 0,
sizeof(event));
188 "configuration file, aborting.");
193 if (!yaml_parser_parse(parser, &event)) {
195 "Failed to parse configuration file at line %" PRIuMAX
": %s\n",
196 (uintmax_t)parser->problem_mark.line, parser->problem);
201 if (event.type == YAML_DOCUMENT_START_EVENT) {
202 SCLogDebug(
"event.type=YAML_DOCUMENT_START_EVENT; state=%d", state);
206 yaml_version_directive_t *ver =
207 event.data.document_start.version_directive;
211 "The configuration file must begin with the following two lines: %%YAML 1.1 and ---");
214 int major = ver->major;
215 int minor = ver->minor;
221 else if (event.type == YAML_SCALAR_EVENT) {
222 char *value = (
char *)event.data.scalar.value;
223 char *
tag = (
char *)
event.data.scalar.tag;
224 SCLogDebug(
"event.type=YAML_SCALAR_EVENT; state=%d; value=%s; "
225 "tag=%s; inseq=%d", state, value,
tag, inseq);
230 if (state ==
CONF_KEY && strlen(value) == 0) {
236 event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE) {
237 if (strlen(value) == 0 || strcmp(value,
"~") == 0 || strcmp(value,
"null") == 0 ||
238 strcmp(value,
"Null") == 0 || strcmp(value,
"NULL") == 0) {
256 if (was_empty == 0) {
259 if (seq_node != NULL) {
283 seq_node->
val = NULL;
290 SCLogInfo(
"Including configuration file %s.", value);
291 if (ConfYamlHandleInclude(parent, value) != 0) {
298 if (strcmp(value,
"include") == 0) {
304 if (parent->
val == NULL) {
306 if (parent->
val && strchr(parent->
val,
'_'))
311 if (existing != NULL) {
312 if (!existing->
final) {
313 SCLogInfo(
"Configuration node '%s' redefined.",
322 if (node->
name && strchr(node->
name,
'_')) {
323 if (!(parent->
name &&
324 ((strcmp(parent->
name,
"address-groups") == 0) ||
325 (strcmp(parent->
name,
"port-groups") == 0)))) {
329 "%s is deprecated. Please use %s on line %"PRIuMAX
".",
330 value, node->
name, (uintmax_t)parser->mark.line+1);
334 "parameter name warnings.");
343 if (value != NULL && (
tag != NULL) && (strcmp(
tag,
"!include") == 0)) {
344 SCLogInfo(
"Including configuration file %s at "
345 "parent node %s.", value, node->
name);
346 if (ConfYamlHandleInclude(node, value) != 0)
348 }
else if (!node->
final && value != NULL) {
349 if (node->
val != NULL)
357 else if (event.type == YAML_SEQUENCE_START_EVENT) {
358 SCLogDebug(
"event.type=YAML_SEQUENCE_START_EVENT; state=%d", state);
359 if (ConfYamlParse(parser, node, 1, rlevel) != 0)
364 else if (event.type == YAML_SEQUENCE_END_EVENT) {
365 SCLogDebug(
"event.type=YAML_SEQUENCE_END_EVENT; state=%d", state);
368 else if (event.type == YAML_MAPPING_START_EVENT) {
369 SCLogDebug(
"event.type=YAML_MAPPING_START_EVENT; state=%d", state);
375 if (seq_node != NULL) {
395 if (ConfYamlParse(parser, seq_node, 0, rlevel) != 0)
399 if (ConfYamlParse(parser, node, inseq, rlevel) != 0)
404 else if (event.type == YAML_MAPPING_END_EVENT) {
405 SCLogDebug(
"event.type=YAML_MAPPING_END_EVENT; state=%d", state);
408 else if (event.type == YAML_STREAM_END_EVENT) {
409 SCLogDebug(
"event.type=YAML_STREAM_END_EVENT; state=%d", state);
414 yaml_event_delete(&event);
418 yaml_event_delete(&event);
443 yaml_parser_t parser;
447 if (yaml_parser_initialize(&parser) != 1) {
452 struct stat stat_buf;
453 if (stat(filename, &stat_buf) == 0) {
454 if (stat_buf.st_mode & S_IFDIR) {
456 "Please specify the yaml file in your -c option.", filename);
457 yaml_parser_delete(&parser);
463 infile = fopen(filename,
"r");
464 if (infile == NULL) {
467 yaml_parser_delete(&parser);
471 if (conf_dirname == NULL) {
472 ConfYamlSetConfDirname(filename);
475 yaml_parser_set_input_file(&parser, infile);
476 ret = ConfYamlParse(&parser, root, 0, 0);
477 yaml_parser_delete(&parser);
490 yaml_parser_t parser;
493 if (yaml_parser_initialize(&parser) != 1) {
494 fprintf(stderr,
"Failed to initialize yaml parser.\n");
497 yaml_parser_set_input_string(&parser, (
const unsigned char *)
string,
len);
498 ret = ConfYamlParse(&parser, root, 0, 0);
499 yaml_parser_delete(&parser);
521 yaml_parser_t parser;
525 if (yaml_parser_initialize(&parser) != 1) {
530 struct stat stat_buf;
532 if (stat(filename, &stat_buf) == 0) {
533 if (stat_buf.st_mode & S_IFDIR) {
535 "Please specify the yaml file in your -c option.", filename);
541 infile = fopen(filename,
"r");
542 if (infile == NULL) {
545 yaml_parser_delete(&parser);
549 if (conf_dirname == NULL) {
550 ConfYamlSetConfDirname(filename);
555 ConfSet(prefix,
"<prefix root node>");
559 yaml_parser_delete(&parser);
563 yaml_parser_set_input_file(&parser, infile);
564 ret = ConfYamlParse(&parser, root, 0, 0);
565 yaml_parser_delete(&parser);
574 ConfYamlSequenceTest(
void)
583 default-log-dir: /tmp\n\
600 FAIL_IF(strcmp(filename->
val,
"netbios.rules") != 0);
605 FAIL_IF(strcmp(filename->
val,
"x11.rules") != 0);
618 ConfYamlLoggingOutputTest(
void)
625 - interface: console\n\
627 - interface: syslog\n\
650 FAIL_IF(strcmp(output_param->
name,
"interface") != 0);
651 FAIL_IF(strcmp(output_param->
val,
"console") != 0);
654 FAIL_IF(strcmp(output_param->
name,
"log-level") != 0);
655 FAIL_IF(strcmp(output_param->
val,
"error") != 0);
663 FAIL_IF(strcmp(output_param->
name,
"interface") != 0);
664 FAIL_IF(strcmp(output_param->
val,
"syslog") != 0);
667 FAIL_IF(strcmp(output_param->
name,
"facility") != 0);
668 FAIL_IF(strcmp(output_param->
val,
"local4") != 0);
671 FAIL_IF(strcmp(output_param->
name,
"log-level") != 0);
672 FAIL_IF(strcmp(output_param->
val,
"info") != 0);
684 ConfYamlNonYamlFileTest(
void)
698 ConfYamlBadYamlVersionTest(
void)
705 - interface: console\n\
707 - interface: syslog\n\
724 ConfYamlSecondLevelSequenceTest(
void)
732 address: [\"192.168.1.0/24\"]\n\
733 personality: [\"Apache_2_2\", \"PHP_5_3\"]\n\
734 path-parsing: [\"compress_separators\", \"lowercase\"]\n\
744 - compress_separators\n\
772 FAIL_IF(strcmp(node->
val,
"192.168.1.0/24") != 0);
784 ConfYamlFileIncludeTest(
void)
788 const char config_filename[] =
"ConfYamlFileIncludeTest-config.yaml";
789 const char config_file_contents[] =
792 "# Include something at the root level.\n"
793 "include: ConfYamlFileIncludeTest-include.yaml\n"
794 "# Test including under a mapping.\n"
795 "mapping: !include ConfYamlFileIncludeTest-include.yaml\n";
797 const char include_filename[] =
"ConfYamlFileIncludeTest-include.yaml";
798 const char include_file_contents[] =
809 FAIL_IF_NULL((config_file = fopen(config_filename,
"w")));
810 FAIL_IF(fwrite(config_file_contents, strlen(config_file_contents), 1, config_file) != 1);
813 FAIL_IF_NULL((config_file = fopen(include_filename,
"w")));
814 FAIL_IF(fwrite(include_file_contents, strlen(include_file_contents), 1, config_file) != 1);
818 if (conf_dirname != NULL) {
841 node =
ConfGetNode(
"mapping.unix-command.enabled");
848 unlink(config_filename);
849 unlink(include_filename);
859 ConfYamlOverrideTest(
void)
864 "some-log-dir: /var/log\n"
865 "some-log-dir: /tmp\n"
881 FAIL_IF(strcmp(value,
"/tmp") != 0);
886 FAIL_IF(strcmp(value,
"value") != 0);
899 ConfYamlOverrideFinalTest(
void)
907 "default-log-dir: /var/log\n";
913 const char *default_log_dir;
916 FAIL_IF(strcmp(default_log_dir,
"/tmp") != 0);
924 static int ConfYamlNull(
void)
929 char config[] =
"%YAML 1.1\n"
931 "quoted-tilde: \"~\"\n"
932 "unquoted-tilde: ~\n"
933 "quoted-null: \"null\"\n"
934 "unquoted-null: null\n"
935 "quoted-Null: \"Null\"\n"
936 "unquoted-Null: Null\n"
937 "quoted-NULL: \"NULL\"\n"
938 "unquoted-NULL: NULL\n"
939 "empty-quoted: \"\"\n"
941 "list: [\"null\", null, \"Null\", Null, \"NULL\", NULL, \"~\", ~]\n";
1004 UtRegisterTest(
"ConfYamlLoggingOutputTest", ConfYamlLoggingOutputTest);
1005 UtRegisterTest(
"ConfYamlNonYamlFileTest", ConfYamlNonYamlFileTest);
1006 UtRegisterTest(
"ConfYamlBadYamlVersionTest", ConfYamlBadYamlVersionTest);
1008 ConfYamlSecondLevelSequenceTest);
1009 UtRegisterTest(
"ConfYamlFileIncludeTest", ConfYamlFileIncludeTest);
1011 UtRegisterTest(
"ConfYamlOverrideFinalTest", ConfYamlOverrideFinalTest);