[BACK]Return to sudo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Diff for /src/usr.bin/sudo/Attic/sudo.c between version 1.26 and 1.27

version 1.26, 2005/06/19 22:00:08 version 1.27, 2007/07/26 16:10:16
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 1993-1996,1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>   * Copyright (c) 1993-1996,1998-2007 Todd C. Miller <Todd.Miller@courtesan.com>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 27 
Line 27 
 # include <floss.h>  # include <floss.h>
 #endif  #endif
   
 #include "config.h"  #include <config.h>
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
Line 69 
Line 69 
 #include <fcntl.h>  #include <fcntl.h>
 #include <signal.h>  #include <signal.h>
 #include <grp.h>  #include <grp.h>
 #include <time.h>  #if TIME_WITH_SYS_TIME
   # include <time.h>
   #endif
   #ifdef HAVE_SETLOCALE
   # include <locale.h>
   #endif
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netdb.h>  #include <netdb.h>
 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)  #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
Line 87 
Line 92 
 #  define LOGIN_DEFROOTCLASS    "daemon"  #  define LOGIN_DEFROOTCLASS    "daemon"
 # endif  # endif
 #endif  #endif
   #ifdef HAVE_PROJECT_H
   # include <project.h>
   # include <sys/task.h>
   #endif
   
 #include "sudo.h"  #include "sudo.h"
 #include "interfaces.h"  #include "interfaces.h"
 #include "version.h"  #include "version.h"
   
 #ifndef lint  #ifndef lint
 static const char rcsid[] = "$Sudo: sudo.c,v 1.370 2004/08/24 18:01:13 millert Exp $";  __unused __unused static const char rcsid[] = "$Sudo: sudo.c,v 1.369.2.26 2007/07/22 19:21:01 millert Exp $";
 #endif /* lint */  #endif /* lint */
   
 /*  /*
  * Prototypes   * Prototypes
  */   */
 static int init_vars                    __P((int));  static int init_vars                    __P((int, char **));
 static int parse_args                   __P((int, char **));  static int parse_args                   __P((int, char **));
 static void check_sudoers               __P((void));  static void check_sudoers               __P((void));
 static void initial_setup               __P((void));  static void initial_setup               __P((void));
 static void set_loginclass              __P((struct passwd *));  static void set_loginclass              __P((struct passwd *));
 static void usage                       __P((int));  static void set_project                 __P((struct passwd *));
   static void usage                       __P((int))
                                               __attribute__((__noreturn__));
   static void usage_excl                  __P((int))
                                               __attribute__((__noreturn__));
 static void usage_excl                  __P((int));  static void usage_excl                  __P((int));
 static struct passwd *get_authpw        __P((void));  static struct passwd *get_authpw        __P((void));
 extern int sudo_edit                    __P((int, char **));  extern int sudo_edit                    __P((int, char **, char **));
 extern void list_matches                __P((void));  extern void list_matches                __P((void));
 extern char **rebuild_env               __P((char **, int, int));  extern char **rebuild_env               __P((char **, int, int));
 extern char **zero_env                  __P((char **));  extern void validate_env_vars           __P((struct list_member *));
   extern char **insert_env_vars           __P((char **, struct list_member *));
 extern struct passwd *sudo_getpwnam     __P((const char *));  extern struct passwd *sudo_getpwnam     __P((const char *));
 extern struct passwd *sudo_getpwuid     __P((uid_t));  extern struct passwd *sudo_getpwuid     __P((uid_t));
 extern struct passwd *sudo_pwdup        __P((const struct passwd *));  extern struct passwd *sudo_pwdup        __P((const struct passwd *));
Line 139 
Line 153 
 char *login_style;  char *login_style;
 #endif /* HAVE_BSD_AUTH_H */  #endif /* HAVE_BSD_AUTH_H */
 sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;  sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;
 void (*set_perms) __P((int));  
   
   
 int  int
