version 1.6, 2002/07/20 12:32:11 |
version 1.7, 2003/03/15 21:23:54 |
|
|
/* |
/* |
* Copyright (c) 1994-1996,1998-2001 Todd C. Miller <Todd.Miller@courtesan.com> |
* Copyright (c) 1994-1996,1998-2003 Todd C. Miller <Todd.Miller@courtesan.com> |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
#include "sudo.h" |
#include "sudo.h" |
|
|
#ifndef lint |
#ifndef lint |
static const char rcsid[] = "$Sudo: set_perms.c,v 1.12 2002/01/22 02:00:25 millert Exp $"; |
static const char rcsid[] = "$Sudo: set_perms.c,v 1.20 2003/03/15 20:31:02 millert Exp $"; |
#endif /* lint */ |
#endif /* lint */ |
|
|
/* |
/* |
|
|
static void runas_setup __P((void)); |
static void runas_setup __P((void)); |
static void fatal __P((char *, int)); |
static void fatal __P((char *, int)); |
|
|
#if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION) |
#if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \ |
|
!defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION) |
/* |
/* |
* Set real and effective uids and gids based on perm. |
* Set real and effective uids and gids based on perm. |
* Since we have POSIX saved IDs we can get away with just |
* Since we have POSIX saved IDs we can get away with just |
* toggling the effective uid/gid unless we are headed for an exec(). |
* toggling the effective uid/gid unless we are headed for an exec(). |
*/ |
*/ |
void |
void |
set_perms_posix(perm, sudo_mode) |
set_perms_posix(perm) |
int perm; |
int perm; |
int sudo_mode; |
|
{ |
{ |
int error; |
int error; |
|
|
|
|
fatal("seteuid(SUDOERS_UID)", 1); |
fatal("seteuid(SUDOERS_UID)", 1); |
} |
} |
break; |
break; |
|
case PERM_TIMESTAMP: |
|
if (seteuid(timestamp_uid)) |
|
fatal("seteuid(timestamp_uid)", 1); |
|
break; |
|
|
} |
} |
} |
} |
#endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */ |
#endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */ |
|
|
#ifdef HAVE_SETREUID |
#ifdef HAVE_SETRESUID |
/* |
/* |
|
* Set real and effective and saved uids and gids based on perm. |
|
* We always retain a saved uid of 0 unless we are headed for an exec(). |
|
* We only flip the effective gid since it only changes for PERM_SUDOERS. |
|
* This version of set_perms() works fine with the "stay_setuid" option. |
|
*/ |
|
void |
|
set_perms_suid(perm) |
|
int perm; |
|
{ |
|
int error; |
|
|
|
switch (perm) { |
|
case PERM_FULL_ROOT: |
|
case PERM_ROOT: |
|
if (setresuid(0, 0, 0)) |
|
fatal("setresuid(0, 0, 0) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid", 0); |
|
break; |
|
|
|
case PERM_USER: |
|
(void) setresgid(-1, user_gid, -1); |
|
if (setresuid(user_uid, user_uid, 0)) |
|
fatal("setresuid(user_uid, user_uid, 0)", 1); |
|
break; |
|
|
|
case PERM_FULL_USER: |
|
/* headed for exec() */ |
|
(void) setgid(user_gid); |
|
if (setresuid(user_uid, user_uid, user_uid)) |
|
fatal("setresuid(user_uid, user_uid, user_uid)", 1); |
|
break; |
|
|
|
case PERM_RUNAS: |
|
/* headed for exec(), assume euid == 0 */ |
|
runas_setup(); |
|
error = setresuid(def_flag(I_STAY_SETUID) ? |
|
user_uid : runas_pw->pw_uid, |
|
runas_pw->pw_uid, runas_pw->pw_uid); |
|
if (error) |
|
fatal("unable to change to runas uid", 1); |
|
break; |
|
|
|
case PERM_SUDOERS: |
|
/* assume euid == 0, ruid == user */ |
|
if (setresgid(-1, SUDOERS_GID, -1)) |
|
fatal("unable to change to sudoers gid", 1); |
|
|
|
/* |
|
* If SUDOERS_UID == 0 and SUDOERS_MODE |
|
* is group readable we use a non-zero |
|
* uid in order to avoid NFS lossage. |
|
* Using uid 1 is a bit bogus but should |
|
* work on all OS's. |
|
*/ |
|
if (SUDOERS_UID == 0) { |
|
if ((SUDOERS_MODE & 040) && setresuid(0, 1, 0)) |
|
fatal("setresuid(0, 1, 0)", 1); |
|
} else { |
|
if (setresuid(0, SUDOERS_UID, 0)) |
|
fatal("setresuid(0, SUDOERS_UID, 0)", 1); |
|
} |
|
break; |
|
case PERM_TIMESTAMP: |
|
if (setresuid(0, timestamp_uid, 0)) |
|
fatal("setresuid(0, timestamp_uid, 0)", 1); |
|
break; |
|
} |
|
} |
|
|
|
#else |
|
# ifdef HAVE_SETREUID |
|
|
|
/* |
* Set real and effective uids and gids based on perm. |
* Set real and effective uids and gids based on perm. |
* We always retain a real or effective uid of 0 unless |
* We always retain a real or effective uid of 0 unless |
* we are headed for an exec(). |
* we are headed for an exec(). |
|
* This version of set_perms() works fine with the "stay_setuid" option. |
*/ |
*/ |
void |
void |
set_perms_fallback(perm, sudo_mode) |
set_perms_suid(perm) |
int perm; |
int perm; |
int sudo_mode; |
|
{ |
{ |
int error; |
int error; |
|
|
switch (perm) { |
switch (perm) { |
case PERM_FULL_ROOT: |
case PERM_FULL_ROOT: |
case PERM_ROOT: |
case PERM_ROOT: |
if (setuid(0)) |
if (setreuid(0, 0)) |
fatal("setuid(0) failed, your operating system may have broken POSIX saved ID support\nTry running configure with --disable-setreuid", 0); |
fatal("setreuid(0, 0) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid", 0); |
break; |
break; |
|
|
case PERM_USER: |
case PERM_USER: |
(void) setegid(user_gid); |
(void) setregid(-1, user_gid); |
if (setreuid(0, user_uid)) |
if (setreuid(0, user_uid)) |
fatal("setreuid(0, user_uid)", 1); |
fatal("setreuid(0, user_uid)", 1); |
break; |
break; |
|
|
case PERM_FULL_USER: |
case PERM_FULL_USER: |
/* headed for exec() */ |
/* headed for exec() */ |
(void) setgid(user_gid); |
(void) setgid(user_gid); |
if (setuid(user_uid)) |
if (setreuid(user_uid, user_uid)) |
fatal("setuid(user_uid)", 1); |
fatal("setreuid(user_uid, user_uid)", 1); |
break; |
break; |
|
|
case PERM_RUNAS: |
case PERM_RUNAS: |
/* headed for exec(), assume euid == 0 */ |
/* headed for exec(), assume euid == 0 */ |
runas_setup(); |
runas_setup(); |
if (def_flag(I_STAY_SETUID)) |
error = setreuid(def_flag(I_STAY_SETUID) ? |
error = setreuid(user_uid, runas_pw->pw_uid); |
user_uid : runas_pw->pw_uid, |
else |
runas_pw->pw_uid); |
error = setuid(runas_pw->pw_uid); |
|
if (error) |
if (error) |
fatal("unable to change to runas uid", 1); |
fatal("unable to change to runas uid", 1); |
break; |
break; |
|
|
case PERM_SUDOERS: |
case PERM_SUDOERS: |
/* assume euid == 0, ruid == user */ |
/* assume euid == 0, ruid == user */ |
if (setegid(SUDOERS_GID)) |
if (setregid(-1, SUDOERS_GID)) |
fatal("unable to change to sudoers gid", 1); |
fatal("unable to change to sudoers gid", 1); |
|
|
/* |
/* |
|
|
fatal("setreuid(0, SUDOERS_UID)", 1); |
fatal("setreuid(0, SUDOERS_UID)", 1); |
} |
} |
break; |
break; |
|
case PERM_TIMESTAMP: |
|
if (setreuid(0, timestamp_uid)) |
|
fatal("setreuid(0, timestamp_uid)", 1); |
|
break; |
} |
} |
} |
} |
|
|
#else |
# else |
|
|
/* |
/* |
* Set real and effective uids and gids based on perm. |
* Set real and effective uids and gids based on perm. |
* NOTE: does not support the "stay_setuid" option. |
* NOTE: does not support the "stay_setuid" option. |
*/ |
*/ |
void |
void |
set_perms_fallback(perm, sudo_mode) |
set_perms_nosuid(perm) |
int perm; |
int perm; |
int sudo_mode; |
|
{ |
{ |
|
|
/* |
/* |
* Since we only have setuid() and seteuid() we have to set |
* Since we only have setuid() and seteuid() we have to set |
* real and effective uidss to 0 initially. |
* real and effective uids to 0 initially. |
*/ |
*/ |
if (setuid(0)) |
if (setuid(0)) |
fatal("setuid(0)", 1); |
fatal("setuid(0)", 1); |
|
|
fatal("seteuid(SUDOERS_UID)", 1); |
fatal("seteuid(SUDOERS_UID)", 1); |
} |
} |
break; |
break; |
|
case PERM_TIMESTAMP: |
|
if (seteuid(timestamp_uid)) |
|
fatal("seteuid(timestamp_uid)", 1); |
|
break; |
} |
} |
} |
} |
#endif /* HAVE_SETREUID */ |
# endif /* HAVE_SETREUID */ |
|
#endif /* HAVE_SETRESUID */ |
|
|
static void |
static void |
runas_setup() |
runas_setup() |
|
|
perror("cannot set gid to runas gid"); |
perror("cannot set gid to runas gid"); |
error = setusercontext(lc, runas_pw, |
error = setusercontext(lc, runas_pw, |
runas_pw->pw_uid, flags); |
runas_pw->pw_uid, flags); |
if (error) |
if (error) { |
perror("unable to set user context"); |
if (runas_pw->pw_uid != 0) |
} else |
|
#endif /* HAVE_LOGIN_CAP_H */ |
|
{ |
|
if (setgid(runas_pw->pw_gid)) { |
|
if (runas_pw->pw_gid != 0) |
|
fatal("unable to set user context", 1); |
fatal("unable to set user context", 1); |
else |
else |
perror("cannot set gid to runas gid"); |
perror("unable to set user context"); |
} |
} |
|
} else |
|
#endif /* HAVE_LOGIN_CAP_H */ |
|
{ |
|
if (setgid(runas_pw->pw_gid)) |
|
perror("cannot set gid to runas gid"); |
#ifdef HAVE_INITGROUPS |
#ifdef HAVE_INITGROUPS |
/* |
/* |
* Initialize group vector unless asked not to. |
* Initialize group vector unless asked not to. |