Skip to content

Commit ff09a71

Browse files
authored
Merge pull request #5966 from larsewi/users
ENT-13535: Users management commands are no longer run in a shell
2 parents 42b2f68 + 497bc58 commit ff09a71

File tree

2 files changed

+83
-14
lines changed

2 files changed

+83
-14
lines changed

cf-agent/verify_users_pam.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static bool ChangePasswordHashUsingChpasswd(const char *puser, const char *passw
413413
int status;
414414
const char *cmd_str = CHPASSWD " -e";
415415
Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s'. (command: '%s')", puser, cmd_str);
416-
FILE *cmd = cf_popen_sh(cmd_str, "w");
416+
FILE *cmd = cf_popen(cmd_str, "w", true);
417417
if (!cmd)
418418
{
419419
Log(LOG_LEVEL_ERR, "Could not launch password changing command '%s': %s.", cmd_str, GetErrorStr());
@@ -645,12 +645,20 @@ static bool ExecuteUserCommand(const char *puser, const char *cmd, size_t sizeof
645645

646646
Log(LOG_LEVEL_VERBOSE, "%s user '%s'. (command: '%s')", cap_action_msg, puser, cmd);
647647

648-
int status = system(cmd);
649-
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
648+
FILE *fptr = cf_popen(cmd, "w", true);
649+
if (!fptr)
650650
{
651651
Log(LOG_LEVEL_ERR, "Command returned error while %s user '%s'. (Command line: '%s')", action_msg, puser, cmd);
652652
return false;
653653
}
654+
655+
int status = cf_pclose(fptr);
656+
if (status)
657+
{
658+
Log(LOG_LEVEL_ERR, "'%s' returned non-zero status: %i\n", cmd, status);
659+
return false;
660+
}
661+
654662
return true;
655663
}
656664

@@ -993,13 +1001,13 @@ static bool EqualGid(const char *key, const struct group *entry)
9931001
{
9941002
assert(entry != NULL);
9951003

996-
unsigned long gid;
1004+
unsigned long gid;
9971005
int ret = StringToUlong(key, &gid);
9981006
if (ret != 0)
9991007
{
10001008
LogStringToLongError(key, "EqualGid", ret);
10011009
return false;
1002-
}
1010+
}
10031011

10041012
return (gid == entry->gr_gid);
10051013
}
@@ -1146,16 +1154,16 @@ static void TransformGidsToGroups(StringSet **list)
11461154
StringSetDestroy(old_list);
11471155
}
11481156

1149-
static bool VerifyIfUserNeedsModifs(const char *puser, const User *u,
1157+
static bool VerifyIfUserNeedsModifs(const char *puser, const User *u,
11501158
const struct passwd *passwd_info,
1151-
uint32_t *changemap,
1152-
StringSet *groups_to_set,
1159+
uint32_t *changemap,
1160+
StringSet *groups_to_set,
11531161
StringSet *current_secondary_groups)
11541162
{
11551163
assert(u != NULL);
11561164
assert(passwd_info != NULL);
11571165

1158-
if (u->description != NULL &&
1166+
if (u->description != NULL &&
11591167
!StringEqual(u->description, passwd_info->pw_gecos))
11601168
{
11611169
CFUSR_SETBIT(*changemap, i_comment);
@@ -1205,17 +1213,17 @@ static bool VerifyIfUserNeedsModifs(const char *puser, const User *u,
12051213

12061214
if (SafeStringLength(u->group_primary) != 0)
12071215
{
1208-
bool group_could_be_gid = (strlen(u->group_primary) ==
1216+
bool group_could_be_gid = (strlen(u->group_primary) ==
12091217
strspn(u->group_primary, "0123456789"));
12101218

12111219
// We try name first, even if it looks like a gid. Only fall back to gid.
12121220
errno = 0;
1213-
struct group *group_info = GetGrEntry(u->group_primary,
1221+
struct group *group_info = GetGrEntry(u->group_primary,
12141222
&EqualGroupName);
12151223
if (group_info == NULL && errno != 0)
12161224
{
1217-
Log(LOG_LEVEL_ERR,
1218-
"Could not obtain information about group '%s': %s",
1225+
Log(LOG_LEVEL_ERR,
1226+
"Could not obtain information about group '%s': %s",
12191227
u->group_primary, GetErrorStr());
12201228
CFUSR_SETBIT(*changemap, i_group);
12211229
}
@@ -1227,7 +1235,7 @@ static bool VerifyIfUserNeedsModifs(const char *puser, const User *u,
12271235
int ret = StringToUlong(u->group_primary, &gid);
12281236
if (ret != 0)
12291237
{
1230-
LogStringToLongError(u->group_primary,
1238+
LogStringToLongError(u->group_primary,
12311239
"VerifyIfUserNeedsModifs", ret);
12321240
CFUSR_SETBIT(*changemap, i_group);
12331241
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
##############################################################################
2+
#
3+
# See ticket ENT-13535 for info.
4+
#
5+
##############################################################################
6+
7+
body common control
8+
{
9+
bundlesequence => { "init", "test", "check", "clean" };
10+
}
11+
12+
body delete tidy
13+
{
14+
dirlinks => "delete";
15+
rmdirs => "true";
16+
}
17+
18+
##############################################################################
19+
20+
bundle agent init
21+
{
22+
users:
23+
"test_user"
24+
policy => "absent";
25+
26+
files:
27+
"/tmp/some-random-file.txt"
28+
delete => tidy;
29+
}
30+
31+
##############################################################################
32+
33+
bundle agent test
34+
{
35+
meta:
36+
"description" -> { "ENT-13535" }
37+
string => "See ticket ENT-13535 for info";
38+
"test_skip_unsupported"
39+
string => "windows",
40+
comment => "Not applicable for Windows since it uses a C API";
41+
42+
users:
43+
linux::
44+
"test_user; echo 'Hello CFEngine' > /tmp/some-random-file.txt"
45+
policy => "present";
46+
}
47+
48+
##############################################################################
49+
50+
bundle agent check
51+
{
52+
reports:
53+
"$(this.promise_filename) $(with)"
54+
with => ifelse(fileexists("/tmp/some-random-file.txt"), "FAIL", "Pass");
55+
}
56+
57+
bundle agent clean
58+
{
59+
methods:
60+
"init";
61+
}

0 commit comments

Comments
 (0)