Line 153 
Line 166 
     int cmnd_status;      int cmnd_status;
     int sudo_mode;      int sudo_mode;
     int pwflag;      int pwflag;
     char **new_environ;  
     sigaction_t sa;      sigaction_t sa;
     extern int printmatches;      extern int printmatches;
     extern char **environ;      extern char **environ;
   
   #ifdef HAVE_SETLOCALE
       setlocale(LC_ALL, "");
   #endif
   
     Argv = argv;      Argv = argv;
     if ((Argc = argc) < 1)      if ((Argc = argc) < 1)
         usage(1);          usage(1);
Line 170 
Line 186 
 # endif  # endif
 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */  #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
   
     /* Zero out the environment. */  
     environ = zero_env(envp);  
   
     if (geteuid() != 0)      if (geteuid() != 0)
         errx(1, "must be setuid root");          errx(1, "must be setuid root");
   
Line 192 
Line 205 
     (void) sigaction(SIGCHLD, &sa, &saved_sa_chld);      (void) sigaction(SIGCHLD, &sa, &saved_sa_chld);
   
     /*      /*
      * Turn off core dumps, close open files and setup set_perms().       * Turn off core dumps and close open files.
      */       */
     initial_setup();      initial_setup();
     setpwent();      setpwent();
Line 217 
Line 230 
                 (void) printf("Sudo version %s\n", version);                  (void) printf("Sudo version %s\n", version);
                 if (getuid() == 0) {                  if (getuid() == 0) {
                     putchar('\n');                      putchar('\n');
                       (void) printf("Sudoers path: %s\n", _PATH_SUDOERS);
                     dump_auth_methods();                      dump_auth_methods();
                     dump_defaults();                      dump_defaults();
                     dump_interfaces();                      dump_interfaces();
Line 250 
Line 264 
     if (user_cmnd == NULL && NewArgc == 0)      if (user_cmnd == NULL && NewArgc == 0)
         usage(1);          usage(1);
   
     cmnd_status = init_vars(sudo_mode);      cmnd_status = init_vars(sudo_mode, environ);
   
 #ifdef HAVE_LDAP  #ifdef HAVE_LDAP
     validated = sudo_ldap_check(pwflag);      validated = sudo_ldap_check(pwflag);
Line 276 
Line 290 
         validated = sudoers_lookup(pwflag);          validated = sudoers_lookup(pwflag);
     }      }
     if (safe_cmnd == NULL)      if (safe_cmnd == NULL)
         safe_cmnd = user_cmnd;          safe_cmnd = estrdup(user_cmnd);
   
     /*      /*
      * 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()  
      * instead of set_perms_posix().  
      */  
 #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);  
         }  
         set_perms = set_perms_nosuid;  
     }  
 #endif  
   
     /*  
      * Look up the timestamp dir owner if one is specified.       * Look up the timestamp dir owner if one is specified.
      */       */
     if (def_timestampowner) {      if (def_timestampowner) {
Line 336 
Line 334 
     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs)      if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs)
         usage(1);          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.  */      /* Bail if a tty is required and we don't have one.  */
     if (def_requiretty) {      if (def_requiretty) {
         if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1)          if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1)
Line 349 
Line 342 
             (void) close(fd);              (void) close(fd);
     }      }
   
       /* User may have overriden environment resetting via the -E flag. */
       if (ISSET(sudo_mode, MODE_PRESERVE_ENV) && ISSET(validated, FLAG_SETENV))
           def_env_reset = FALSE;
   
       /* Build a new environment that avoids any nasty bits. */
       environ = rebuild_env(environ, sudo_mode, ISSET(validated, FLAG_NOEXEC));
   
     /* Fill in passwd struct based on user we are authenticating as.  */      /* Fill in passwd struct based on user we are authenticating as.  */
     auth_pw = get_authpw();      auth_pw = get_authpw();
   
     /* Require a password if sudoers says so.  */      /* Require a password if sudoers says so.  */
     if (!ISSET(validated, FLAG_NOPASS))      if (!ISSET(validated, FLAG_NOPASS))
         check_user(ISSET(validated, FLAG_CHECK_USER));          check_user(validated);
   
     /* If run as root with SUDO_USER set, set sudo_user.pw to that 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) {      if (user_uid == 0 && prev_user != NULL && strcmp(prev_user, "root") != 0) {
             struct passwd *pw;              struct passwd *pw;
   
             if ((pw = sudo_getpwnam(prev_user)) != NULL) {              if ((pw = sudo_getpwnam(prev_user)) != NULL) {
                     free(sudo_user.pw);                      efree(sudo_user.pw);
                     sudo_user.pw = 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)) {      if (ISSET(validated, VALIDATE_OK)) {
         /* Finally tell the user if the command did not exist. */          /* Finally tell the user if the command did not exist. */
         if (cmnd_status == NOT_FOUND_DOT) {          if (cmnd_status == NOT_FOUND_DOT) {
Line 382 
Line 376 
             exit(1);              exit(1);
         }          }
   
           /* If user specified env vars make sure sudoers allows it. */
           if (ISSET(sudo_mode, MODE_RUN) && !ISSET(validated, FLAG_SETENV)) {
               if (ISSET(sudo_mode, MODE_PRESERVE_ENV))
                   log_error(NO_MAIL,
                       "sorry, you are not allowed to preserve the environment");
               else
                   validate_env_vars(sudo_user.env_vars);
           }
   
         log_auth(validated, 1);          log_auth(validated, 1);
         if (sudo_mode == MODE_VALIDATE)          if (sudo_mode == MODE_VALIDATE)
             exit(0);              exit(0);
