xref: /freebsd/crypto/openssh/uidswap.c (revision b66f2d16a0435b7e7f3edde6101797004ae8d3b9)
1511b41d2SMark Murray /*
2511b41d2SMark Murray  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4511b41d2SMark Murray  *                    All rights reserved
5511b41d2SMark Murray  * Code for uid-swapping.
6b66f2d16SKris Kennaway  *
7b66f2d16SKris Kennaway  * As far as I am concerned, the code I have written for this software
8b66f2d16SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
9b66f2d16SKris Kennaway  * software must be clearly marked as such, and if the derived work is
10b66f2d16SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
11b66f2d16SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
12511b41d2SMark Murray  */
13511b41d2SMark Murray 
14511b41d2SMark Murray #include "includes.h"
15b66f2d16SKris Kennaway RCSID("$OpenBSD: uidswap.c,v 1.9 2000/09/07 20:27:55 deraadt Exp $");
16511b41d2SMark Murray 
17511b41d2SMark Murray #include "ssh.h"
18511b41d2SMark Murray #include "uidswap.h"
19511b41d2SMark Murray 
20511b41d2SMark Murray /*
21511b41d2SMark Murray  * Note: all these functions must work in all of the following cases:
22511b41d2SMark Murray  *    1. euid=0, ruid=0
23511b41d2SMark Murray  *    2. euid=0, ruid!=0
24511b41d2SMark Murray  *    3. euid!=0, ruid!=0
25511b41d2SMark Murray  * Additionally, they must work regardless of whether the system has
26511b41d2SMark Murray  * POSIX saved uids or not.
27511b41d2SMark Murray  */
28511b41d2SMark Murray 
29511b41d2SMark Murray #ifdef _POSIX_SAVED_IDS
30511b41d2SMark Murray /* Lets assume that posix saved ids also work with seteuid, even though that
31511b41d2SMark Murray    is not part of the posix specification. */
32511b41d2SMark Murray #define SAVED_IDS_WORK_WITH_SETEUID
33511b41d2SMark Murray #endif /* _POSIX_SAVED_IDS */
34511b41d2SMark Murray 
35511b41d2SMark Murray /* Saved effective uid. */
36511b41d2SMark Murray static uid_t saved_euid = 0;
37511b41d2SMark Murray 
38511b41d2SMark Murray /*
39511b41d2SMark Murray  * Temporarily changes to the given uid.  If the effective user
40511b41d2SMark Murray  * id is not root, this does nothing.  This call cannot be nested.
41511b41d2SMark Murray  */
42511b41d2SMark Murray void
43511b41d2SMark Murray temporarily_use_uid(uid_t uid)
44511b41d2SMark Murray {
45511b41d2SMark Murray #ifdef SAVED_IDS_WORK_WITH_SETEUID
46511b41d2SMark Murray 	/* Save the current euid. */
47511b41d2SMark Murray 	saved_euid = geteuid();
48511b41d2SMark Murray 
49511b41d2SMark Murray 	/* Set the effective uid to the given (unprivileged) uid. */
50511b41d2SMark Murray 	if (seteuid(uid) == -1)
51b66f2d16SKris Kennaway 		debug("seteuid %u: %.100s", (u_int) uid, strerror(errno));
52511b41d2SMark Murray #else /* SAVED_IDS_WORK_WITH_SETUID */
53511b41d2SMark Murray 	/* Propagate the privileged uid to all of our uids. */
54511b41d2SMark Murray 	if (setuid(geteuid()) < 0)
55b66f2d16SKris Kennaway 		debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno));
56511b41d2SMark Murray 
57511b41d2SMark Murray 	/* Set the effective uid to the given (unprivileged) uid. */
58511b41d2SMark Murray 	if (seteuid(uid) == -1)
59b66f2d16SKris Kennaway 		debug("seteuid %u: %.100s", (u_int) uid, strerror(errno));
60511b41d2SMark Murray #endif /* SAVED_IDS_WORK_WITH_SETEUID */
61511b41d2SMark Murray }
62511b41d2SMark Murray 
63511b41d2SMark Murray /*
64511b41d2SMark Murray  * Restores to the original uid.
65511b41d2SMark Murray  */
66511b41d2SMark Murray void
67511b41d2SMark Murray restore_uid()
68511b41d2SMark Murray {
69511b41d2SMark Murray #ifdef SAVED_IDS_WORK_WITH_SETEUID
70511b41d2SMark Murray 	/* Set the effective uid back to the saved uid. */
71511b41d2SMark Murray 	if (seteuid(saved_euid) < 0)
72b66f2d16SKris Kennaway 		debug("seteuid %u: %.100s", (u_int) saved_euid, strerror(errno));
73511b41d2SMark Murray #else /* SAVED_IDS_WORK_WITH_SETEUID */
74511b41d2SMark Murray 	/*
75511b41d2SMark Murray 	 * We are unable to restore the real uid to its unprivileged value.
76511b41d2SMark Murray 	 * Propagate the real uid (usually more privileged) to effective uid
77511b41d2SMark Murray 	 * as well.
78511b41d2SMark Murray 	 */
79511b41d2SMark Murray 	setuid(getuid());
80511b41d2SMark Murray #endif /* SAVED_IDS_WORK_WITH_SETEUID */
81511b41d2SMark Murray }
82511b41d2SMark Murray 
83511b41d2SMark Murray /*
84511b41d2SMark Murray  * Permanently sets all uids to the given uid.  This cannot be
85511b41d2SMark Murray  * called while temporarily_use_uid is effective.
86511b41d2SMark Murray  */
87511b41d2SMark Murray void
88511b41d2SMark Murray permanently_set_uid(uid_t uid)
89511b41d2SMark Murray {
90511b41d2SMark Murray 	if (setuid(uid) < 0)
91b66f2d16SKris Kennaway 		debug("setuid %u: %.100s", (u_int) uid, strerror(errno));
92511b41d2SMark Murray }
93