diff --git a/cf-agent/cf-agent.c b/cf-agent/cf-agent.c index 7a7ad905fc..c30c049724 100644 --- a/cf-agent/cf-agent.c +++ b/cf-agent/cf-agent.c @@ -1337,6 +1337,7 @@ static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericA { Log(LOG_LEVEL_VERBOSE, "SET select_end_match_eof %s", (char *) value); EvalContextSetSelectEndMatchEof(ctx, BooleanFromString(value)); + continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_REPORTCLASSLOG].lval) == 0) @@ -1362,6 +1363,27 @@ static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericA { EvalContextSetAgentEvalOrder(ctx, EVAL_ORDER_CLASSIC); } + continue; + } + + if (StringEqual(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_DEFAULT_DIRECTORY_CREATE_MODE].lval)) + { + assert(value_type == CF_DATA_TYPE_STRING); + const char *mode_str = value; + mode_t plus, minus; + if (ParseModeString(mode_str, &plus, &minus)) + { + DEFAULTMODE |= plus; + DEFAULTMODE &= ~minus; + Log(LOG_LEVEL_VERBOSE, "Changed default directory create mode to %ju " + "(default_directory_create_mode => \"%s\")", (uintmax_t) DEFAULTMODE, mode_str); + } + else + { + Log(LOG_LEVEL_ERR, "Failed to parse mode string for overriding default directory create mode " + "(default_directory_create_mode => \"%s\")", mode_str); + } + continue; } } } diff --git a/cf-agent/verify_files_utils.c b/cf-agent/verify_files_utils.c index a743df1fb4..6a195e3e18 100644 --- a/cf-agent/verify_files_utils.c +++ b/cf-agent/verify_files_utils.c @@ -1019,7 +1019,7 @@ static PromiseResult SourceSearchAndCopy(EvalContext *ctx, const char *from, cha if ((!attr->copy.collapse) && (stat(newto, &dsb) == -1)) { - if (mkdir(changes_newto, 0700) == -1) + if (mkdir(changes_newto, DEFAULTMODE) == -1) { RecordInterruption(ctx, pp, attr, "Can't make directory '%s'. (mkdir: %s)", newto, GetErrorStr()); diff --git a/libpromises/cf3.defs.h b/libpromises/cf3.defs.h index cea29e672b..c3e6e87aee 100644 --- a/libpromises/cf3.defs.h +++ b/libpromises/cf3.defs.h @@ -344,8 +344,6 @@ struct GidList_ #define CF_NOINT -678L #define CF_UNDEFINED_ITEM (void *)0x1234 -#define DEFAULTMODE ((mode_t)0700) - #define CF_DONEPASSES 4 #define CFPULSETIME 60 @@ -496,6 +494,7 @@ typedef enum AGENT_CONTROL_SELECT_END_MATCH_EOF, AGENT_CONTROL_COPYFROM_RESTRICT_KEYS, AGENT_CONTROL_EVALUATION_ORDER, + AGENT_CONTROL_DEFAULT_DIRECTORY_CREATE_MODE, AGENT_CONTROL_NONE } AgentControl; diff --git a/libpromises/cf3.extern.h b/libpromises/cf3.extern.h index d8d93f5341..6303b170b9 100644 --- a/libpromises/cf3.extern.h +++ b/libpromises/cf3.extern.h @@ -48,6 +48,8 @@ extern char VFQNAME[CF_MAXVARSIZE]; extern char VDOMAIN[CF_MAXVARSIZE / 2]; extern char VUQNAME[CF_MAXVARSIZE / 2]; +extern mode_t DEFAULTMODE; + typedef enum EvalMode { EVAL_MODE_NORMAL = 0, /* needs to be 'false' to work for DONTDO below */ EVAL_MODE_DRY_RUN = 1, diff --git a/libpromises/cf3globals.c b/libpromises/cf3globals.c index 745cfc50a1..f14f4d39c6 100644 --- a/libpromises/cf3globals.c +++ b/libpromises/cf3globals.c @@ -154,3 +154,10 @@ char BINDINTERFACE[CF_MAXVARSIZE]; /* GLOBAL_P */ - GenericAgentLoadPolicy (ReadPolicyValidatedFile) */ bool MINUSF = false; /* GLOBAL_A */ + +/* + Can be mutated in cf-agent.c (from control body) + + Used as default directory create mode. +*/ +mode_t DEFAULTMODE = (mode_t) 0700; diff --git a/libpromises/mod_common.c b/libpromises/mod_common.c index d017b8cca3..24e9788bce 100644 --- a/libpromises/mod_common.c +++ b/libpromises/mod_common.c @@ -321,6 +321,7 @@ const ConstraintSyntax CFA_CONTROLBODY[] = ConstraintSyntaxNewBool("select_end_match_eof", "Set the default behavior of select_end_match_eof in edit_line promises. Default: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("copyfrom_restrict_keys", ".*", "A list of key hashes to restrict copy_from to", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("evaluation_order", "(classic|top_down)", "Order of evaluation of promises of agent", SYNTAX_STATUS_NORMAL), + ConstraintSyntaxNewString("default_directory_create_mode", ".*", "Default directory create mode (defaults to 0700 if not specified)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; diff --git a/tests/acceptance/10_files/agent_control_default_directory_create_mode.cf b/tests/acceptance/10_files/agent_control_default_directory_create_mode.cf new file mode 100644 index 0000000000..9e79ab2100 --- /dev/null +++ b/tests/acceptance/10_files/agent_control_default_directory_create_mode.cf @@ -0,0 +1,72 @@ +############################################################################## +# +# Test overriding default directory create mode (CFE-4590, ENT-13239). +# +############################################################################## + + +body common control +{ + inputs => { "../default.cf.sub" }; + bundlesequence => { default("$(this.promise_filename)") }; + version => "1.0"; +} + +body agent control { + # Override the default directory create mode to 0755 (it defaults to 0700 if + # not specified) + default_directory_create_mode => "0777"; # Make sure the last one wins + default_directory_create_mode => "a+rx"; # Can also use octets 0755 +} + +############################################################################## + +bundle agent init +{ + methods: + "clean"; +} + +############################################################################## + +bundle agent test +{ + meta: + "description" -> { "CFE-4590", "ENT-13239" } + string => "Test overriding default directory create mode"; + + files: + "$(G.testdir)/foo/config.txt" + create => "true", + perms => m(0655); +} + +############################################################################## + +bundle agent check +{ + vars: + "expected" + string => "[0-9]*755", + comment => "We only care about the last three octets (i.e., 755)"; + "actual" + string => filestat("$(G.testdir)/foo/", "modeoct"); + + methods: + "Pass/FAIL" + usebundle => dcs_check_regcmp("$(expected)", "$(actual)", + "$(this.promise_filename)", "false"); + + reports: + "Expected $(expected), actual $(actual)"; +} + +############################################################################## + +bundle agent clean +{ + files: + "$(G.testdir)/foo/." + delete => tidy, + if => fileexist("$(this.promiser)"); +}