Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | #include "includes.h" | - |
16 | | - |
17 | #include <errno.h> | - |
18 | #include <pwd.h> | - |
19 | #include <string.h> | - |
20 | #include <unistd.h> | - |
21 | #include <limits.h> | - |
22 | #include <stdarg.h> | - |
23 | #include <stdlib.h> | - |
24 | | - |
25 | #include <grp.h> | - |
26 | | - |
27 | #include "log.h" | - |
28 | #include "uidswap.h" | - |
29 | #include "xmalloc.h" | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | | - |
35 | | - |
36 | | - |
37 | | - |
38 | | - |
39 | | - |
40 | #if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) | - |
41 | | - |
42 | | - |
43 | #define SAVED_IDS_WORK_WITH_SETEUID | - |
44 | | - |
45 | static uid_t saved_euid = 0; | - |
46 | static gid_t saved_egid = 0; | - |
47 | #endif | - |
48 | | - |
49 | | - |
50 | static int privileged = 0; | - |
51 | static int temporarily_use_uid_effective = 0; | - |
52 | static uid_t user_groups_uid; | - |
53 | static gid_t *saved_egroups = NULL, *user_groups = NULL; | - |
54 | static int saved_egroupslen = -1, user_groupslen = -1; | - |
55 | | - |
56 | | - |
57 | | - |
58 | | - |
59 | | - |
60 | void | - |
61 | temporarily_use_uid(struct passwd *pw) | - |
62 | { | - |
63 | | - |
64 | #ifdef SAVED_IDS_WORK_WITH_SETEUID | - |
65 | saved_euid = geteuid(); | - |
66 | saved_egid = getegid(); | - |
67 | debug("temporarily_use_uid: %u/%u (e=%u/%u)", | - |
68 | (u_int)pw->pw_uid, (u_int)pw->pw_gid, | - |
69 | (u_int)saved_euid, (u_int)saved_egid); | - |
70 | #ifndef HAVE_CYGWIN | - |
71 | if (saved_euid != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
72 | privileged = 0; | - |
73 | return; never executed: return; | 0 |
74 | } | - |
75 | #endif | - |
76 | #else | - |
77 | if (geteuid() != 0) { | - |
78 | privileged = 0; | - |
79 | return; | - |
80 | } | - |
81 | #endif /* SAVED_IDS_WORK_WITH_SETEUID */ | - |
82 | | - |
83 | privileged = 1; | - |
84 | temporarily_use_uid_effective = 1; | - |
85 | | - |
86 | saved_egroupslen = getgroups(0, NULL); | - |
87 | if (saved_egroupslen < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
88 | fatal("getgroups: %.100s", strerror(errno)); never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
89 | if (saved_egroupslen > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
90 | saved_egroups = xreallocarray(saved_egroups, | - |
91 | saved_egroupslen, sizeof(gid_t)); | - |
92 | if (getgroups(saved_egroupslen, saved_egroups) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
93 | fatal("getgroups: %.100s", strerror(errno)); never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
94 | } else { never executed: end of block | 0 |
95 | free(saved_egroups); | - |
96 | saved_egroups = NULL; | - |
97 | } never executed: end of block | 0 |
98 | | - |
99 | | - |
100 | if (user_groupslen == -1 || user_groups_uid != pw->pw_uid) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
101 | if (initgroups(pw->pw_name, pw->pw_gid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
102 | fatal("initgroups: %s: %.100s", pw->pw_name, never executed: fatal("initgroups: %s: %.100s", pw->pw_name, strerror( (*__errno_location ()) )); | 0 |
103 | strerror(errno)); never executed: fatal("initgroups: %s: %.100s", pw->pw_name, strerror( (*__errno_location ()) )); | 0 |
104 | | - |
105 | user_groupslen = getgroups(0, NULL); | - |
106 | if (user_groupslen < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
107 | fatal("getgroups: %.100s", strerror(errno)); never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
108 | if (user_groupslen > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
109 | user_groups = xreallocarray(user_groups, | - |
110 | user_groupslen, sizeof(gid_t)); | - |
111 | if (getgroups(user_groupslen, user_groups) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
112 | fatal("getgroups: %.100s", strerror(errno)); never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
113 | } else { never executed: end of block | 0 |
114 | free(user_groups); | - |
115 | user_groups = NULL; | - |
116 | } never executed: end of block | 0 |
117 | user_groups_uid = pw->pw_uid; | - |
118 | } never executed: end of block | 0 |
119 | | - |
120 | if (setgroups(user_groupslen, user_groups) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
121 | fatal("setgroups: %.100s", strerror(errno)); never executed: fatal("setgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
122 | #ifndef SAVED_IDS_WORK_WITH_SETEUID | - |
123 | | - |
124 | if (setgid(getegid()) < 0) | - |
125 | debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno)); | - |
126 | | - |
127 | if (setuid(geteuid()) < 0) | - |
128 | debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); | - |
129 | #endif /* SAVED_IDS_WORK_WITH_SETEUID */ | - |
130 | if (setegid(pw->pw_gid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
131 | fatal("setegid %u: %.100s", (u_int)pw->pw_gid, never executed: fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror( (*__errno_location ()) )); | 0 |
132 | strerror(errno)); never executed: fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror( (*__errno_location ()) )); | 0 |
133 | if (seteuid(pw->pw_uid) == -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
134 | fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, never executed: fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror( (*__errno_location ()) )); | 0 |
135 | strerror(errno)); never executed: fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror( (*__errno_location ()) )); | 0 |
136 | } never executed: end of block | 0 |
137 | | - |
138 | | - |
139 | | - |
140 | | - |
141 | void | - |
142 | restore_uid(void) | - |
143 | { | - |
144 | | - |
145 | if (!privileged) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
146 | debug("restore_uid: (unprivileged)"); | - |
147 | return; never executed: return; | 0 |
148 | } | - |
149 | if (!temporarily_use_uid_effective)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
150 | fatal("restore_uid: temporarily_use_uid not effective"); never executed: fatal("restore_uid: temporarily_use_uid not effective"); | 0 |
151 | | - |
152 | #ifdef SAVED_IDS_WORK_WITH_SETEUID | - |
153 | debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid); | - |
154 | | - |
155 | if (seteuid(saved_euid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
156 | fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); never executed: fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror( (*__errno_location ()) )); | 0 |
157 | if (setegid(saved_egid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
158 | fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno)); never executed: fatal("setegid %u: %.100s", (u_int)saved_egid, strerror( (*__errno_location ()) )); | 0 |
159 | #else /* SAVED_IDS_WORK_WITH_SETEUID */ | - |
160 | | - |
161 | | - |
162 | | - |
163 | | - |
164 | | - |
165 | setuid(getuid()); | - |
166 | setgid(getgid()); | - |
167 | #endif /* SAVED_IDS_WORK_WITH_SETEUID */ | - |
168 | | - |
169 | if (setgroups(saved_egroupslen, saved_egroups) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
170 | fatal("setgroups: %.100s", strerror(errno)); never executed: fatal("setgroups: %.100s", strerror( (*__errno_location ()) )); | 0 |
171 | temporarily_use_uid_effective = 0; | - |
172 | } never executed: end of block | 0 |
173 | | - |
174 | | - |
175 | | - |
176 | | - |
177 | | - |
178 | void | - |
179 | permanently_set_uid(struct passwd *pw) | - |
180 | { | - |
181 | #ifndef NO_UID_RESTORATION_TEST | - |
182 | uid_t old_uid = getuid(); | - |
183 | gid_t old_gid = getgid(); | - |
184 | #endif | - |
185 | | - |
186 | if (pw == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
187 | fatal("permanently_set_uid: no user given"); never executed: fatal("permanently_set_uid: no user given"); | 0 |
188 | if (temporarily_use_uid_effective)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
189 | fatal("permanently_set_uid: temporarily_use_uid effective"); never executed: fatal("permanently_set_uid: temporarily_use_uid effective"); | 0 |
190 | debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, | - |
191 | (u_int)pw->pw_gid); | - |
192 | | - |
193 | if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
194 | fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); never executed: fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror( (*__errno_location ()) )); | 0 |
195 | | - |
196 | #ifdef __APPLE__ | - |
197 | | - |
198 | | - |
199 | | - |
200 | | - |
201 | if (initgroups(pw->pw_name, pw->pw_gid) < 0) | - |
202 | fatal("initgroups %.100s %u: %.100s", | - |
203 | pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); | - |
204 | #endif | - |
205 | | - |
206 | if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
207 | fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); never executed: fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror( (*__errno_location ()) )); | 0 |
208 | | - |
209 | #ifndef NO_UID_RESTORATION_TEST | - |
210 | | - |
211 | if (old_gid != pw->pw_gid && pw->pw_uid != 0 &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
212 | (setgid(old_gid) != -1 || setegid(old_gid) != -1))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
213 | fatal("%s: was able to restore old [e]gid", __func__); never executed: fatal("%s: was able to restore old [e]gid", __func__); | 0 |
214 | #endif | - |
215 | | - |
216 | | - |
217 | if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
218 | fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", | - |
219 | __func__, (u_int)getgid(), (u_int)getegid(), | - |
220 | (u_int)pw->pw_gid); | - |
221 | } never executed: end of block | 0 |
222 | | - |
223 | #ifndef NO_UID_RESTORATION_TEST | - |
224 | | - |
225 | if (old_uid != pw->pw_uid &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
226 | (setuid(old_uid) != -1 || seteuid(old_uid) != -1))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
227 | fatal("%s: was able to restore old [e]uid", __func__); never executed: fatal("%s: was able to restore old [e]uid", __func__); | 0 |
228 | #endif | - |
229 | | - |
230 | | - |
231 | if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
232 | fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", | - |
233 | __func__, (u_int)getuid(), (u_int)geteuid(), | - |
234 | (u_int)pw->pw_uid); | - |
235 | } never executed: end of block | 0 |
236 | } never executed: end of block | 0 |
| | |