xref: /xnu-11215/tests/drop_priv.c (revision e7776783)
1 #include <darwintest.h>
2 
3 #include <TargetConditionals.h>
4 #include <limits.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/errno.h>
9 #include <unistd.h>
10 
11 #if !TARGET_OS_OSX
12 #include <pwd.h>
13 #include <sys/types.h>
14 #include <uuid/uuid.h>
15 #endif
16 
17 #include "drop_priv.h"
18 
19 #if TARGET_OS_OSX
20 #define INVOKER_UID "SUDO_UID"
21 #define INVOKER_GID "SUDO_GID"
22 #define ID_MAX (unsigned long)UINT_MAX
23 static unsigned
_get_sudo_invoker(const char * var)24 _get_sudo_invoker(const char *var)
25 {
26 	char *value_str = getenv(var);
27 	T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(value_str,
28 	    "Not running under sudo, getenv(\"%s\") failed", var);
29 	T_QUIET; T_ASSERT_NE_CHAR(*value_str, '\0',
30 	    "getenv(\"%s\") returned an empty string", var);
31 
32 	char *endp;
33 	unsigned long value = strtoul(value_str, &endp, 10);
34 	T_QUIET; T_WITH_ERRNO; T_ASSERT_EQ_CHAR(*endp, '\0',
35 	    "strtoul(\"%s\") not called on a valid number", value_str);
36 	T_QUIET; T_WITH_ERRNO; T_ASSERT_NE_ULONG(value, ULONG_MAX,
37 	    "strtoul(\"%s\") overflow", value_str);
38 
39 	T_QUIET; T_ASSERT_NE_ULONG(value, 0ul, "%s invalid", var);
40 	T_QUIET; T_ASSERT_LT_ULONG(value, ID_MAX, "%s invalid", var);
41 	return (unsigned)value;
42 }
43 #endif /* TARGET_OS_OSX */
44 
45 void
drop_priv(void)46 drop_priv(void)
47 {
48 #if TARGET_OS_OSX
49 	uid_t lower_uid = _get_sudo_invoker(INVOKER_UID);
50 	gid_t lower_gid = _get_sudo_invoker(INVOKER_GID);
51 #else
52 	struct passwd *pw = getpwnam("mobile");
53 	T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(pw, "getpwnam(\"mobile\")");
54 	uid_t lower_uid = pw->pw_uid;
55 	gid_t lower_gid = pw->pw_gid;
56 #endif
57 	T_ASSERT_POSIX_SUCCESS(setgid(lower_gid), "Change group to %u", lower_gid);
58 	T_ASSERT_POSIX_SUCCESS(setuid(lower_uid), "Change user to %u", lower_uid);
59 }
60 
61 bool
running_as_root(void)62 running_as_root(void)
63 {
64 	return geteuid() == 0;
65 }
66