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(
52 yaml_parser_t *parser,
SCConfNode *parent,
int inseq,
int rlevel,
int state);
73 while ((c = strchr(
string,
'_')))
83 ConfYamlSetConfDirname(
const char *filename)
87 ep = strrchr(filename,
'\\');
89 ep = strrchr(filename,
'/');
93 if (conf_dirname == NULL) {
94 FatalError(
"ERROR: Failed to allocate memory while loading configuration.");
99 if (conf_dirname == NULL) {
100 FatalError(
"ERROR: Failed to allocate memory while loading configuration.");
102 conf_dirname[ep - filename] =
'\0';
117 yaml_parser_t parser;
118 char include_filename[PATH_MAX];
122 if (yaml_parser_initialize(&parser) != 1) {
123 SCLogError(
"Failed to initialize YAML parser");
128 strlcpy(include_filename, filename,
sizeof(include_filename));
131 snprintf(include_filename,
sizeof(include_filename),
"%s/%s",
132 conf_dirname, filename);
135 file = fopen(include_filename,
"r");
137 SCLogError(
"Failed to open configuration include file %s: %s", include_filename,
142 yaml_parser_set_input_file(&parser, file);
144 if (ConfYamlParse(&parser, parent, 0, 0, 0) != 0) {
145 SCLogError(
"Failed to include configuration file %s", filename);
152 yaml_parser_delete(&parser);
168 static int ConfYamlParse(
169 yaml_parser_t *parser,
SCConfNode *parent,
int inseq,
int rlevel,
int state)
173 memset(&event, 0,
sizeof(event));
178 int include_count = 0;
181 SCLogError(
"Recursion limit reached while parsing "
182 "configuration file, aborting.");
187 if (!yaml_parser_parse(parser, &event)) {
188 SCLogError(
"Failed to parse configuration file at line %" PRIuMAX
": %s",
189 (uintmax_t)parser->problem_mark.line, parser->problem);
194 if (event.type == YAML_DOCUMENT_START_EVENT) {
195 SCLogDebug(
"event.type=YAML_DOCUMENT_START_EVENT; state=%d", state);
199 yaml_version_directive_t *ver =
200 event.data.document_start.version_directive;
202 SCLogError(
"ERROR: Invalid configuration file.");
203 SCLogError(
"The configuration file must begin with the following two lines: %%YAML "
207 int major = ver->major;
208 int minor = ver->minor;
210 SCLogError(
"ERROR: Invalid YAML version. Must be 1.1");
214 else if (event.type == YAML_SCALAR_EVENT) {
215 char *value = (
char *)event.data.scalar.value;
216 char *
tag = (
char *)
event.data.scalar.tag;
217 SCLogDebug(
"event.type=YAML_SCALAR_EVENT; state=%d; value=%s; "
218 "tag=%s; inseq=%d", state, value,
tag, inseq);
223 if (state ==
CONF_KEY && strlen(value) == 0) {
229 event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE) {
230 if (strlen(value) == 0 || strcmp(value,
"~") == 0 || strcmp(value,
"null") == 0 ||
231 strcmp(value,
"Null") == 0 || strcmp(value,
"NULL") == 0) {
239 SCLogInfo(
"Including configuration file %s.", value);
258 if (was_empty == 0) {
259 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
267 if (seq_node != NULL) {
291 seq_node->
val = NULL;
298 SCLogInfo(
"Including configuration file %s.", value);
306 if (strcmp(value,
"include") == 0) {
308 if (++include_count > 1) {
309 SCLogWarning(
"Multipline \"include\" fields at the same level are "
310 "deprecated and will not work in Suricata 8, please move "
311 "to an array of include files: line: %zu",
318 if (parent->
val == NULL) {
320 if (parent->
val && strchr(parent->
val,
'_'))
325 if (strchr(value,
'.') != NULL) {
333 if (existing != NULL) {
334 if (!existing->
final) {
335 SCLogInfo(
"Configuration node '%s' redefined.", existing->
name);
346 if (node->
name && strchr(node->
name,
'_')) {
347 if (!(parent->
name &&
348 ((strcmp(parent->
name,
"address-groups") == 0) ||
349 (strcmp(parent->
name,
"port-groups") == 0)))) {
353 "%s is deprecated. Please use %s on line %" PRIuMAX
356 (uintmax_t)parser->mark.line + 1);
360 "parameter name warnings.");
370 if (value != NULL && (
tag != NULL) && (strcmp(
tag,
"!include") == 0)) {
371 SCLogInfo(
"Including configuration file %s at "
372 "parent node %s.", value, node->
name);
375 }
else if (!node->
final && value != NULL) {
376 if (node->
val != NULL)
384 else if (event.type == YAML_SEQUENCE_START_EVENT) {
385 SCLogDebug(
"event.type=YAML_SEQUENCE_START_EVENT; state=%d", state);
387 if (ConfYamlParse(parser, state ==
CONF_INCLUDE ? parent : node, 1, rlevel,
393 else if (event.type == YAML_SEQUENCE_END_EVENT) {
394 SCLogDebug(
"event.type=YAML_SEQUENCE_END_EVENT; state=%d", state);
397 else if (event.type == YAML_MAPPING_START_EVENT) {
398 SCLogDebug(
"event.type=YAML_MAPPING_START_EVENT; state=%d", state);
400 SCLogError(
"Include fields cannot be a mapping: line %zu", parser->mark.line);
416 if (was_empty == 0) {
417 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
425 if (seq_node != NULL) {
445 if (ConfYamlParse(parser, seq_node, 0, rlevel, 0) != 0)
449 if (ConfYamlParse(parser, node, inseq, rlevel, 0) != 0)
454 else if (event.type == YAML_MAPPING_END_EVENT) {
455 SCLogDebug(
"event.type=YAML_MAPPING_END_EVENT; state=%d", state);
458 else if (event.type == YAML_STREAM_END_EVENT) {
459 SCLogDebug(
"event.type=YAML_STREAM_END_EVENT; state=%d", state);
464 yaml_event_delete(&event);
468 yaml_event_delete(&event);
492 yaml_parser_t parser;
496 if (yaml_parser_initialize(&parser) != 1) {
497 SCLogError(
"failed to initialize yaml parser.");
501 struct stat stat_buf;
502 if (stat(filename, &stat_buf) == 0) {
503 if (stat_buf.st_mode & S_IFDIR) {
504 SCLogError(
"yaml argument is not a file but a directory: %s. "
505 "Please specify the yaml file in your -c option.",
507 yaml_parser_delete(&parser);
513 infile = fopen(filename,
"r");
514 if (infile == NULL) {
515 SCLogError(
"failed to open file: %s: %s", filename, strerror(errno));
516 yaml_parser_delete(&parser);
520 if (conf_dirname == NULL) {
521 ConfYamlSetConfDirname(filename);
524 yaml_parser_set_input_file(&parser, infile);
525 ret = ConfYamlParse(&parser, root, 0, 0, 0);
526 yaml_parser_delete(&parser);
538 yaml_parser_t parser;
541 if (yaml_parser_initialize(&parser) != 1) {
542 fprintf(stderr,
"Failed to initialize yaml parser.\n");
545 yaml_parser_set_input_string(&parser, (
const unsigned char *)
string,
len);
546 ret = ConfYamlParse(&parser, root, 0, 0, 0);
547 yaml_parser_delete(&parser);
568 yaml_parser_t parser;
572 struct stat stat_buf;
574 if (stat(filename, &stat_buf) == 0) {
575 if (stat_buf.st_mode & S_IFDIR) {
576 SCLogError(
"yaml argument is not a file but a directory: %s. "
577 "Please specify the yaml file in your -c option.",
583 if (yaml_parser_initialize(&parser) != 1) {
584 SCLogError(
"failed to initialize yaml parser.");
589 infile = fopen(filename,
"r");
590 if (infile == NULL) {
591 SCLogError(
"failed to open file: %s: %s", filename, strerror(errno));
592 yaml_parser_delete(&parser);
596 if (conf_dirname == NULL) {
597 ConfYamlSetConfDirname(filename);
606 yaml_parser_delete(&parser);
610 yaml_parser_set_input_file(&parser, infile);
611 ret = ConfYamlParse(&parser, root, 0, 0, 0);
612 yaml_parser_delete(&parser);
621 ConfYamlSequenceTest(
void)
630 default-log-dir: /tmp\n\
647 FAIL_IF(strcmp(filename->
val,
"netbios.rules") != 0);
652 FAIL_IF(strcmp(filename->
val,
"x11.rules") != 0);
665 ConfYamlLoggingOutputTest(
void)
672 - interface: console\n\
674 - interface: syslog\n\
697 FAIL_IF(strcmp(output_param->
name,
"interface") != 0);
698 FAIL_IF(strcmp(output_param->
val,
"console") != 0);
701 FAIL_IF(strcmp(output_param->
name,
"log-level") != 0);
702 FAIL_IF(strcmp(output_param->
val,
"error") != 0);
710 FAIL_IF(strcmp(output_param->
name,
"interface") != 0);
711 FAIL_IF(strcmp(output_param->
val,
"syslog") != 0);
714 FAIL_IF(strcmp(output_param->
name,
"facility") != 0);
715 FAIL_IF(strcmp(output_param->
val,
"local4") != 0);
718 FAIL_IF(strcmp(output_param->
name,
"log-level") != 0);
719 FAIL_IF(strcmp(output_param->
val,
"info") != 0);
731 ConfYamlNonYamlFileTest(
void)
745 ConfYamlBadYamlVersionTest(
void)
752 - interface: console\n\
754 - interface: syslog\n\
771 ConfYamlSecondLevelSequenceTest(
void)
779 address: [\"192.168.1.0/24\"]\n\
780 personality: [\"Apache_2_2\", \"PHP_5_3\"]\n\
781 path-parsing: [\"compress_separators\", \"lowercase\"]\n\
791 - compress_separators\n\
819 FAIL_IF(strcmp(node->
val,
"192.168.1.0/24") != 0);
831 ConfYamlFileIncludeTest(
void)
835 const char config_filename[] =
"ConfYamlFileIncludeTest-config.yaml";
836 const char config_file_contents[] =
839 "# Include something at the root level.\n"
840 "include: ConfYamlFileIncludeTest-include.yaml\n"
841 "# Test including under a mapping.\n"
842 "mapping: !include ConfYamlFileIncludeTest-include.yaml\n";
844 const char include_filename[] =
"ConfYamlFileIncludeTest-include.yaml";
845 const char include_file_contents[] =
856 FAIL_IF_NULL((config_file = fopen(config_filename,
"w")));
857 FAIL_IF(fwrite(config_file_contents, strlen(config_file_contents), 1, config_file) != 1);
860 FAIL_IF_NULL((config_file = fopen(include_filename,
"w")));
861 FAIL_IF(fwrite(include_file_contents, strlen(include_file_contents), 1, config_file) != 1);
865 if (conf_dirname != NULL) {
895 unlink(config_filename);
896 unlink(include_filename);
906 ConfYamlOverrideTest(
void)
908 char config[] =
"%YAML 1.1\n"
910 "some-log-dir: /var/log\n"
911 "some-log-dir: /tmp\n"
921 " HOME_NET: \"[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]\"\n"
922 " EXTERNAL_NET: any\n"
923 "vars.address-groups.HOME_NET: \"10.10.10.10/32\"\n";
931 FAIL_IF(strcmp(value,
"/tmp") != 0);
936 FAIL_IF(strcmp(value,
"value") != 0);
944 SCConfNode *vars_address_groups_external_net =
952 FAIL_IF(strcmp(vars_address_groups_home_net->
val,
"10.10.10.10/32") != 0);
968 ConfYamlOverrideFinalTest(
void)
976 "default-log-dir: /var/log\n";
982 const char *default_log_dir;
985 FAIL_IF(strcmp(default_log_dir,
"/tmp") != 0);
993 static int ConfYamlNull(
void)
998 char config[] =
"%YAML 1.1\n"
1000 "quoted-tilde: \"~\"\n"
1001 "unquoted-tilde: ~\n"
1002 "quoted-null: \"null\"\n"
1003 "unquoted-null: null\n"
1004 "quoted-Null: \"Null\"\n"
1005 "unquoted-Null: Null\n"
1006 "quoted-NULL: \"NULL\"\n"
1007 "unquoted-NULL: NULL\n"
1008 "empty-quoted: \"\"\n"
1009 "empty-unquoted: \n"
1010 "list: [\"null\", null, \"Null\", Null, \"NULL\", NULL, \"~\", ~]\n";
1072 UtRegisterTest(
"ConfYamlLoggingOutputTest", ConfYamlLoggingOutputTest);
1073 UtRegisterTest(
"ConfYamlNonYamlFileTest", ConfYamlNonYamlFileTest);
1074 UtRegisterTest(
"ConfYamlBadYamlVersionTest", ConfYamlBadYamlVersionTest);
1076 ConfYamlSecondLevelSequenceTest);
1077 UtRegisterTest(
"ConfYamlFileIncludeTest", ConfYamlFileIncludeTest);
1079 UtRegisterTest(
"ConfYamlOverrideFinalTest", ConfYamlOverrideFinalTest);