Line 410 
Line 413 
         endpwent();          endpwent();
         endgrent();          endgrent();
   
         /* Install the real environment. */  
         environ = new_environ;  
   
         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {          if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
             char *p;              char *p;
   
Line 428 
Line 428 
         }          }
   
         if (ISSET(sudo_mode, MODE_EDIT))          if (ISSET(sudo_mode, MODE_EDIT))
             exit(sudo_edit(NewArgc, NewArgv));              exit(sudo_edit(NewArgc, NewArgv, envp));
   
           /* Insert user-specified environment variables. */
           environ = insert_env_vars(environ, sudo_user.env_vars);
   
         /* Restore signal handlers before we exec. */          /* Restore signal handlers before we exec. */
         (void) sigaction(SIGINT, &saved_sa_int, NULL);          (void) sigaction(SIGINT, &saved_sa_int, NULL);
         (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);          (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
Line 440 
Line 443 
         if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0)          if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0)
             exit(0);              exit(0);
         else          else
             EXECV(safe_cmnd, NewArgv);  /* run the command */              execve(safe_cmnd, NewArgv, environ);
 #else  #else
         exit(0);          exit(0);
 #endif /* PROFILING */  #endif /* PROFILING */
         /*          /*
          * If we got here then the exec() failed...           * If we got here then the exec() failed...
          */           */
           if (errno == ENOEXEC) {
               NewArgv--;                  /* at least one extra slot... */
               NewArgv[0] = "sh";
               NewArgv[1] = safe_cmnd;
               execve(_PATH_BSHELL, NewArgv, environ);
           }
         warn("unable to execute %s", safe_cmnd);          warn("unable to execute %s", safe_cmnd);
         exit(127);          exit(127);
     } else if (ISSET(validated, FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {      } else if (ISSET(validated, FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {
Line 485 
Line 494 
  * load the ``interfaces'' array.   * load the ``interfaces'' array.
  */   */
 static int  static int
 init_vars(sudo_mode)  init_vars(sudo_mode, envp)
     int sudo_mode;      int sudo_mode;
       char **envp;
 {  {
     char *p, thost[MAXHOSTNAMELEN];      char *p, **ep, thost[MAXHOSTNAMELEN];
     int nohostname, rval;      int nohostname, rval;
   
     /* Sanity check command from user. */      /* Sanity check command from user. */
Line 536 
Line 546 
     } else      } else
         user_tty = "unknown";          user_tty = "unknown";
   
       for (ep = envp; *ep; ep++) {
           switch (**ep) {
               case 'P':
                   if (strncmp("PATH=", *ep, 5) == 0)
                       user_path = *ep + 5;
                   break;
               case 'S':
                   if (strncmp("SHELL=", *ep, 6) == 0)
                       user_shell = *ep + 6;
                   else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
                       user_prompt = *ep + 12;
                   else if (strncmp("SUDO_USER=", *ep, 10) == 0)
                       prev_user = *ep + 10;
                   break;
   
               }
       }
   
     /*      /*
      * Get a local copy of the user's struct passwd with the shadow password       * Get a local copy of the user's struct passwd with the shadow password
      * if necessary.  It is assumed that euid is 0 at this point so we       * if necessary.  It is assumed that euid is 0 at this point so we
Line 566 
Line 594 
   
     /* It is now safe to use log_error() and set_perms() */      /* It is now safe to use log_error() and set_perms() */
   
   #ifdef HAVE_GETGROUPS
       if ((user_ngroups = getgroups(0, NULL)) > 0) {
           user_groups = emalloc2(user_ngroups, sizeof(gid_t));
           if (getgroups(user_ngroups, user_groups) < 0)
               log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
       } else
           user_ngroups = 0;
   #endif
   
     if (def_fqdn)      if (def_fqdn)
         set_fqdn();                     /* may call log_error() */          set_fqdn();                     /* may call log_error() */
   
Line 596 
Line 633 
     if ((sudo_mode & (MODE_SHELL | MODE_EDIT))) {      if ((sudo_mode & (MODE_SHELL | MODE_EDIT))) {
         char **dst, **src = NewArgv;          char **dst, **src = NewArgv;
   
         NewArgv = (char **) emalloc2((++NewArgc + 1), sizeof(char *));          /* Allocate an extra slot for execve() failure (ENOEXEC). */
           NewArgv = (char **) emalloc2((++NewArgc + 2), sizeof(char *));
           NewArgv++;
         if (ISSET(sudo_mode, MODE_EDIT))          if (ISSET(sudo_mode, MODE_EDIT))
             NewArgv[0] = "sudoedit";              NewArgv[0] = "sudoedit";
         else if (ISSET(sudo_mode, MODE_LOGIN_SHELL))          else if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
Line 608 
Line 647 
   
         /* copy the args from NewArgv */          /* copy the args from NewArgv */
         for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)          for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)
             ;              continue;
     }      }
   
     /* Set login class if applicable. */      /* Set login class if applicable. */
     set_loginclass(sudo_user.pw);      set_loginclass(sudo_user.pw);
   
       /* Set project if applicable. */
       set_project(runas_pw);
   
     /* Resolve the path and return. */      /* Resolve the path and return. */
     rval = FOUND;      rval = FOUND;
     user_stat = emalloc(sizeof(struct stat));      user_stat = emalloc(sizeof(struct stat));
Line 686 
Line 728 
     } else      } else
         rval = MODE_RUN;          rval = MODE_RUN;
   
     if (NewArgc == 0 && rval == MODE_RUN) {     /* no options and no command */      while (NewArgc > 0) {
         SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL));          if (NewArgv[0][0] == '-') {
         return(rval);              if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0')
     }                  warnx("please use single character options");
   
     while (NewArgc > 0 && NewArgv[0][0] == '-') {              switch (NewArgv[0][1]) {
         if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0')                  case 'p':
             warnx("please use single character options");                      /* Must have an associated prompt. */
                       if (NewArgv[1] == NULL)
                           usage(1);
   
         switch (NewArgv[0][1]) {                      user_prompt = NewArgv[1];
             case 'p':  
                 /* Must have an associated prompt. */  
                 if (NewArgv[1] == NULL)  
                     usage(1);  
   
                 user_prompt = NewArgv[1];                      NewArgc--;
                       NewArgv++;
                       break;
                   case 'u':
                       /* Must have an associated runas user. */
                       if (NewArgv[1] == NULL)
                           usage(1);
   
                 NewArgc--;                      user_runas = &NewArgv[1];
                 NewArgv++;  
                 break;  
             case 'u':  
                 /* Must have an associated runas user. */  
                 if (NewArgv[1] == NULL)  
                     usage(1);  
   
                 user_runas = &NewArgv[1];                      NewArgc--;
                       NewArgv++;
                 NewArgc--;                      break;
                 NewArgv++;  
                 break;  
 #ifdef HAVE_BSD_AUTH_H  #ifdef HAVE_BSD_AUTH_H
             case 'a':                  case 'a':
                 /* Must have an associated authentication style. */                      /* Must have an associated authentication style. */
                 if (NewArgv[1] == NULL)                      if (NewArgv[1] == NULL)
                     usage(1);                          usage(1);
   
                 login_style = NewArgv[1];                      login_style = NewArgv[1];
   
                 NewArgc--;                      NewArgc--;
                 NewArgv++;                      NewArgv++;
                 break;                      break;
 #endif  #endif
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
             case 'c':                  case 'c':
                 /* Must have an associated login class. */                      /* Must have an associated login class. */
                 if (NewArgv[1] == NULL)                      if (NewArgv[1] == NULL)
                     usage(1);                          usage(1);
   
                 login_class = NewArgv[1];                      login_class = NewArgv[1];
                 def_use_loginclass = TRUE;                      def_use_loginclass = TRUE;
   
                 NewArgc--;                      NewArgc--;
                 NewArgv++;                      NewArgv++;
                 break;                      break;
 #endif  #endif
             case 'b':                  case 'b':
                 SET(rval, MODE_BACKGROUND);                      SET(rval, MODE_BACKGROUND);
                 break;                      break;
             case 'e':                  case 'e':
                 rval = MODE_EDIT;                      rval = MODE_EDIT;
                 if (excl && excl != 'e')                      if (excl && excl != 'e')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'e';                      excl = 'e';
                 break;                      break;
             case 'v':                  case 'v':
                 rval = MODE_VALIDATE;                      rval = MODE_VALIDATE;
                 if (excl && excl != 'v')                      if (excl && excl != 'v')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'v';                      excl = 'v';
                 break;                      break;
             case 'i':                  case 'i':
                 SET(rval, (MODE_LOGIN_SHELL | MODE_SHELL));                      SET(rval, (MODE_LOGIN_SHELL | MODE_SHELL));
                 def_env_reset = TRUE;                      def_env_reset = TRUE;
                 if (excl && excl != 'i')                      if (excl && excl != 'i')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'i';                      excl = 'i';
                 break;                      break;
             case 'k':                  case 'k':
                 rval = MODE_INVALIDATE;                      rval = MODE_INVALIDATE;
                 if (excl && excl != 'k')                      if (excl && excl != 'k')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'k';                      excl = 'k';
                 break;                      break;
             case 'K':                  case 'K':
                 rval = MODE_KILL;                      rval = MODE_KILL;
                 if (excl && excl != 'K')                      if (excl && excl != 'K')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'K';                      excl = 'K';
                 break;                      break;
             case 'L':                  case 'L':
                 rval = MODE_LISTDEFS;                      rval = MODE_LISTDEFS;
                 if (excl && excl != 'L')                      if (excl && excl != 'L')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'L';                      excl = 'L';
                 break;                      break;
             case 'l':                  case 'l':
                 rval = MODE_LIST;                      rval = MODE_LIST;
                 if (excl && excl != 'l')                      if (excl && excl != 'l')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'l';                      excl = 'l';
                 break;                      break;
             case 'V':                  case 'V':
                 rval = MODE_VERSION;                      rval = MODE_VERSION;
                 if (excl && excl != 'V')                      if (excl && excl != 'V')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'V';                      excl = 'V';
                 break;                      break;
             case 'h':                  case 'h':
                 rval = MODE_HELP;                      rval = MODE_HELP;
                 if (excl && excl != 'h')                      if (excl && excl != 'h')
                     usage_excl(1);                          usage_excl(1);
                 excl = 'h';                      excl = 'h';
                 break;                      break;
             case 's':                  case 's':
                 SET(rval, MODE_SHELL);                      SET(rval, MODE_SHELL);
                 if (excl && excl != 's')                      if (excl && excl != 's')
                     usage_excl(1);                          usage_excl(1);
                 excl = 's';                      excl = 's';
                 break;                      break;
             case 'H':                  case 'H':
                 SET(rval, MODE_RESET_HOME);                      SET(rval, MODE_RESET_HOME);
                 break;                      break;
             case 'P':                  case 'P':
                 SET(rval, MODE_PRESERVE_GROUPS);                      SET(rval, MODE_PRESERVE_GROUPS);
                 break;                      break;
             case 'S':                  case 'S':
                 SET(tgetpass_flags, TGP_STDIN);                      SET(tgetpass_flags, TGP_STDIN);
                 break;                      break;
             case '-':                  case 'E':
                 NewArgc--;                      SET(rval, MODE_PRESERVE_ENV);
                 NewArgv++;                      break;
                 if (rval == MODE_RUN)                  case '-':
                     SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL));                      NewArgc--;
                 return(rval);                      NewArgv++;
             case '\0':                      goto args_done;
                 warnx("'-' requires an argument");                  case '\0':
                 usage(1);                      warnx("'-' requires an argument");
             default:                      usage(1);
                 warnx("illegal option `%s'", NewArgv[0]);                  default:
                 usage(1);                      warnx("illegal option `%s'", NewArgv[0]);
                       usage(1);
               }
           } else if (NewArgv[0][0] != '/' && strchr(NewArgv[0], '=') != NULL) {
               /* Could be an environment variable. */
               struct list_member *ev;
               ev = emalloc(sizeof(*ev));
               ev->value = NewArgv[0];
               ev->next = sudo_user.env_vars;
               sudo_user.env_vars = ev;
           } else {
               /* Not an arg */
               break;
         }          }
         NewArgc--;          NewArgc--;
         NewArgv++;          NewArgv++;
     }      }
   args_done:
   
       if (ISSET(rval, MODE_EDIT) &&
           (ISSET(rval, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) {
           if (ISSET(rval, MODE_PRESERVE_ENV))
               warnx("the `-E' option is not valid in edit mode");
           if (sudo_user.env_vars != NULL)
               warnx("you may not specify environment variables in edit mode");
           usage(1);
       }
   
     if (user_runas != NULL && !ISSET(rval, (MODE_EDIT|MODE_RUN))) {      if (user_runas != NULL && !ISSET(rval, (MODE_EDIT|MODE_RUN))) {
         if (excl != '\0')          if (excl != '\0')
             warnx("the `-u' and '-%c' options may not be used together", excl);              warnx("the `-u' and '-%c' options may not be used together", excl);
         usage(1);          usage(1);
     }      }
   
     if ((NewArgc == 0 && (rval & MODE_EDIT)) ||      if ((NewArgc == 0 && (rval & MODE_EDIT)) ||
         (NewArgc > 0 && !(rval & (MODE_RUN | MODE_EDIT))))          (NewArgc > 0 && !(rval & (MODE_RUN | MODE_EDIT))))
         usage(1);          usage(1);
       if (NewArgc == 0 && rval == MODE_RUN)
           SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL));
   
     return(rval);      return(rval);
 }  }
