Skip to content

Commit de36237

Browse files
authored
Merge pull request #5756 from victormlg/useringroup
ENT-12721: Added a new policy function useringroup
2 parents 0279d91 + 2c053cd commit de36237

File tree

4 files changed

+107
-5
lines changed

4 files changed

+107
-5
lines changed

examples/useringroup.cf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#+begin_src cfengine3
2+
body common control
3+
{
4+
bundlesequence => { "example" };
5+
}
6+
bundle agent example
7+
{
8+
classes:
9+
"root_in_root" expression => useringroup("root", "root");
10+
11+
reports:
12+
root_in_root::
13+
"root is indeed in the root group";
14+
!root_in_root::
15+
"something went wrong";
16+
}
17+
#+end_src
18+
#############################################################################
19+
#+begin_src example_output
20+
#@ ```
21+
#@ R: root is indeed in the root group
22+
#@ ```
23+
#+end_src

libpromises/cf3.defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@
7373
#define SECONDS_PER_WEEK (7 * SECONDS_PER_DAY)
7474
#define SECONDS_PER_YEAR (365 * SECONDS_PER_DAY)
7575

76+
/* Max size of the 'passwd' string in the getpwuid_r() function,
77+
* man:getpwuid_r(3) says that this value "Should be more than enough". */
78+
#define GETPW_R_SIZE_MAX 16384
79+
#define GETGR_R_SIZE_MAX 16384 /* same for group name */
80+
7681
/* Long-term monitoring constants */
7782

7883
#define HOURS_PER_SHIFT 6

libpromises/evalfunction.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,75 @@ static FnCallResult FnCallGetGid(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const P
13671367
#endif
13681368
}
13691369

1370+
/*********************************************************************/
1371+
1372+
static FnCallResult no_entry(int ret, const FnCall *fp, const char *group_name, bool is_user_db)
1373+
{
1374+
assert(fp != NULL);
1375+
1376+
const char *entry_type = is_user_db ? "user" : "group";
1377+
const char *db_type = is_user_db ? "passwd" : "group";
1378+
if (ret == 0 || ret == ENOENT || ret == ESRCH || ret == EBADF || ret == EPERM)
1379+
{
1380+
Log(LOG_LEVEL_DEBUG, "Couldn't find %s '%s' in %s database", entry_type, group_name, db_type);
1381+
return FnReturnContext(false);
1382+
}
1383+
const char *const error_msg = GetErrorStrFromCode(ret);
1384+
Log(LOG_LEVEL_ERR, "Couldn't open %s database in function '%s': %s", db_type, fp->name, error_msg);
1385+
return FnFailure();
1386+
}
1387+
1388+
static FnCallResult FnCallUserInGroup(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs)
1389+
{
1390+
assert(fp != NULL);
1391+
assert(finalargs != NULL);
1392+
#ifdef _WIN32
1393+
Log(LOG_LEVEL_ERR, "Function '%s' is POSIX specific", fp->name);
1394+
return FnFailure();
1395+
#else
1396+
1397+
const char *user_name = RlistScalarValue(finalargs);
1398+
const char *group_name = RlistScalarValue(finalargs->next);
1399+
assert(group_name != NULL); // Guaranteed by parser
1400+
1401+
int ret;
1402+
1403+
// Check secondary group. This is what we expect the user to check for, thus it comes first.
1404+
struct group grp;
1405+
struct group *grent;
1406+
char gr_buf[GETGR_R_SIZE_MAX] = {0};
1407+
ret = getgrnam_r(group_name, &grp, gr_buf, GETGR_R_SIZE_MAX, &grent);
1408+
1409+
if (grent == NULL)
1410+
{
1411+
// Group does not exist at all, so cannot be
1412+
// primary or secondary group of user
1413+
return no_entry(ret, fp, group_name, false);
1414+
}
1415+
while (grent->gr_mem[0] != NULL)
1416+
{
1417+
if (StringEqual(grent->gr_mem[0], user_name))
1418+
{
1419+
return FnReturnContext(true);
1420+
}
1421+
grent->gr_mem++;
1422+
}
1423+
1424+
// Check primary group
1425+
struct passwd pwd;
1426+
struct passwd *pwent;
1427+
char pw_buf[GETPW_R_SIZE_MAX] = {0};
1428+
ret = getpwnam_r(user_name, &pwd, pw_buf, GETPW_R_SIZE_MAX, &pwent);
1429+
1430+
if (pwent == NULL)
1431+
{
1432+
return no_entry(ret, fp, user_name, true);
1433+
}
1434+
return FnReturnContext(grent->gr_gid == pwent->pw_gid);
1435+
1436+
#endif
1437+
}
1438+
13701439
/*********************************************************************/
13711440

13721441
static FnCallResult FnCallHandlerHash(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs)
@@ -9885,6 +9954,13 @@ static const FnCallArg GETUID_ARGS[] =
98859954
{NULL, CF_DATA_TYPE_NONE, NULL}
98869955
};
98879956

9957+
static const FnCallArg USERINGROUP_ARGS[] =
9958+
{
9959+
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "User name"},
9960+
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "Group name"},
9961+
{NULL, CF_DATA_TYPE_NONE, NULL}
9962+
};
9963+
98889964
static const FnCallArg GETUSERINFO_ARGS[] =
98899965
{
98909966
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "User name in text"},
@@ -10936,7 +11012,9 @@ const FnCallType CF_FNCALL_TYPES[] =
1093611012
FnCallTypeNew("randomint", CF_DATA_TYPE_INT, RANDOMINT_ARGS, &FnCallRandomInt, "Generate a random integer between the given limits, excluding the upper",
1093711013
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
1093811014
FnCallTypeNew("hash_to_int", CF_DATA_TYPE_INT, HASH_TO_INT_ARGS, &FnCallHashToInt, "Generate an integer in given range based on string hash",
10939-
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
11015+
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
11016+
FnCallTypeNew("useringroup", CF_DATA_TYPE_CONTEXT, USERINGROUP_ARGS, &FnCallUserInGroup, "Checks whether a user is in a group",
11017+
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
1094011018

1094111019
FnCallTypeNew("string", CF_DATA_TYPE_STRING, STRING_ARGS, &FnCallString, "Convert argument to string",
1094211020
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),

libpromises/unix.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333

3434
#ifndef __MINGW32__
3535

36-
/* Max size of the 'passwd' string in the getpwuid_r() function,
37-
* man:getpwuid_r(3) says that this value "Should be more than enough". */
38-
#define GETPW_R_SIZE_MAX 16384
39-
#define GETGR_R_SIZE_MAX 16384 /* same for group name */
4036

4137
static bool IsProcessRunning(pid_t pid);
4238

0 commit comments

Comments
 (0)