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