version 1.3, 2000/01/24 04:22:53 |
version 1.4, 2000/03/27 03:44:39 |
|
|
# endif /* __hpux */ |
# endif /* __hpux */ |
# include <prot.h> |
# include <prot.h> |
#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ |
#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ |
|
#ifdef HAVE_LOGINCAP |
|
# include <login_cap.h> |
|
# ifndef LOGIN_DEFROOTCLASS |
|
# define LOGIN_DEFROOTCLASS "daemon" |
|
# endif |
|
#endif |
|
|
#include "sudo.h" |
#include "sudo.h" |
#include "interfaces.h" |
#include "interfaces.h" |
|
|
#endif /* STDC_HEADERS */ |
#endif /* STDC_HEADERS */ |
|
|
#ifndef lint |
#ifndef lint |
static const char rcsid[] = "$Sudo: sudo.c,v 1.268 2000/01/17 23:46:25 millert Exp $"; |
static const char rcsid[] = "$Sudo: sudo.c,v 1.278 2000/03/24 20:13:12 millert Exp $"; |
#endif /* lint */ |
#endif /* lint */ |
|
|
/* |
/* |
|
|
static void usage_excl __P((int)); |
static void usage_excl __P((int)); |
static void check_sudoers __P((void)); |
static void check_sudoers __P((void)); |
static int init_vars __P((int)); |
static int init_vars __P((int)); |
|
static int set_loginclass __P((struct passwd *)); |
static void add_env __P((int)); |
static void add_env __P((int)); |
static void clean_env __P((char **, struct env_table *)); |
static void clean_env __P((char **, struct env_table *)); |
static void initial_setup __P((void)); |
static void initial_setup __P((void)); |
extern int user_is_exempt __P((void)); |
static void update_epasswd __P((void)); |
extern struct passwd *sudo_getpwuid __P((uid_t)); |
extern struct passwd *sudo_getpwuid __P((uid_t)); |
extern void list_matches __P((void)); |
extern void list_matches __P((void)); |
|
|
|
|
char **NewArgv = NULL; |
char **NewArgv = NULL; |
struct sudo_user sudo_user; |
struct sudo_user sudo_user; |
FILE *sudoers_fp = NULL; |
FILE *sudoers_fp = NULL; |
static char *runas_homedir = NULL; /* XXX */ |
|
struct interface *interfaces; |
struct interface *interfaces; |
int num_interfaces; |
int num_interfaces; |
|
int tgetpass_flags; |
extern int errorlineno; |
extern int errorlineno; |
|
static char *runas_homedir = NULL; /* XXX */ |
|
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) |
|
static struct rlimit corelimit; |
|
#endif /* RLIMIT_CORE */ |
|
|
/* |
/* |
* Table of "bad" envariables to remove and len for strncmp() |
* Table of "bad" envariables to remove and len for strncmp() |
|
|
(void) close(fd); |
(void) close(fd); |
} |
} |
|
|
|
/* Update encrypted password in user_password if sudoers said to. */ |
|
update_epasswd(); |
|
|
/* Require a password unless the NOPASS tag was set. */ |
/* Require a password unless the NOPASS tag was set. */ |
if (!(validated & FLAG_NOPASS)) |
if (!(validated & FLAG_NOPASS)) |
check_user(); |
check_user(); |
|
|
exit(0); |
exit(0); |
} |
} |
|
|
/* Become specified user or root. */ |
|
set_perms(PERM_RUNAS, sudo_mode); |
|
|
|
/* Set $HOME for `sudo -H' */ |
/* Set $HOME for `sudo -H' */ |
if ((sudo_mode & MODE_RESET_HOME) && runas_homedir) |
if ((sudo_mode & MODE_RESET_HOME) && runas_homedir) |
(void) sudo_setenv("HOME", runas_homedir); |
(void) sudo_setenv("HOME", runas_homedir); |
|
|
exit(1); |
exit(1); |
} |
} |
|
|
|
/* Restore coredumpsize resource limit. */ |
|
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) |
|
(void) setrlimit(RLIMIT_CORE, &corelimit); |
|
#endif /* RLIMIT_CORE */ |
|
|
|
/* Become specified user or root. */ |
|
set_perms(PERM_RUNAS, sudo_mode); |
|
|
#ifndef PROFILING |
#ifndef PROFILING |
if ((sudo_mode & MODE_BACKGROUND) && fork() > 0) |
if ((sudo_mode & MODE_BACKGROUND) && fork() > 0) |
exit(0); |
exit(0); |
|
|
NewArgc--; |
NewArgc--; |
NewArgv++; |
NewArgv++; |
break; |
break; |
|
#ifdef HAVE_LOGINCAP |
|
case 'c': |
|
/* Must have an associated login class. */ |
|
if (NewArgv[1] == NULL) |
|
usage(1); |
|
|
|
login_class = NewArgv[1]; |
|
def_flag(I_LOGINCLASS) = TRUE; |
|
|
|
/* Shift Argv over and adjust Argc. */ |
|
NewArgc--; |
|
NewArgv++; |
|
break; |
|
#endif |
case 'b': |
case 'b': |
rval |= MODE_BACKGROUND; |
rval |= MODE_BACKGROUND; |
break; |
break; |
|
|
case 'H': |
case 'H': |
rval |= MODE_RESET_HOME; |
rval |= MODE_RESET_HOME; |
break; |
break; |
|
case 'S': |
|
tgetpass_flags |= TGP_STDIN; |
|
break; |
case '-': |
case '-': |
NewArgc--; |
NewArgc--; |
NewArgv++; |
NewArgv++; |
|
|
} |
} |
|
|
/* Set $USER and $LOGNAME to target user */ |
/* Set $USER and $LOGNAME to target user */ |
if (sudo_setenv("USER", pw->pw_name)) { |
if (def_flag(I_LOGNAME)) { |
(void) fprintf(stderr, |
if (sudo_setenv("USER", pw->pw_name)) { |
"%s: cannot allocate memory!\n", |
(void) fprintf(stderr, |
Argv[0]); |
"%s: cannot allocate memory!\n", |
exit(1); |
Argv[0]); |
|
exit(1); |
|
} |
|
if (sudo_setenv("LOGNAME", pw->pw_name)) { |
|
(void) fprintf(stderr, |
|
"%s: cannot allocate memory!\n", |
|
Argv[0]); |
|
exit(1); |
|
} |
} |
} |
if (sudo_setenv("LOGNAME", pw->pw_name)) { |
|
(void) fprintf(stderr, |
if (def_flag(I_LOGINCLASS)) { |
"%s: cannot allocate memory!\n", |
/* |
Argv[0]); |
* setusercontext() will set uid/gid/etc |
exit(1); |
* for us so no need to do it below. |
|
*/ |
|
if (set_loginclass(pw) > 0) |
|
break; |
} |
} |
|
|
if (setgid(pw->pw_gid)) { |
if (setgid(pw->pw_gid)) { |
|
|
/* |
/* |
* Turn off core dumps. |
* Turn off core dumps. |
*/ |
*/ |
|
(void) getrlimit(RLIMIT_CORE, &corelimit); |
rl.rlim_cur = rl.rlim_max = 0; |
rl.rlim_cur = rl.rlim_max = 0; |
(void) setrlimit(RLIMIT_CORE, &rl); |
(void) setrlimit(RLIMIT_CORE, &rl); |
#endif /* RLIMIT_CORE */ |
#endif /* RLIMIT_CORE */ |
|
|
#endif /* POSIX_SIGNALS */ |
#endif /* POSIX_SIGNALS */ |
} |
} |
|
|
|
#ifdef HAVE_LOGINCAP |
|
static int |
|
set_loginclass(pw) |
|
struct passwd *pw; |
|
{ |
|
login_cap_t *lc; |
|
int errflags; |
|
|
|
/* |
|
* Don't make it a fatal error if the user didn't specify the login |
|
* class themselves. We do this because if login.conf gets |
|
* corrupted we want the admin to be able to use sudo to fix it. |
|
*/ |
|
if (login_class) |
|
errflags = NO_MAIL|MSG_ONLY; |
|
else |
|
errflags = NO_MAIL|MSG_ONLY|NO_EXIT; |
|
|
|
if (login_class && strcmp(login_class, "-") != 0) { |
|
if (strcmp(*user_runas, "root") != 0 && user_uid != 0) { |
|
(void) fprintf(stderr, "%s: only root can use -c %s\n", |
|
Argv[0], login_class); |
|
exit(1); |
|
} |
|
} else { |
|
login_class = pw->pw_class; |
|
if (!login_class || !*login_class) |
|
login_class = |
|
(pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; |
|
} |
|
|
|
lc = login_getclass(login_class); |
|
if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) { |
|
log_error(errflags, "unknown login class: %s", login_class); |
|
return(0); |
|
} |
|
|
|
/* Set everything except the environment and umask. */ |
|
if (setusercontext(lc, pw, pw->pw_uid, |
|
LOGIN_SETUSER|LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY) < 0) |
|
log_error(NO_MAIL|USE_ERRNO|MSG_ONLY, |
|
"setusercontext() failed for login class %s", login_class); |
|
|
|
login_close(lc); |
|
return(1); |
|
} |
|
#else |
|
static int |
|
set_loginclass(pw) |
|
struct passwd *pw; |
|
{ |
|
return(0); |
|
} |
|
#endif /* HAVE_LOGINCAP */ |
|
|
/* |
/* |
* Look up the fully qualified domain name and set user_host and user_shost. |
* Look up the fully qualified domain name and set user_host and user_shost. |
*/ |
*/ |
|
|
} |
} |
|
|
/* |
/* |
|
* If the sudoers file says to prompt for a different user's password, |
|
* update the encrypted password in user_passwd accordingly. |
|
*/ |
|
static void |
|
update_epasswd() |
|
{ |
|
struct passwd *pw; |
|
|
|
/* We may be configured to prompt for a password other than the user's */ |
|
if (def_ival(I_ROOTPW)) { |
|
if ((pw = getpwuid(0)) == NULL) |
|
log_error(0, "uid 0 does not exist in the passwd file!"); |
|
free(user_passwd); |
|
user_passwd = estrdup(sudo_getepw(pw)); |
|
} else if (def_ival(I_RUNASPW)) { |
|
if ((pw = getpwnam(def_str(I_RUNAS_DEF))) == NULL) |
|
log_error(0, "user %s does not exist in the passwd file!", |
|
def_str(I_RUNAS_DEF)); |
|
free(user_passwd); |
|
user_passwd = estrdup(sudo_getepw(pw)); |
|
} else if (def_ival(I_TARGETPW)) { |
|
if (**user_runas == '#') { |
|
if ((pw = getpwuid(atoi(*user_runas + 1))) == NULL) |
|
log_error(0, "uid %s does not exist in the passwd file!", |
|
user_runas); |
|
} else { |
|
if ((pw = getpwnam(*user_runas)) == NULL) |
|
log_error(0, "user %s does not exist in the passwd file!", |
|
user_runas); |
|
} |
|
free(user_passwd); |
|
user_passwd = estrdup(sudo_getepw(pw)); |
|
} |
|
} |
|
|
|
/* |
* Tell which options are mutually exclusive and exit. |
* Tell which options are mutually exclusive and exit. |
*/ |
*/ |
static void |
static void |
|
|
int exit_val; |
int exit_val; |
{ |
{ |
(void) fprintf(stderr, |
(void) fprintf(stderr, |
"usage: %s -V | -h | -L | -l | -v | -k | -K | -H | [-b] [-p prompt]\n%*s", |
"usage: %s -V | -h | -L | -l | -v | -k | -K | [-H] [-S] [-b]\n%*s", |
Argv[0], (int) strlen(Argv[0]) + 8, " "); |
Argv[0], (int) strlen(Argv[0]) + 8, " "); |
(void) fprintf(stderr, "[-u username/#uid] -s | <command>\n"); |
#ifdef HAVE_LOGINCAP |
|
(void) fprintf(stderr, "[-p prompt] [-u username/#uid] [-c class] -s | <command>\n"); |
|
#else |
|
(void) fprintf(stderr, "[-p prompt] [-u username/#uid] -s | <command>\n"); |
|
#endif |
exit(exit_val); |
exit(exit_val); |
} |
} |