Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SSSD tests: User switching
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : /* Yes, a .c file. We need to call static functions during the test */
24 : #include "../../../src/util/become_user.c"
25 :
26 : #include <popt.h>
27 : #include "util/util.h"
28 : #include "tests/cmocka/common_mock.h"
29 :
30 1 : void test_become_user(void **state)
31 : {
32 : struct passwd *sssd;
33 : errno_t ret;
34 : pid_t pid, wpid;
35 : int status;
36 :
37 : /* Must root as root, real or fake */
38 1 : assert_int_equal(geteuid(), 0);
39 :
40 1 : sssd = getpwnam("sssd");
41 1 : assert_non_null(sssd);
42 :
43 1 : pid = fork();
44 2 : if (pid == 0) {
45 : /* Change the UID in a child */
46 1 : ret = become_user(sssd->pw_uid, sssd->pw_gid);
47 1 : assert_int_equal(ret, EOK);
48 :
49 : /* Make sure we have the requested UID and GID now and there
50 : * are no supplementary groups
51 : */
52 1 : assert_int_equal(geteuid(), sssd->pw_uid);
53 1 : assert_int_equal(getegid(), sssd->pw_gid);
54 1 : assert_int_equal(getuid(), sssd->pw_uid);
55 1 : assert_int_equal(getgid(), sssd->pw_gid);
56 :
57 : /* Another become_user is a no-op */
58 1 : ret = become_user(sssd->pw_uid, sssd->pw_gid);
59 1 : assert_int_equal(ret, EOK);
60 :
61 1 : assert_int_equal(getgroups(0, NULL), 0);
62 1 : exit(0);
63 : }
64 :
65 1 : assert_int_not_equal(pid, -1);
66 :
67 1 : wpid = waitpid(pid, &status, 0);
68 1 : assert_int_equal(wpid, pid);
69 1 : assert_true(WIFEXITED(status));
70 1 : assert_int_equal(WEXITSTATUS(status), 0);
71 1 : }
72 :
73 1 : void test_switch_user(void **state)
74 : {
75 : errno_t ret;
76 : struct passwd *sssd;
77 : TALLOC_CTX *tmp_ctx;
78 : struct sss_creds *saved_creds;
79 1 : struct sss_creds *saved_creds2 = NULL;
80 :
81 1 : check_leaks_push(global_talloc_context);
82 1 : tmp_ctx = talloc_new(global_talloc_context);
83 1 : assert_non_null(tmp_ctx);
84 :
85 : /* Must root as root, real or fake */
86 1 : assert_int_equal(geteuid(), 0);
87 :
88 1 : sssd = getpwnam("sssd");
89 1 : assert_non_null(sssd);
90 :
91 1 : check_leaks_push(tmp_ctx);
92 :
93 1 : ret = switch_creds(tmp_ctx, sssd->pw_uid, sssd->pw_gid,
94 : 0, NULL, &saved_creds);
95 1 : assert_int_equal(ret, EOK);
96 1 : assert_int_equal(geteuid(), sssd->pw_uid);
97 1 : assert_int_equal(getegid(), sssd->pw_gid);
98 : /* Only effective UID is changed.. */
99 1 : assert_int_equal(getuid(), 0);
100 1 : assert_int_equal(getgid(), 0);
101 :
102 1 : assert_non_null(saved_creds);
103 1 : assert_int_equal(saved_creds->uid, 0);
104 1 : assert_int_equal(saved_creds->gid, 0);
105 :
106 : /* Attempt to restore creds again */
107 1 : ret = switch_creds(tmp_ctx, sssd->pw_uid, sssd->pw_gid,
108 : 0, NULL, &saved_creds2);
109 1 : assert_int_equal(ret, EOK);
110 1 : assert_null(saved_creds2);
111 :
112 : /* restore root */
113 1 : ret = restore_creds(saved_creds);
114 1 : assert_int_equal(ret, EOK);
115 1 : assert_int_equal(geteuid(), 0);
116 1 : assert_int_equal(getegid(), 0);
117 1 : assert_int_equal(getuid(), 0);
118 1 : assert_int_equal(getgid(), 0);
119 :
120 1 : talloc_free(saved_creds);
121 1 : check_leaks_pop(tmp_ctx);
122 1 : talloc_free(tmp_ctx);
123 1 : check_leaks_pop(global_talloc_context);
124 1 : }
125 :
126 1 : int main(int argc, const char *argv[])
127 : {
128 : poptContext pc;
129 : int opt;
130 6 : struct poptOption long_options[] = {
131 : POPT_AUTOHELP
132 5 : SSSD_DEBUG_OPTS
133 : POPT_TABLEEND
134 : };
135 :
136 1 : const struct CMUnitTest tests[] = {
137 : cmocka_unit_test(test_become_user),
138 : cmocka_unit_test(test_switch_user),
139 : };
140 :
141 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
142 1 : debug_level = SSSDBG_INVALID;
143 :
144 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
145 1 : while((opt = poptGetNextOpt(pc)) != -1) {
146 : switch(opt) {
147 : default:
148 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
149 : poptBadOption(pc, 0), poptStrerror(opt));
150 0 : poptPrintUsage(pc, stderr, 0);
151 0 : return 1;
152 : }
153 : }
154 1 : poptFreeContext(pc);
155 :
156 1 : DEBUG_CLI_INIT(debug_level);
157 :
158 : /* Even though normally the tests should clean up after themselves
159 : * they might not after a failed run. Remove the old db to be sure */
160 1 : tests_set_cwd();
161 :
162 1 : return cmocka_run_group_tests(tests, NULL, NULL);
163 : }
|