=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sudo/Attic/sudo.c,v retrieving revision 1.22 retrieving revision 1.23 diff -c -r1.22 -r1.23 *** src/usr.bin/sudo/Attic/sudo.c 2004/01/12 19:13:21 1.22 --- src/usr.bin/sudo/Attic/sudo.c 2004/09/28 15:10:51 1.23 *************** *** 1,36 **** /* ! * Copyright (c) 1993-1996,1998-2003 Todd C. Miller ! * All rights reserved. * ! * Redistribution and use in source and binary forms, with or without ! * modification, are permitted provided that the following conditions ! * are met: * ! * 1. Redistributions of source code must retain the above copyright ! * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 4. Products derived from this software may not be called "Sudo" nor - * may "Sudo" appear in their names without specific prior written - * permission from the author. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. --- 1,18 ---- /* ! * Copyright (c) 1993-1996,1998-2004 Todd C. Miller * ! * Permission to use, copy, modify, and distribute this software for any ! * purpose with or without fee is hereby granted, provided that the above ! * copyright notice and this permission notice appear in all copies. * ! * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ! * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ! * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ! * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ! * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ! * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. *************** *** 41,46 **** --- 23,32 ---- #define _SUDO_MAIN + #ifdef __TANDEM + # include + #endif + #include "config.h" #include *************** *** 107,113 **** #include "version.h" #ifndef lint ! static const char rcsid[] = "$Sudo: sudo.c,v 1.337 2003/04/16 00:42:10 millert Exp $"; #endif /* lint */ /* --- 93,99 ---- #include "version.h" #ifndef lint ! static const char rcsid[] = "$Sudo: sudo.c,v 1.370 2004/08/24 18:01:13 millert Exp $"; #endif /* lint */ /* *************** *** 121,137 **** static void usage __P((int)); static void usage_excl __P((int)); static struct passwd *get_authpw __P((void)); extern void list_matches __P((void)); ! extern char **rebuild_env __P((int, char **)); extern char **zero_env __P((char **)); extern struct passwd *sudo_getpwnam __P((const char *)); extern struct passwd *sudo_getpwuid __P((uid_t)); /* * Globals */ int Argc, NewArgc; char **Argv, **NewArgv; struct sudo_user sudo_user; struct passwd *auth_pw; FILE *sudoers_fp; --- 107,126 ---- static void usage __P((int)); static void usage_excl __P((int)); static struct passwd *get_authpw __P((void)); + extern int sudo_edit __P((int, char **)); extern void list_matches __P((void)); ! extern char **rebuild_env __P((char **, int, int)); extern char **zero_env __P((char **)); extern struct passwd *sudo_getpwnam __P((const char *)); extern struct passwd *sudo_getpwuid __P((uid_t)); + extern struct passwd *sudo_pwdup __P((const struct passwd *)); /* * Globals */ int Argc, NewArgc; char **Argv, **NewArgv; + char *prev_user; struct sudo_user sudo_user; struct passwd *auth_pw; FILE *sudoers_fp; *************** *** 149,154 **** --- 138,144 ---- #ifdef HAVE_BSD_AUTH_H char *login_style; #endif /* HAVE_BSD_AUTH_H */ + sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld; void (*set_perms) __P((int)); *************** *** 164,175 **** int sudo_mode; int pwflag; char **new_environ; ! sigaction_t sa, saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld; extern int printmatches; extern char **environ; - Argc = argc; Argv = argv; /* Must be done as the first thing... */ #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) --- 154,166 ---- int sudo_mode; int pwflag; char **new_environ; ! sigaction_t sa; extern int printmatches; extern char **environ; Argv = argv; + if ((Argc = argc) < 1) + usage(1); /* Must be done as the first thing... */ #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) *************** *** 216,223 **** load_interfaces(); pwflag = 0; ! if (sudo_mode & MODE_SHELL) user_cmnd = "shell"; else switch (sudo_mode) { case MODE_VERSION: --- 207,216 ---- load_interfaces(); pwflag = 0; ! if (ISSET(sudo_mode, MODE_SHELL)) user_cmnd = "shell"; + else if (ISSET(sudo_mode, MODE_EDIT)) + user_cmnd = "sudoedit"; else switch (sudo_mode) { case MODE_VERSION: *************** *** 235,241 **** break; case MODE_VALIDATE: user_cmnd = "validate"; ! pwflag = I_VERIFYPW_I; break; case MODE_KILL: case MODE_INVALIDATE: --- 228,234 ---- break; case MODE_VALIDATE: user_cmnd = "validate"; ! pwflag = I_VERIFYPW; break; case MODE_KILL: case MODE_INVALIDATE: *************** *** 248,254 **** break; case MODE_LIST: user_cmnd = "list"; ! pwflag = I_LISTPW_I; printmatches = 1; break; } --- 241,247 ---- break; case MODE_LIST: user_cmnd = "list"; ! pwflag = I_LISTPW; printmatches = 1; break; } *************** *** 259,269 **** cmnd_status = init_vars(sudo_mode); ! check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ ! /* Validate the user but don't search for pseudo-commands. */ ! validated = sudoers_lookup(pwflag); /* * If we are using set_perms_posix() and the stay_setuid flag was not set, * set the real, effective and saved uids to 0 and use set_perms_nosuid() --- 252,281 ---- cmnd_status = init_vars(sudo_mode); ! #ifdef HAVE_LDAP ! validated = sudo_ldap_check(pwflag); ! /* Skip reading /etc/sudoers if LDAP told us to */ ! if (def_ignore_local_sudoers); /* skips */ ! else if (ISSET(validated, VALIDATE_OK) && !printmatches); /* skips */ ! else if (ISSET(validated, VALIDATE_OK) && printmatches) ! { ! check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ + /* User is found in LDAP and we want a list of all sudo commands the + * user can do, so consult sudoers but throw away result. + */ + sudoers_lookup(pwflag); + } + else + #endif + { + check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ + + /* Validate the user but don't search for pseudo-commands. */ + validated = sudoers_lookup(pwflag); + } + /* * If we are using set_perms_posix() and the stay_setuid flag was not set, * set the real, effective and saved uids to 0 and use set_perms_nosuid() *************** *** 271,277 **** */ #if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \ !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION) ! if (!def_flag(I_STAY_SETUID) && set_perms == set_perms_posix) { if (setuid(0)) { perror("setuid(0)"); exit(1); --- 283,289 ---- */ #if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \ !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION) ! if (!def_stay_setuid && set_perms == set_perms_posix) { if (setuid(0)) { perror("setuid(0)"); exit(1); *************** *** 281,315 **** #endif /* - * Look up runas user passwd struct. If we are given a uid then - * there may be no corresponding passwd(5) entry (which is OK). - */ - if (**user_runas == '#') { - runas_pw = sudo_getpwuid(atoi(*user_runas + 1)); - if (runas_pw == NULL) { - runas_pw = emalloc(sizeof(struct passwd)); - (void) memset((VOID *)runas_pw, 0, sizeof(struct passwd)); - runas_pw->pw_uid = atoi(*user_runas + 1); - } - } else { - runas_pw = sudo_getpwnam(*user_runas); - if (runas_pw == NULL) - log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", *user_runas); - } - - /* * Look up the timestamp dir owner if one is specified. */ ! if (def_str(I_TIMESTAMPOWNER)) { struct passwd *pw; ! if (*def_str(I_TIMESTAMPOWNER) == '#') ! pw = getpwuid(atoi(def_str(I_TIMESTAMPOWNER) + 1)); else ! pw = getpwnam(def_str(I_TIMESTAMPOWNER)); if (!pw) log_error(0, "timestamp owner (%s): No such user", ! def_str(I_TIMESTAMPOWNER)); timestamp_uid = pw->pw_uid; } --- 293,310 ---- #endif /* * Look up the timestamp dir owner if one is specified. */ ! if (def_timestampowner) { struct passwd *pw; ! if (*def_timestampowner == '#') ! pw = getpwuid(atoi(def_timestampowner + 1)); else ! pw = getpwnam(def_timestampowner); if (!pw) log_error(0, "timestamp owner (%s): No such user", ! def_timestampowner); timestamp_uid = pw->pw_uid; } *************** *** 319,330 **** exit(0); } ! if (validated & VALIDATE_ERROR) log_error(0, "parse error in %s near line %d", _PATH_SUDOERS, errorlineno); /* Is root even allowed to run sudo? */ ! if (user_uid == 0 && !def_flag(I_ROOT_SUDO)) { (void) fprintf(stderr, "Sorry, %s has been configured to not allow root to run it.\n", getprogname()); --- 314,325 ---- exit(0); } ! if (ISSET(validated, VALIDATE_ERROR)) log_error(0, "parse error in %s near line %d", _PATH_SUDOERS, errorlineno); /* Is root even allowed to run sudo? */ ! if (user_uid == 0 && !def_root_sudo) { (void) fprintf(stderr, "Sorry, %s has been configured to not allow root to run it.\n", getprogname()); *************** *** 332,351 **** } /* If given the -P option, set the "preserve_groups" flag. */ ! if (sudo_mode & MODE_PRESERVE_GROUPS) ! def_flag(I_PRESERVE_GROUPS) = TRUE; /* If no command line args and "set_home" is not set, error out. */ ! if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS)) usage(1); /* May need to set $HOME to target user if we are running a command. */ ! if ((sudo_mode & MODE_RUN) && (def_flag(I_ALWAYS_SET_HOME) || ! ((sudo_mode & MODE_SHELL) && def_flag(I_SET_HOME)))) ! sudo_mode |= MODE_RESET_HOME; /* Bail if a tty is required and we don't have one. */ ! if (def_flag(I_REQUIRETTY)) { if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) log_error(NO_MAIL, "sorry, you must have a tty to run sudo"); else --- 327,346 ---- } /* If given the -P option, set the "preserve_groups" flag. */ ! if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) ! def_preserve_groups = TRUE; /* If no command line args and "set_home" is not set, error out. */ ! if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) usage(1); /* May need to set $HOME to target user if we are running a command. */ ! if (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home || ! (ISSET(sudo_mode, MODE_SHELL) && def_set_home))) ! SET(sudo_mode, MODE_RESET_HOME); /* Bail if a tty is required and we don't have one. */ ! if (def_requiretty) { if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) log_error(NO_MAIL, "sorry, you must have a tty to run sudo"); else *************** *** 355,368 **** /* Fill in passwd struct based on user we are authenticating as. */ auth_pw = get_authpw(); ! /* Require a password unless the NOPASS tag was set. */ ! if (!(validated & FLAG_NOPASS)) ! check_user(); ! /* Build up custom environment that avoids any nasty bits. */ ! new_environ = rebuild_env(sudo_mode, envp); ! if (validated & VALIDATE_OK) { /* Finally tell the user if the command did not exist. */ if (cmnd_status == NOT_FOUND_DOT) { warnx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); --- 350,376 ---- /* Fill in passwd struct based on user we are authenticating as. */ auth_pw = get_authpw(); ! /* Require a password if sudoers says so. */ ! if (!ISSET(validated, FLAG_NOPASS)) ! check_user(ISSET(validated, FLAG_CHECK_USER)); ! /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ ! if (user_uid == 0 && prev_user != NULL && strcmp(prev_user, "root") != 0) { ! struct passwd *pw; ! if ((pw = sudo_getpwnam(prev_user)) != NULL) { ! free(sudo_user.pw); ! sudo_user.pw = pw; ! } ! } ! ! /* Build a new environment that avoids any nasty bits if we have a cmnd. */ ! if (ISSET(sudo_mode, MODE_RUN)) ! new_environ = rebuild_env(envp, sudo_mode, ISSET(validated, FLAG_NOEXEC)); ! else ! new_environ = envp; ! ! if (ISSET(validated, VALIDATE_OK)) { /* Finally tell the user if the command did not exist. */ if (cmnd_status == NOT_FOUND_DOT) { warnx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); *************** *** 377,382 **** --- 385,393 ---- exit(0); else if (sudo_mode == MODE_LIST) { list_matches(); + #ifdef HAVE_LDAP + sudo_ldap_list_matches(); + #endif exit(0); } *************** *** 389,412 **** } /* Override user's umask if configured to do so. */ ! if (def_ival(I_UMASK) != 0777) ! (void) umask(def_mode(I_UMASK)); /* Restore coredumpsize resource limit. */ #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) (void) setrlimit(RLIMIT_CORE, &corelimit); #endif /* RLIMIT_CORE && !SUDO_DEVEL */ ! /* Become specified user or root. */ ! set_perms(PERM_RUNAS); /* Close the password and group files */ endpwent(); endgrent(); ! /* Install the new environment. */ environ = new_environ; /* Restore signal handlers before we exec. */ (void) sigaction(SIGINT, &saved_sa_int, NULL); (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); --- 400,441 ---- } /* Override user's umask if configured to do so. */ ! if (def_umask != 0777) ! (void) umask(def_umask); /* Restore coredumpsize resource limit. */ #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) (void) setrlimit(RLIMIT_CORE, &corelimit); #endif /* RLIMIT_CORE && !SUDO_DEVEL */ ! /* Become specified user or root if executing a command. */ ! if (ISSET(sudo_mode, MODE_RUN)) ! set_perms(PERM_FULL_RUNAS); /* Close the password and group files */ endpwent(); endgrent(); ! /* Install the real environment. */ environ = new_environ; + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + char *p; + + /* Convert /bin/sh -> -sh so shell knows it is a login shell */ + if ((p = strrchr(NewArgv[0], '/')) == NULL) + p = NewArgv[0]; + *p = '-'; + NewArgv[0] = p; + + /* Change to target user's homedir. */ + if (chdir(runas_pw->pw_dir) == -1) + warn("unable to change directory to %s", runas_pw->pw_dir); + } + + if (ISSET(sudo_mode, MODE_EDIT)) + exit(sudo_edit(NewArgc, NewArgv)); + /* Restore signal handlers before we exec. */ (void) sigaction(SIGINT, &saved_sa_int, NULL); (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); *************** *** 414,423 **** (void) sigaction(SIGCHLD, &saved_sa_chld, NULL); #ifndef PROFILING ! if ((sudo_mode & MODE_BACKGROUND) && fork() > 0) exit(0); else ! EXEC(safe_cmnd, NewArgv); /* run the command */ #else exit(0); #endif /* PROFILING */ --- 443,452 ---- (void) sigaction(SIGCHLD, &saved_sa_chld, NULL); #ifndef PROFILING ! if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) exit(0); else ! EXECV(safe_cmnd, NewArgv); /* run the command */ #else exit(0); #endif /* PROFILING */ *************** *** 426,436 **** */ warn("unable to execute %s", safe_cmnd); exit(127); ! } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) { log_auth(validated, 1); exit(1); ! } else if (validated & VALIDATE_NOT_OK) { ! if (def_flag(I_PATH_INFO)) { /* * We'd like to not leak path info at all here, but that can * *really* confuse the users. To really close the leak we'd --- 455,465 ---- */ warn("unable to execute %s", safe_cmnd); exit(127); ! } else if (ISSET(validated, FLAG_NO_USER) || (validated & FLAG_NO_HOST)) { log_auth(validated, 1); exit(1); ! } else if (ISSET(validated, VALIDATE_NOT_OK)) { ! if (def_path_info) { /* * We'd like to not leak path info at all here, but that can * *really* confuse the users. To really close the leak we'd *************** *** 469,475 **** int nohostname, rval; /* Sanity check command from user. */ ! if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) errx(1, "%s: File name too long", NewArgv[0]); #ifdef HAVE_TZSET --- 498,504 ---- int nohostname, rval; /* Sanity check command from user. */ ! if (user_cmnd == NULL && strlen(NewArgv[0]) >= PATH_MAX) errx(1, "%s: File name too long", NewArgv[0]); #ifdef HAVE_TZSET *************** *** 492,498 **** user_host = user_shost = "localhost"; else { user_host = estrdup(thost); ! if (def_flag(I_FQDN)) { /* Defer call to set_fqdn() until log_error() is safe. */ user_shost = user_host; } else { --- 521,527 ---- user_host = user_shost = "localhost"; else { user_host = estrdup(thost); ! if (def_fqdn) { /* Defer call to set_fqdn() until log_error() is safe. */ user_shost = user_host; } else { *************** *** 543,557 **** /* It is now safe to use log_error() and set_perms() */ ! /* ! * Must defer set_fqdn() until it is safe to call log_error() ! */ ! if (def_flag(I_FQDN)) ! set_fqdn(); if (nohostname) log_error(USE_ERRNO|MSG_ONLY, "can't get hostname"); /* * Get current working directory. Try as user, fall back to root. */ --- 572,587 ---- /* It is now safe to use log_error() and set_perms() */ ! if (def_fqdn) ! set_fqdn(); /* may call log_error() */ if (nohostname) log_error(USE_ERRNO|MSG_ONLY, "can't get hostname"); + set_runaspw(*user_runas); /* may call log_error() */ + if (*user_runas[0] == '#' && runas_pw->pw_name && runas_pw->pw_name[0]) + *user_runas = estrdup(runas_pw->pw_name); + /* * Get current working directory. Try as user, fall back to root. */ *************** *** 566,581 **** set_perms(PERM_ROOT); /* ! * If we were given the '-s' option (run shell) we need to redo * NewArgv and NewArgc. */ ! if ((sudo_mode & MODE_SHELL)) { char **dst, **src = NewArgv; NewArgv = (char **) emalloc2((++NewArgc + 1), sizeof(char *)); ! if (user_shell && *user_shell) { NewArgv[0] = user_shell; ! } else errx(1, "unable to determine shell"); /* copy the args from NewArgv */ --- 596,615 ---- set_perms(PERM_ROOT); /* ! * If we were given the '-e', '-i' or '-s' options we need to redo * NewArgv and NewArgc. */ ! if ((sudo_mode & (MODE_SHELL | MODE_EDIT))) { char **dst, **src = NewArgv; NewArgv = (char **) emalloc2((++NewArgc + 1), sizeof(char *)); ! if (ISSET(sudo_mode, MODE_EDIT)) ! NewArgv[0] = "sudoedit"; ! else if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) ! NewArgv[0] = runas_pw->pw_shell; ! else if (user_shell && *user_shell) NewArgv[0] = user_shell; ! else errx(1, "unable to determine shell"); /* copy the args from NewArgv */ *************** *** 587,600 **** set_loginclass(sudo_user.pw); /* Resolve the path and return. */ ! if ((sudo_mode & MODE_RUN)) { ! /* XXX - should call this as runas user, not root. */ ! rval = find_path(NewArgv[0], &user_cmnd, user_path); ! if (rval != FOUND) { ! /* Failed as root, try as invoking user. */ ! set_perms(PERM_USER); ! rval = find_path(NewArgv[0], &user_cmnd, user_path); set_perms(PERM_ROOT); } /* set user_args */ --- 621,640 ---- set_loginclass(sudo_user.pw); /* Resolve the path and return. */ ! rval = FOUND; ! user_stat = emalloc(sizeof(struct stat)); ! if (sudo_mode & (MODE_RUN | MODE_EDIT)) { ! if (ISSET(sudo_mode, MODE_RUN)) { ! /* XXX - default_runas may be modified during parsing of sudoers */ ! set_perms(PERM_RUNAS); ! rval = find_path(NewArgv[0], &user_cmnd, user_stat, user_path); set_perms(PERM_ROOT); + if (rval != FOUND) { + /* Failed as root, try as invoking user. */ + set_perms(PERM_USER); + rval = find_path(NewArgv[0], &user_cmnd, user_stat, user_path); + set_perms(PERM_ROOT); + } } /* set user_args */ *************** *** 602,609 **** char *to, **from; size_t size, n; ! /* If MODE_SHELL not set then NewArgv is contiguous so just count */ ! if (!(sudo_mode & MODE_SHELL)) { size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) + strlen(NewArgv[NewArgc-1]) + 1; } else { --- 642,649 ---- char *to, **from; size_t size, n; ! /* If we didn't realloc NewArgv it is contiguous so just count. */ ! if (!(sudo_mode & (MODE_SHELL | MODE_EDIT))) { size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) + strlen(NewArgv[NewArgc-1]) + 1; } else { *************** *** 611,617 **** size += strlen(*from) + 1; } ! /* alloc and copy. */ user_args = (char *) emalloc(size); for (to = user_args, from = NewArgv + 1; *from; from++) { n = strlcpy(to, *from, size - (to - user_args)); --- 651,657 ---- size += strlen(*from) + 1; } ! /* Alloc and build up user_args. */ user_args = (char *) emalloc(size); for (to = user_args, from = NewArgv + 1; *from; from++) { n = strlcpy(to, *from, size - (to - user_args)); *************** *** 622,629 **** } *--to = '\0'; } ! } else ! rval = FOUND; return(rval); } --- 662,672 ---- } *--to = '\0'; } ! } ! if ((user_base = strrchr(user_cmnd, '/')) != NULL) ! user_base++; ! else ! user_base = user_cmnd; return(rval); } *************** *** 642,649 **** NewArgv = argv + 1; NewArgc = argc - 1; ! if (NewArgc == 0) { /* no options and no command */ ! rval |= (MODE_IMPLIED_SHELL | MODE_SHELL); return(rval); } --- 685,699 ---- NewArgv = argv + 1; NewArgc = argc - 1; ! /* First, check to see if we were invoked as "sudoedit". */ ! if (strcmp(getprogname(), "sudoedit") == 0) { ! rval = MODE_EDIT; ! excl = 'e'; ! } else ! rval = MODE_RUN; ! ! if (NewArgc == 0 && rval == MODE_RUN) { /* no options and no command */ ! SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL)); return(rval); } *************** *** 691,711 **** usage(1); login_class = NewArgv[1]; ! def_flag(I_USE_LOGINCLASS) = TRUE; NewArgc--; NewArgv++; break; #endif case 'b': ! rval |= MODE_BACKGROUND; break; case 'v': rval = MODE_VALIDATE; if (excl && excl != 'v') usage_excl(1); excl = 'v'; break; case 'k': rval = MODE_INVALIDATE; if (excl && excl != 'k') --- 741,774 ---- usage(1); login_class = NewArgv[1]; ! def_use_loginclass = TRUE; NewArgc--; NewArgv++; break; #endif case 'b': ! SET(rval, MODE_BACKGROUND); break; + case 'e': + rval = MODE_EDIT; + if (excl && excl != 'e') + usage_excl(1); + excl = 'e'; + break; case 'v': rval = MODE_VALIDATE; if (excl && excl != 'v') usage_excl(1); excl = 'v'; break; + case 'i': + SET(rval, (MODE_LOGIN_SHELL | MODE_SHELL)); + def_env_reset = TRUE; + if (excl && excl != 'i') + usage_excl(1); + excl = 'i'; + break; case 'k': rval = MODE_INVALIDATE; if (excl && excl != 'k') *************** *** 743,767 **** excl = 'h'; break; case 's': ! rval |= MODE_SHELL; if (excl && excl != 's') usage_excl(1); excl = 's'; break; case 'H': ! rval |= MODE_RESET_HOME; break; case 'P': ! rval |= MODE_PRESERVE_GROUPS; break; case 'S': ! tgetpass_flags |= TGP_STDIN; break; case '-': NewArgc--; NewArgv++; if (rval == MODE_RUN) ! rval |= (MODE_IMPLIED_SHELL | MODE_SHELL); return(rval); case '\0': warnx("'-' requires an argument"); --- 806,830 ---- excl = 'h'; break; case 's': ! SET(rval, MODE_SHELL); if (excl && excl != 's') usage_excl(1); excl = 's'; break; case 'H': ! SET(rval, MODE_RESET_HOME); break; case 'P': ! SET(rval, MODE_PRESERVE_GROUPS); break; case 'S': ! SET(tgetpass_flags, TGP_STDIN); break; case '-': NewArgc--; NewArgv++; if (rval == MODE_RUN) ! SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL)); return(rval); case '\0': warnx("'-' requires an argument"); *************** *** 774,780 **** NewArgv++; } ! if (NewArgc > 0 && !(rval & MODE_RUN)) usage(1); return(rval); --- 837,844 ---- NewArgv++; } ! if ((NewArgc == 0 && (rval & MODE_EDIT)) || ! (NewArgc > 0 && !(rval & (MODE_RUN | MODE_EDIT)))) usage(1); return(rval); *************** *** 793,799 **** /* * Fix the mode and group on sudoers file from old default. ! * Only works if filesystem is readable/writable by root. */ if ((rootstat = stat_sudoers(_PATH_SUDOERS, &statbuf)) == 0 && SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && --- 857,863 ---- /* * Fix the mode and group on sudoers file from old default. ! * Only works if file system is readable/writable by root. */ if ((rootstat = stat_sudoers(_PATH_SUDOERS, &statbuf)) == 0 && SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && *************** *** 801,807 **** if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) { warnx("fixed mode on %s", _PATH_SUDOERS); ! statbuf.st_mode |= SUDOERS_MODE; if (statbuf.st_gid != SUDOERS_GID) { if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) { warnx("set group on %s", _PATH_SUDOERS); --- 865,871 ---- if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) { warnx("fixed mode on %s", _PATH_SUDOERS); ! SET(statbuf.st_mode, SUDOERS_MODE); if (statbuf.st_gid != SUDOERS_GID) { if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) { warnx("set group on %s", _PATH_SUDOERS); *************** *** 965,995 **** } /* * Get passwd entry for the user we are going to authenticate as. ! * By default, this is the user invoking sudo... */ static struct passwd * get_authpw() { struct passwd *pw; ! if (def_ival(I_ROOTPW)) { ! if ((pw = sudo_getpwuid(0)) == NULL) log_error(0, "uid 0 does not exist in the passwd file!"); ! } else if (def_ival(I_RUNASPW)) { ! if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEFAULT))) == NULL) log_error(0, "user %s does not exist in the passwd file!", ! def_str(I_RUNAS_DEFAULT)); ! } else if (def_ival(I_TARGETPW)) { ! if (**user_runas == '#') { ! if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL) ! log_error(0, "uid %s does not exist in the passwd file!", ! user_runas); ! } else { ! if ((pw = sudo_getpwnam(*user_runas)) == NULL) ! log_error(0, "user %s does not exist in the passwd file!", ! user_runas); ! } } else pw = sudo_user.pw; --- 1029,1087 ---- } /* + * Get passwd entry for the user we are going to run commands as. + * By default, this is "root". Updates runas_pw as a side effect. + */ + int + set_runaspw(user) + char *user; + { + if (runas_pw != NULL) { + if (user_runas != &def_runas_default) + return(TRUE); /* don't override -u option */ + free(runas_pw); + } + if (*user == '#') { + runas_pw = sudo_getpwuid(atoi(user + 1)); + if (runas_pw == NULL) { + runas_pw = emalloc(sizeof(struct passwd)); + (void) memset((VOID *)runas_pw, 0, sizeof(struct passwd)); + runas_pw->pw_uid = atoi(user + 1); + } + } else { + runas_pw = sudo_getpwnam(user); + if (runas_pw == NULL) + log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", user); + } + return(TRUE); + } + + /* * Get passwd entry for the user we are going to authenticate as. ! * By default, this is the user invoking sudo. In the most common ! * case, this matches sudo_user.pw or runas_pw. */ static struct passwd * get_authpw() { struct passwd *pw; ! if (def_rootpw) { ! if (runas_pw->pw_uid == 0) ! pw = runas_pw; ! else if ((pw = sudo_getpwuid(0)) == NULL) log_error(0, "uid 0 does not exist in the passwd file!"); ! } else if (def_runaspw) { ! if (strcmp(def_runas_default, *user_runas) == 0) ! pw = runas_pw; ! else if ((pw = sudo_getpwnam(def_runas_default)) == NULL) log_error(0, "user %s does not exist in the passwd file!", ! def_runas_default); ! } else if (def_targetpw) { ! if (runas_pw->pw_name == NULL) ! log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %lu!", ! runas_pw->pw_uid); ! pw = runas_pw; } else pw = sudo_user.pw; *************** *** 1003,1010 **** usage_excl(exit_val) int exit_val; { ! (void) fprintf(stderr, ! "Only one of the -h, -k, -K, -l, -s, -v or -V options may be used\n"); usage(exit_val); } --- 1095,1101 ---- usage_excl(exit_val) int exit_val; { ! warnx("Only one of the -e, -h, -k, -K, -l, -s, -v or -V options may be used"); usage(exit_val); } *************** *** 1015,1029 **** usage(exit_val) int exit_val; { ! ! (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s", ! "[-H] [-P] [-S] [-b] [-p prompt]\n [-u username/#uid] "); ! #ifdef HAVE_LOGIN_CAP_H ! (void) fprintf(stderr, "[-c class] "); ! #endif #ifdef HAVE_BSD_AUTH_H ! (void) fprintf(stderr, "[-a auth_type] "); #endif ! (void) fprintf(stderr, "-s | \n"); exit(exit_val); } --- 1106,1158 ---- usage(exit_val) int exit_val; { ! char **p; ! int linelen, linemax, ulen; ! static char *uvec[] = { ! " [-HPSb]", #ifdef HAVE_BSD_AUTH_H ! " [-a auth_type]", #endif ! #ifdef HAVE_LOGIN_CAP_H ! " [-c class|-]", ! #endif ! " [-p prompt]", ! " [-u username|#uid]", ! " { -e file [...] | -i | -s | }", ! NULL ! }; ! ! /* ! * For sudoedit, replace the last entry in the usage vector. ! * For sudo, print the secondary usage. ! */ ! if (strcmp(getprogname(), "sudoedit") == 0) { ! /* Replace the last entry in the usage vector. */ ! for (p = uvec; p[1] != NULL; p++) ! continue; ! *p = " file [...]"; ! } else { ! fprintf(stderr, "usage: %s -K | -L | -V | -h | -k | -l | -v\n", ! getprogname()); ! } ! ! /* ! * Print the main usage and wrap lines as needed. ! * Assumes an 80-character wide terminal, which is kind of bogus... ! */ ! ulen = (int)strlen(getprogname()) + 7; ! linemax = 80; ! linelen = linemax - ulen; ! printf("usage: %s", getprogname()); ! for (p = uvec; *p != NULL; p++) { ! if (linelen == linemax || (linelen -= strlen(*p)) >= 0) { ! fputs(*p, stdout); ! } else { ! p--; ! linelen = linemax; ! printf("\n%*s", ulen, ""); ! } ! } ! putchar('\n'); exit(exit_val); }