static void test_policy_json_to_from(void) { EvalContext *ctx = EvalContextNew(); Policy *policy = NULL; { Policy *original = LoadPolicy("benchmark.cf"); JsonElement *json = PolicyToJson(original); PolicyDestroy(original); policy = PolicyFromJson(json); JsonDestroy(json); } assert_true(policy); assert_int_equal(1, SeqLength(policy->bundles)); assert_int_equal(2, SeqLength(policy->bodies)); { Bundle *main_bundle = PolicyGetBundle(policy, NULL, "agent", "main"); assert_true(main_bundle); { { PromiseType *files = BundleGetPromiseType(main_bundle, "files"); assert_true(files); assert_int_equal(1, SeqLength(files->promises)); for (size_t i = 0; i < SeqLength(files->promises); i++) { Promise *promise = SeqAt(files->promises, i); if (strcmp("/tmp/stuff", promise->promiser) == 0) { assert_string_equal("any", promise->classes); assert_int_equal(2, SeqLength(promise->conlist)); { Constraint *create = PromiseGetConstraint(ctx, promise, "create"); assert_true(create); assert_string_equal("create", create->lval); assert_string_equal("true", RvalScalarValue(create->rval)); } { Constraint *create = PromiseGetConstraint(ctx, promise, "perms"); assert_true(create); assert_string_equal("perms", create->lval); assert_string_equal("myperms", RvalScalarValue(create->rval)); } } else { fprintf(stderr, "Found unknown promise"); fail(); } } } { const char* reportOutput[2] = { "Hello, CFEngine", "Hello, world" }; const char* reportClass[2] = { "cfengine", "any" }; PromiseType *reports = BundleGetPromiseType(main_bundle, "reports"); assert_true(reports); assert_int_equal(2, SeqLength(reports->promises)); for (size_t i = 0; i < SeqLength(reports->promises); i++) { Promise *promise = SeqAt(reports->promises, i); if (strcmp(reportOutput[i], promise->promiser) == 0) { assert_string_equal(reportClass[i], promise->classes); assert_int_equal(1, SeqLength(promise->conlist)); { Constraint *friend_pattern = SeqAt(promise->conlist, 0); assert_true(friend_pattern); assert_string_equal("friend_pattern", friend_pattern->lval); assert_int_equal(RVAL_TYPE_FNCALL, friend_pattern->rval.type); FnCall *fn = RvalFnCallValue(friend_pattern->rval); assert_string_equal("hash", fn->name); assert_int_equal(2, RlistLen(fn->args)); } } else { fprintf(stderr, "Found unknown promise"); fail(); } } } } } { Body *myperms = PolicyGetBody(policy, NULL, "perms", "myperms"); assert_true(myperms); { Seq *mode_cps = BodyGetConstraint(myperms, "mode"); assert_int_equal(1, SeqLength(mode_cps)); Constraint *mode = SeqAt(mode_cps, 0); assert_string_equal("mode", mode->lval); assert_string_equal("555", RvalScalarValue(mode->rval)); } } PolicyDestroy(policy); EvalContextDestroy(ctx); }
/* * The difference between filename and input_input file is that the latter is the file specified by -f or * equivalently the file containing body common control. This will hopefully be squashed in later refactoring. */ static Policy *Cf3ParseFile(const GenericAgentConfig *config, const char *input_path) { struct stat statbuf; if (stat(input_path, &statbuf) == -1) { if (config->ignore_missing_inputs) { return PolicyNew(); } Log(LOG_LEVEL_ERR, "Can't stat file '%s' for parsing. (stat: %s)", input_path, GetErrorStr()); exit(1); } #ifndef _WIN32 if (config->check_not_writable_by_others && (statbuf.st_mode & (S_IWGRP | S_IWOTH))) { Log(LOG_LEVEL_ERR, "File %s (owner %ju) is writable by others (security exception)", input_path, (uintmax_t)statbuf.st_uid); exit(1); } #endif Log(LOG_LEVEL_VERBOSE, "Parsing file '%s'", input_path); if (!FileCanOpen(input_path, "r")) { Log(LOG_LEVEL_ERR, "Can't open file '%s' for parsing", input_path); exit(1); } Policy *policy = NULL; if (StringEndsWith(input_path, ".json")) { char *contents = NULL; if (FileReadMax(&contents, input_path, SIZE_MAX) == -1) { Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", input_path); return NULL; } JsonElement *json_policy = NULL; const char *data = contents; // TODO: need to fix JSON parser signature, just silly if (JsonParse(&data, &json_policy) != JSON_PARSE_OK) { Log(LOG_LEVEL_ERR, "Error parsing JSON input file '%s'", input_path); free(contents); return NULL; } policy = PolicyFromJson(json_policy); JsonDestroy(json_policy); free(contents); } else { if (config->agent_type == AGENT_TYPE_COMMON) { policy = ParserParseFile(input_path, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error); } else { policy = ParserParseFile(input_path, 0, 0); } } return policy; }
/* * The difference between filename and input_input file is that the latter is the file specified by -f or * equivalently the file containing body common control. This will hopefully be squashed in later refactoring. */ Policy *Cf3ParseFile(const GenericAgentConfig *config, const char *input_path) { struct stat statbuf; if (stat(input_path, &statbuf) == -1) { if (config->ignore_missing_inputs) { return PolicyNew(); } Log(LOG_LEVEL_ERR, "Can't stat file '%s' for parsing. (stat: %s)", input_path, GetErrorStr()); exit(EXIT_FAILURE); } else if (S_ISDIR(statbuf.st_mode)) { if (config->ignore_missing_inputs) { return PolicyNew(); } Log(LOG_LEVEL_ERR, "Can't parse directory '%s'.", input_path); exit(EXIT_FAILURE); } #ifndef _WIN32 if (config->check_not_writable_by_others && (statbuf.st_mode & (S_IWGRP | S_IWOTH))) { Log(LOG_LEVEL_ERR, "File %s (owner %ju) is writable by others (security exception)", input_path, (uintmax_t)statbuf.st_uid); exit(EXIT_FAILURE); } #endif Log(LOG_LEVEL_VERBOSE, "BEGIN parsing file: %s", input_path); if (!FileCanOpen(input_path, "r")) { Log(LOG_LEVEL_ERR, "Can't open file '%s' for parsing", input_path); exit(EXIT_FAILURE); } Policy *policy = NULL; if (StringEndsWith(input_path, ".json")) { Writer *contents = FileRead(input_path, SIZE_MAX, NULL); if (!contents) { Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", input_path); return NULL; } JsonElement *json_policy = NULL; const char *data = StringWriterData(contents); if (JsonParse(&data, &json_policy) != JSON_PARSE_OK) { Log(LOG_LEVEL_ERR, "Error parsing JSON input file '%s'", input_path); WriterClose(contents); return NULL; } policy = PolicyFromJson(json_policy); JsonDestroy(json_policy); WriterClose(contents); } else { if (config->agent_type == AGENT_TYPE_COMMON) { policy = ParserParseFile(config->agent_type, input_path, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error); } else { policy = ParserParseFile(config->agent_type, input_path, 0, 0); } } Log(LOG_LEVEL_VERBOSE, "END parsing file: %s", input_path); return policy; }