source: trunk/third/openssh/uidswap.c @ 18759

Revision 18759, 4.8 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Code for uid-swapping.
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose.  Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 */
13
14#include "includes.h"
15RCSID("$OpenBSD: uidswap.c,v 1.23 2002/07/15 17:15:31 stevesk Exp $");
16
17#include "log.h"
18#include "uidswap.h"
19
20/*
21 * Note: all these functions must work in all of the following cases:
22 *    1. euid=0, ruid=0
23 *    2. euid=0, ruid!=0
24 *    3. euid!=0, ruid!=0
25 * Additionally, they must work regardless of whether the system has
26 * POSIX saved uids or not.
27 */
28
29#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS)
30/* Lets assume that posix saved ids also work with seteuid, even though that
31   is not part of the posix specification. */
32#define SAVED_IDS_WORK_WITH_SETEUID
33/* Saved effective uid. */
34static uid_t    saved_euid = 0;
35static gid_t    saved_egid = 0;
36#endif
37
38/* Saved effective uid. */
39static int      privileged = 0;
40static int      temporarily_use_uid_effective = 0;
41static gid_t    saved_egroups[NGROUPS_MAX], user_groups[NGROUPS_MAX];
42static int      saved_egroupslen = -1, user_groupslen = -1;
43
44/*
45 * Temporarily changes to the given uid.  If the effective user
46 * id is not root, this does nothing.  This call cannot be nested.
47 */
48void
49temporarily_use_uid(struct passwd *pw)
50{
51        /* Save the current euid, and egroups. */
52#ifdef SAVED_IDS_WORK_WITH_SETEUID
53        saved_euid = geteuid();
54        saved_egid = getegid();
55        debug("temporarily_use_uid: %u/%u (e=%u/%u)",
56            (u_int)pw->pw_uid, (u_int)pw->pw_gid,
57            (u_int)saved_euid, (u_int)saved_egid);
58        if (saved_euid != 0) {
59                privileged = 0;
60                return;
61        }
62#else
63        if (geteuid() != 0) {
64                privileged = 0;
65                return;
66        }
67#endif /* SAVED_IDS_WORK_WITH_SETEUID */
68
69        privileged = 1;
70        temporarily_use_uid_effective = 1;
71        saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups);
72        if (saved_egroupslen < 0)
73                fatal("getgroups: %.100s", strerror(errno));
74
75        /* set and save the user's groups */
76        if (user_groupslen == -1) {
77                if (initgroups(pw->pw_name, pw->pw_gid) < 0)
78                        fatal("initgroups: %s: %.100s", pw->pw_name,
79                            strerror(errno));
80                user_groupslen = getgroups(NGROUPS_MAX, user_groups);
81                if (user_groupslen < 0)
82                        fatal("getgroups: %.100s", strerror(errno));
83        }
84        /* Set the effective uid to the given (unprivileged) uid. */
85        if (setgroups(user_groupslen, user_groups) < 0)
86                fatal("setgroups: %.100s", strerror(errno));
87#ifndef SAVED_IDS_WORK_WITH_SETEUID
88        /* Propagate the privileged gid to all of our gids. */
89        if (setgid(getegid()) < 0)
90                debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno));
91        /* Propagate the privileged uid to all of our uids. */
92        if (setuid(geteuid()) < 0)
93                debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno));
94#endif /* SAVED_IDS_WORK_WITH_SETEUID */
95        if (setegid(pw->pw_gid) < 0)
96                fatal("setegid %u: %.100s", (u_int)pw->pw_gid,
97                    strerror(errno));
98        if (seteuid(pw->pw_uid) == -1)
99                fatal("seteuid %u: %.100s", (u_int)pw->pw_uid,
100                    strerror(errno));
101}
102
103/*
104 * Restores to the original (privileged) uid.
105 */
106void
107restore_uid(void)
108{
109        /* it's a no-op unless privileged */
110        if (!privileged) {
111                debug("restore_uid: (unprivileged)");
112                return;
113        }
114        if (!temporarily_use_uid_effective)
115                fatal("restore_uid: temporarily_use_uid not effective");
116
117#ifdef SAVED_IDS_WORK_WITH_SETEUID
118        debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid);
119        /* Set the effective uid back to the saved privileged uid. */
120        if (seteuid(saved_euid) < 0)
121                fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno));
122        if (setegid(saved_egid) < 0)
123                fatal("setegid %u: %.100s", (u_int)saved_egid, strerror(errno));
124#else /* SAVED_IDS_WORK_WITH_SETEUID */
125        /*
126         * We are unable to restore the real uid to its unprivileged value.
127         * Propagate the real uid (usually more privileged) to effective uid
128         * as well.
129         */
130        setuid(getuid());
131        setgid(getgid());
132#endif /* SAVED_IDS_WORK_WITH_SETEUID */
133
134        if (setgroups(saved_egroupslen, saved_egroups) < 0)
135                fatal("setgroups: %.100s", strerror(errno));
136        temporarily_use_uid_effective = 0;
137}
138
139/*
140 * Permanently sets all uids to the given uid.  This cannot be
141 * called while temporarily_use_uid is effective.
142 */
143void
144permanently_set_uid(struct passwd *pw)
145{
146        if (temporarily_use_uid_effective)
147                fatal("permanently_set_uid: temporarily_use_uid effective");
148        debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid,
149            (u_int)pw->pw_gid);
150        if (setgid(pw->pw_gid) < 0)
151                fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno));
152        if (setuid(pw->pw_uid) < 0)
153                fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
154}
Note: See TracBrowser for help on using the repository browser.