OpenCoverage

uidswap.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/openssh/src/uidswap.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* $OpenBSD: uidswap.c,v 1.41 2018/07/18 11:34:04 dtucker Exp $ */-
2/*-
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>-
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland-
5 * All rights reserved-
6 * Code for uid-swapping.-
7 *-
8 * As far as I am concerned, the code I have written for this software-
9 * can be used freely for any purpose. Any derived versions of this-
10 * software must be clearly marked as such, and if the derived work is-
11 * incompatible with the protocol description in the RFC file, it must be-
12 * called by a name other than "ssh" or "Secure Shell".-
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 * Note: all these functions must work in all of the following cases:-
33 * 1. euid=0, ruid=0-
34 * 2. euid=0, ruid!=0-
35 * 3. euid!=0, ruid!=0-
36 * Additionally, they must work regardless of whether the system has-
37 * POSIX saved uids or not.-
38 */-
39-
40#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS)-
41/* Lets assume that posix saved ids also work with seteuid, even though that-
42 is not part of the posix specification. */-
43#define SAVED_IDS_WORK_WITH_SETEUID-
44/* Saved effective uid. */-
45static uid_t saved_euid = 0;-
46static gid_t saved_egid = 0;-
47#endif-
48-
49/* Saved effective uid. */-
50static int privileged = 0;-
51static int temporarily_use_uid_effective = 0;-
52static uid_t user_groups_uid;-
53static gid_t *saved_egroups = NULL, *user_groups = NULL;-
54static int saved_egroupslen = -1, user_groupslen = -1;-
55-
56/*-
57 * Temporarily changes to the given uid. If the effective user-
58 * id is not root, this does nothing. This call cannot be nested.-
59 */-
60void-
61temporarily_use_uid(struct passwd *pw)-
62{-
63 /* Save the current euid, and egroups. */-
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) {
saved_euid != 0Description
TRUEnever evaluated
FALSEnever 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)
saved_egroupslen < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
88 fatal("getgroups: %.100s", strerror(errno));
never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) ));
0
89 if (saved_egroupslen > 0) {
saved_egroupslen > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
90 saved_egroups = xreallocarray(saved_egroups,-
91 saved_egroupslen, sizeof(gid_t));-
92 if (getgroups(saved_egroupslen, saved_egroups) < 0)
getgroups(save...d_egroups) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
93 fatal("getgroups: %.100s", strerror(errno));
never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) ));
0
94 } else { /* saved_egroupslen == 0 */
never executed: end of block
0
95 free(saved_egroups);-
96 saved_egroups = NULL;-
97 }
never executed: end of block
0
98-
99 /* set and save the user's groups */-
100 if (user_groupslen == -1 || user_groups_uid != pw->pw_uid) {
user_groupslen == -1Description
TRUEnever evaluated
FALSEnever evaluated
user_groups_uid != pw->pw_uidDescription
TRUEnever evaluated
FALSEnever evaluated
0
101 if (initgroups(pw->pw_name, pw->pw_gid) < 0)
initgroups(pw-...w->pw_gid) < 0Description
TRUEnever evaluated
FALSEnever 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)
user_groupslen < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
107 fatal("getgroups: %.100s", strerror(errno));
never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) ));
0
108 if (user_groupslen > 0) {
user_groupslen > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
109 user_groups = xreallocarray(user_groups,-
110 user_groupslen, sizeof(gid_t));-
111 if (getgroups(user_groupslen, user_groups) < 0)
getgroups(user...er_groups) < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
112 fatal("getgroups: %.100s", strerror(errno));
never executed: fatal("getgroups: %.100s", strerror( (*__errno_location ()) ));
0
113 } else { /* user_groupslen == 0 */
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 /* Set the effective uid to the given (unprivileged) uid. */-
120 if (setgroups(user_groupslen, user_groups) < 0)
setgroups(user...er_groups) < 0Description
TRUEnever evaluated
FALSEnever 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 /* Propagate the privileged gid to all of our gids. */-
124 if (setgid(getegid()) < 0)-
125 debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno));-
126 /* Propagate the privileged uid to all of our uids. */-
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)
setegid(pw->pw_gid) < 0Description
TRUEnever evaluated
FALSEnever 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)
seteuid(pw->pw_uid) == -1Description
TRUEnever evaluated
FALSEnever 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 * Restores to the original (privileged) uid.-
140 */-
141void-
142restore_uid(void)-
143{-
144 /* it's a no-op unless privileged */-
145 if (!privileged) {
!privilegedDescription
TRUEnever evaluated
FALSEnever evaluated
0
146 debug("restore_uid: (unprivileged)");-
147 return;
never executed: return;
0
148 }-
149 if (!temporarily_use_uid_effective)
!temporarily_use_uid_effectiveDescription
TRUEnever evaluated
FALSEnever 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 /* Set the effective uid back to the saved privileged uid. */-
155 if (seteuid(saved_euid) < 0)
seteuid(saved_euid) < 0Description
TRUEnever evaluated
FALSEnever 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)
setegid(saved_egid) < 0Description
TRUEnever evaluated
FALSEnever 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 * We are unable to restore the real uid to its unprivileged value.-
162 * Propagate the real uid (usually more privileged) to effective uid-
163 * as well.-
164 */-
165 setuid(getuid());-
166 setgid(getgid());-
167#endif /* SAVED_IDS_WORK_WITH_SETEUID */-
168-
169 if (setgroups(saved_egroupslen, saved_egroups) < 0)
setgroups(save...d_egroups) < 0Description
TRUEnever evaluated
FALSEnever 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 * Permanently sets all uids to the given uid. This cannot be-
176 * called while temporarily_use_uid is effective.-
177 */-
178void-
179permanently_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)
pw == ((void *)0)Description
TRUEnever evaluated
FALSEnever 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)
temporarily_use_uid_effectiveDescription
TRUEnever evaluated
FALSEnever 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)
setresgid(pw->...w->pw_gid) < 0Description
TRUEnever evaluated
FALSEnever 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 * OS X requires initgroups after setgid to opt back into-
199 * memberd support for >16 supplemental groups.-
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)
setresuid(pw->...w->pw_uid) < 0Description
TRUEnever evaluated
FALSEnever 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 /* Try restoration of GID if changed (test clearing of saved gid) */-
211 if (old_gid != pw->pw_gid && pw->pw_uid != 0 &&
old_gid != pw->pw_gidDescription
TRUEnever evaluated
FALSEnever evaluated
pw->pw_uid != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
212 (setgid(old_gid) != -1 || setegid(old_gid) != -1))
setgid(old_gid) != -1Description
TRUEnever evaluated
FALSEnever evaluated
setegid(old_gid) != -1Description
TRUEnever evaluated
FALSEnever 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 /* Verify GID drop was successful */-
217 if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) {
getgid() != pw->pw_gidDescription
TRUEnever evaluated
FALSEnever evaluated
getegid() != pw->pw_gidDescription
TRUEnever evaluated
FALSEnever 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 /* Try restoration of UID if changed (test clearing of saved uid) */-
225 if (old_uid != pw->pw_uid &&
old_uid != pw->pw_uidDescription
TRUEnever evaluated
FALSEnever evaluated
0
226 (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
setuid(old_uid) != -1Description
TRUEnever evaluated
FALSEnever evaluated
seteuid(old_uid) != -1Description
TRUEnever evaluated
FALSEnever 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 /* Verify UID drop was successful */-
231 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) {
getuid() != pw->pw_uidDescription
TRUEnever evaluated
FALSEnever evaluated
geteuid() != pw->pw_uidDescription
TRUEnever evaluated
FALSEnever 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
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2