Line 892 
Line 953 
         log_error(0, "%s is zero length", _PATH_SUDOERS);          log_error(0, "%s is zero length", _PATH_SUDOERS);
     else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)      else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
         log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS,          log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS,
             (statbuf.st_mode & 07777), SUDOERS_MODE);              (unsigned int) (statbuf.st_mode & 07777),
               (unsigned int) SUDOERS_MODE);
     else if (statbuf.st_uid != SUDOERS_UID)      else if (statbuf.st_uid != SUDOERS_UID)
         log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS,          log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS,
             (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID);              (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID);
Line 921 
Line 983 
   
 /*  /*
  * Close all open files (except std*) and turn off core dumps.   * Close all open files (except std*) and turn off core dumps.
  * Also sets the set_perms() pointer to the correct function.  
  */   */
 static void  static void
 initial_setup()  initial_setup()
 {  {
       int miss[3], devnull = -1;
 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)  #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
     struct rlimit rl;      struct rlimit rl;
   
Line 938 
Line 1000 
     (void) setrlimit(RLIMIT_CORE, &rl);      (void) setrlimit(RLIMIT_CORE, &rl);
 #endif /* RLIMIT_CORE && !SUDO_DEVEL */  #endif /* RLIMIT_CORE && !SUDO_DEVEL */
   
     closefrom(STDERR_FILENO + 1);  
   
     /*      /*
      * Make set_perms point to the correct function.       * stdin, stdout and stderr must be open; set them to /dev/null
      * If we are using setresuid() or setreuid() we only need to set this       * if they are closed and close all other fds.
      * once.  If we are using POSIX saved uids we will switch to  
      * set_perms_nosuid after sudoers has been parsed if the "stay_suid"  
      * option is not set.  
      */       */
 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID)      miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1;
     set_perms = set_perms_suid;      miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1;
 #else      miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1;
 # if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)      if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) {
     if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)          if ((devnull = open(_PATH_DEVNULL, O_RDWR, 0644)) != -1) {
         set_perms = set_perms_posix;              if (miss[STDIN_FILENO])
     else                  (void) dup2(devnull, STDIN_FILENO);
 # endif              if (miss[STDOUT_FILENO])
         set_perms = set_perms_nosuid;                  (void) dup2(devnull, STDOUT_FILENO);
 #endif /* HAVE_SETRESUID || HAVE_SETREUID */              if (miss[STDERR_FILENO])
                   (void) dup2(devnull, STDERR_FILENO);
           }
       }
       closefrom(STDERR_FILENO + 1);
 }  }
   
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
Line 1001 
Line 1062 
 }  }
 #endif /* HAVE_LOGIN_CAP_H */  #endif /* HAVE_LOGIN_CAP_H */
   
   #ifdef HAVE_PROJECT_H
   static void
   set_project(pw)
       struct passwd *pw;
   {
       int errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
       int errval;
       struct project proj;
       struct project *resultp = '\0';
       char buf[1024];
   
       /*
        * Collect the default project for the user and settaskid
        */
       setprojent();
       if (resultp = getdefaultproj(pw->pw_name, &proj, buf, sizeof(buf))) {
           errval = setproject(resultp->pj_name, pw->pw_name, TASK_NORMAL);
           if (errval != 0) {
               switch(errval) {
               case SETPROJ_ERR_TASK:
                   if (errno == EAGAIN)
                       log_error(errflags, "resource control limit has been reached");
                   else if (errno == ESRCH)
                       log_error(errflags, "user \"%s\" is not a member of "
                           "project \"%s\"", pw->pw_name, resultp->pj_name);
                   else if (errno == EACCES)
                       log_error(errflags, "the invoking task is final");
                   else
                       log_error(errflags, "could not join project \"%s\"",
                           resultp->pj_name);
                   break;
               case SETPROJ_ERR_POOL:
                   if (errno == EACCES)
                       log_error(errflags, "no resource pool accepting "
                               "default bindings exists for project \"%s\"",
                               resultp->pj_name);
                   else if (errno == ESRCH)
                       log_error(errflags, "specified resource pool does "
                               "not exist for project \"%s\"", resultp->pj_name);
                   else
                       log_error(errflags, "could not bind to default "
                               "resource pool for project \"%s\"", resultp->pj_name);
                   break;
               default:
                   if (errval <= 0) {
                       log_error(errflags, "setproject failed for project \"%s\"",
                           resultp->pj_name);
                   } else {
                       log_error(errflags, "warning, resource control assignment "
                           "failed for project \"%s\"", resultp->pj_name);
                   }
               }
           }
       } else {
           log_error(errflags, "getdefaultproj() error: %s", strerror(errno));
       }
       endprojent();
   }
   #else
   static void
   set_project(pw)
       struct passwd *pw;
   {
   }
   #endif /* HAVE_PROJECT_H */
   
 /*  /*
  * 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.
  */   */
Line 1015 
Line 1142 
             "unable to lookup %s via gethostbyname()", user_host);              "unable to lookup %s via gethostbyname()", user_host);
     } else {      } else {
         if (user_shost != user_host)          if (user_shost != user_host)
             free(user_shost);              efree(user_shost);
         free(user_host);          efree(user_host);
         user_host = estrdup(hp->h_name);          user_host = estrdup(hp->h_name);
     }      }
     if ((p = strchr(user_host, '.'))) {      if ((p = strchr(user_host, '.'))) {
Line 1039 
Line 1166 
     if (runas_pw != NULL) {      if (runas_pw != NULL) {
         if (user_runas != &def_runas_default)          if (user_runas != &def_runas_default)
             return(TRUE);               /* don't override -u option */              return(TRUE);               /* don't override -u option */
         free(runas_pw);          efree(runas_pw);
     }      }
     if (*user == '#') {      if (*user == '#') {
         runas_pw = sudo_getpwuid(atoi(user + 1));          runas_pw = sudo_getpwuid(atoi(user + 1));
Line 1095 
Line 1222 
 usage_excl(exit_val)  usage_excl(exit_val)
     int exit_val;      int exit_val;
 {  {
     warnx("Only one of the -e, -h, -k, -K, -l, -s, -v or -V options may be used");      warnx("Only one of the -e, -h, i, -k, -K, -l, -s, -v or -V options may be used");
     usage(exit_val);      usage(exit_val);
 }  }
   
Line 1106 
Line 1233 
 usage(exit_val)  usage(exit_val)
     int exit_val;      int exit_val;
 {  {
     char **p;      char **p, **uvec[4];
     int linelen, linemax, ulen;      int i, linelen, linemax, ulen;
     static char *uvec[] = {      static char *uvec1[] = {
         " [-HPSb]",          " -h | -K | -k | -L | -l | -V | -v",
           NULL
       };
       static char *uvec2[] = {
           " [-bEHPS]",
 #ifdef HAVE_BSD_AUTH_H  #ifdef HAVE_BSD_AUTH_H
         " [-a auth_type]",          " [-a auth_type]",
 #endif  #endif
Line 1118 
Line 1249 
 #endif  #endif
         " [-p prompt]",          " [-p prompt]",
         " [-u username|#uid]",          " [-u username|#uid]",
         " { -e file [...] | -i | -s | <command> }",          " [VAR=value]",
           " {-i | -s | <command>}",
         NULL          NULL
     };      };
       static char *uvec3[] = {
           " -e",
           " [-S]",
   #ifdef HAVE_BSD_AUTH_H
           " [-a auth_type]",
   #endif
   #ifdef HAVE_LOGIN_CAP_H
           " [-c class|-]",
   #endif
           " [-p prompt]",
           " [-u username|#uid]",
           " file ...",
           NULL
       };
   
     /*      /*
      * For sudoedit, replace the last entry in the usage vector.       * Use usage vectors appropriate to the progname.
      * For sudo, print the secondary usage.  
      */       */
     if (strcmp(getprogname(), "sudoedit") == 0) {      if (strcmp(getprogname(), "sudoedit") == 0) {
         /* Replace the last entry in the usage vector. */          uvec[0] = uvec3 + 1;
         for (p = uvec; p[1] != NULL; p++)          uvec[1] = NULL;
             continue;  
         *p = " file [...]";  
     } else {      } else {
         fprintf(stderr, "usage: %s -K | -L | -V | -h | -k | -l | -v\n",          uvec[0] = uvec1;
             getprogname());          uvec[1] = uvec2;
           uvec[2] = uvec3;
           uvec[3] = NULL;
     }      }
   
     /*      /*
      * Print the main usage and wrap lines as needed.       * Print usage and wrap lines as needed.
      * Assumes an 80-character wide terminal, which is kind of bogus...       * Assumes an 80-character wide terminal, which is kind of bogus...
      */       */
     ulen = (int)strlen(getprogname()) + 7;      ulen = (int)strlen(getprogname()) + 7;
     linemax = 80;      linemax = 80;
     linelen = linemax - ulen;      for (i = 0; uvec[i] != NULL; i++) {
     printf("usage: %s", getprogname());          linelen = linemax - ulen;
     for (p = uvec; *p != NULL; p++) {          printf("usage: %s", getprogname());
         if (linelen == linemax || (linelen -= strlen(*p)) >= 0) {          for (p = uvec[i]; *p != NULL; p++) {
             fputs(*p, stdout);              if (linelen == linemax || (linelen -= strlen(*p)) >= 0) {
         } else {                  fputs(*p, stdout);
             p--;              } else {
             linelen = linemax;                  p--;
             printf("\n%*s", ulen, "");                  linelen = linemax;
                   printf("\n%*s", ulen, "");
               }
         }          }
           putchar('\n');
     }      }
     putchar('\n');  
     exit(exit_val);      exit(exit_val);
 }  }

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.27