[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.9 and 1.9.2.1

version 1.9, 2000/12/15 14:35:58 version 1.9.2.1, 2002/01/18 17:20:23
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 1994-1996,1998-2000 Todd C. Miller <Todd.Miller@courtesan.com>   * Copyright (c) 1993-1996,1998-2002 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
Line 39 
Line 39 
   
 #include "config.h"  #include "config.h"
   
   #include <sys/types.h>
   #include <sys/stat.h>
   #include <sys/param.h>
   #include <sys/socket.h>
   #ifdef HAVE_SETRLIMIT
   # include <sys/time.h>
   # include <sys/resource.h>
   #endif
 #include <stdio.h>  #include <stdio.h>
 #ifdef STDC_HEADERS  #ifdef STDC_HEADERS
 #include <stdlib.h>  # include <stdlib.h>
   # include <stddef.h>
   #else
   # ifdef HAVE_STDLIB_H
   #  include <stdlib.h>
   # endif
 #endif /* STDC_HEADERS */  #endif /* STDC_HEADERS */
 #ifdef HAVE_UNISTD_H  
 #include <unistd.h>  
 #endif /* HAVE_UNISTD_H */  
 #ifdef HAVE_STRING_H  #ifdef HAVE_STRING_H
 #include <string.h>  # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
   #  include <memory.h>
   # endif
   # include <string.h>
   #else
   # ifdef HAVE_STRINGS_H
   #  include <strings.h>
   # endif
 #endif /* HAVE_STRING_H */  #endif /* HAVE_STRING_H */
 #ifdef HAVE_STRINGS_H  #ifdef HAVE_UNISTD_H
 #include <strings.h>  # include <unistd.h>
 #endif /* HAVE_STRINGS_H */  #endif /* HAVE_UNISTD_H */
 #include <pwd.h>  #include <pwd.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <signal.h>  #include <signal.h>
 #include <grp.h>  #include <grp.h>
 #include <time.h>  #include <time.h>
 #include <sys/types.h>  
 #include <sys/stat.h>  
 #include <sys/param.h>  
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netdb.h>  #include <netdb.h>
 #ifdef HAVE_SETRLIMIT  
 #include <sys/time.h>  
 #include <sys/resource.h>  
 #endif  
 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)  #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
 # ifdef __hpux  # ifdef __hpux
 #  undef MAXINT  #  undef MAXINT
Line 87 
Line 97 
 #include "interfaces.h"  #include "interfaces.h"
 #include "version.h"  #include "version.h"
   
 #ifndef STDC_HEADERS  
 extern char *getenv     __P((char *));  
 #endif /* STDC_HEADERS */  
   
 #ifndef lint  #ifndef lint
 static const char rcsid[] = "$Sudo: sudo.c,v 1.278 2000/03/24 20:13:12 millert Exp $";  static const char rcsid[] = "$Sudo: sudo.c,v 1.318 2002/01/15 23:43:59 millert Exp $";
 #endif /* lint */  #endif /* lint */
   
 /*  /*
  * Local type declarations  
  */  
 struct env_table {  
     char *name;  
     int len;  
 };  
   
 /*  
  * Prototypes   * Prototypes
  */   */
 static int  parse_args                  __P((void));  
 static void usage                       __P((int));  
 static void usage_excl                  __P((int));  
 static void check_sudoers               __P((void));  
 static int init_vars                    __P((int));  static int init_vars                    __P((int));
 static void set_loginclass              __P((struct passwd *));  static int parse_args                   __P((void));
 static void add_env                     __P((int));  static void check_sudoers               __P((void));
 static void clean_env                   __P((char **, struct env_table *));  
 static void initial_setup               __P((void));  static void initial_setup               __P((void));
   static void set_loginclass              __P((struct passwd *));
   static void usage                       __P((int));
   static void usage_excl                  __P((int));
 static struct passwd *get_authpw        __P((void));  static struct passwd *get_authpw        __P((void));
 extern struct passwd *sudo_getpwuid     __P((uid_t));  
 extern struct passwd *sudo_getpwnam     __P((const char *));  
 extern void list_matches                __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   * Globals
Line 134 
Line 132 
 int num_interfaces;  int num_interfaces;
 int tgetpass_flags;  int tgetpass_flags;
 extern int errorlineno;  extern int errorlineno;
 static char *runas_homedir = NULL;      /* XXX */  
 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)  #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
 static struct rlimit corelimit;  static struct rlimit corelimit;
 #endif /* RLIMIT_CORE */  #endif /* RLIMIT_CORE */
Line 144 
Line 141 
 #ifdef HAVE_BSD_AUTH_H  #ifdef HAVE_BSD_AUTH_H
 char *login_style;  char *login_style;
 #endif /* HAVE_BSD_AUTH_H */  #endif /* HAVE_BSD_AUTH_H */
   void (*set_perms) __P((int, int));
   
 /*  
  * Table of "bad" envariables to remove and len for strncmp()  
  */  
 static struct env_table badenv_table[] = {  
     { "IFS=", 4 },  
     { "LOCALDOMAIN=", 12 },  
     { "RES_OPTIONS=", 12 },  
     { "HOSTALIASES=", 12 },  
     { "LD_", 3 },  
     { "_RLD", 4 },  
 #ifdef __hpux  
     { "SHLIB_PATH=", 11 },  
 #endif /* __hpux */  
 #ifdef _AIX  
     { "LIBPATH=", 8 },  
 #endif /* _AIX */  
 #ifdef HAVE_KERB4  
     { "KRB_CONF", 8 },  
 #endif /* HAVE_KERB4 */  
 #ifdef HAVE_KERB5  
     { "KRB5_CONFIG", 11 },  
 #endif /* HAVE_KERB5 */  
     { "ENV=", 4 },  
     { "BASH_ENV=", 9 },  
     { (char *) NULL, 0 }  
 };  
   
   
 int  int
 main(argc, argv)  main(argc, argv, envp)
     int argc;      int argc;
     char **argv;      char **argv;
       char **envp;
 {  {
     int validated;      int validated;
     int fd;      int fd;
     int cmnd_status;      int cmnd_status;
     int sudo_mode;      int sudo_mode;
 #ifdef POSIX_SIGNALS      int pwflag;
     sigset_t set, oset;      char **new_environ;
 #else      sigaction_t sa;
     int omask;  
 #endif /* POSIX_SIGNALS */  
     extern char **environ;  
     extern int printmatches;      extern int printmatches;
       extern char **environ;
   
     /* Must be done as the first thing... */      /* Must be done as the first thing... */
 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)  #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
Line 198 
Line 168 
 # endif  # endif
 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */  #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
   
       /* Zero out the environment. */
       environ = zero_env(envp);
   
     Argv = argv;      Argv = argv;
     Argc = argc;      Argc = argc;
   
Line 207 
Line 180 
     }      }
   
     /*      /*
      * Block signals so the user cannot interrupt us at some point and       * Ignore keyboard-generated signals so the user cannot interrupt
      * avoid the logging.       * us at some point and avoid the logging.
      */       */
 #ifdef POSIX_SIGNALS      sigemptyset(&sa.sa_mask);
     (void) sigemptyset(&set);      sa.sa_flags = SA_RESTART;
     (void) sigaddset(&set, SIGINT);      sa.sa_handler = SIG_IGN;
     (void) sigaddset(&set, SIGQUIT);      (void) sigaction(SIGINT, &sa, NULL);
     (void) sigaddset(&set, SIGTSTP);      (void) sigaction(SIGQUIT, &sa, NULL);
     (void) sigprocmask(SIG_BLOCK, &set, &oset);      (void) sigaction(SIGTSTP, &sa, NULL);
 #else  
     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTSTP));  
 #endif /* POSIX_SIGNALS */  
   
     /*      /*
      * Setup signal handlers, turn off core dumps, and close open files.       * Setup signal handlers, turn off core dumps, and close open files.
      */       */
     initial_setup();      initial_setup();
       setpwent();
   
     /*  
      * Set the prompt based on $SUDO_PROMPT (can be overridden by `-p')  
      */  
     user_prompt = getenv("SUDO_PROMPT");  
   
     /* Parse our arguments. */      /* Parse our arguments. */
     sudo_mode = parse_args();      sudo_mode = parse_args();
   
     /* Setup defaults data structures. */      /* Setup defaults data structures. */
     init_defaults();      init_defaults();
   
       /* Load the list of local ip addresses and netmasks.  */
       load_interfaces();
   
       pwflag = 0;
     if (sudo_mode & MODE_SHELL)      if (sudo_mode & MODE_SHELL)
         user_cmnd = "shell";          user_cmnd = "shell";
     else      else
Line 246 
Line 216 
                     putchar('\n');                      putchar('\n');
                     dump_auth_methods();                      dump_auth_methods();
                     dump_defaults();                      dump_defaults();
                       dump_interfaces();
                       dump_badenv();
                 }                  }
                 exit(0);                  exit(0);
                 break;                  break;
Line 254 
Line 226 
                 break;                  break;
             case MODE_VALIDATE:              case MODE_VALIDATE:
                 user_cmnd = "validate";                  user_cmnd = "validate";
                   pwflag = I_VERIFYPW_I;
                 break;                  break;
             case MODE_KILL:              case MODE_KILL:
             case MODE_INVALIDATE:              case MODE_INVALIDATE:
                 user_cmnd = "kill";                  user_cmnd = "kill";
                   pwflag = -1;
                 break;                  break;
             case MODE_LISTDEFS:              case MODE_LISTDEFS:
                 list_options();                  list_options();
Line 265 
Line 239 
                 break;                  break;
             case MODE_LIST:              case MODE_LIST:
                 user_cmnd = "list";                  user_cmnd = "list";
                   pwflag = I_LISTPW_I;
                 printmatches = 1;                  printmatches = 1;
                 break;                  break;
         }          }
Line 273 
Line 248 
     if (user_cmnd == NULL && NewArgc == 0)      if (user_cmnd == NULL && NewArgc == 0)
         usage(1);          usage(1);
   
     clean_env(environ, badenv_table);  
   
     cmnd_status = init_vars(sudo_mode);      cmnd_status = init_vars(sudo_mode);
   
     /* At this point, ruid == euid == 0 */  
   
     check_sudoers();    /* check mode/owner on _PATH_SUDOERS */      check_sudoers();    /* check mode/owner on _PATH_SUDOERS */
   
     add_env(!(sudo_mode & MODE_SHELL)); /* add in SUDO_* envariables */  
   
     /* Validate the user but don't search for pseudo-commands. */      /* Validate the user but don't search for pseudo-commands. */
     validated = sudoers_lookup(sudo_mode);      validated = sudoers_lookup(pwflag);
   
       /*
        * If we have POSIX saved uids and the stay_setuid flag was not set,
        * set the real, effective and saved uids to 0 and use set_perms_fallback()
        * instead of set_perms_posix().
        */
   #if !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);
           }
           set_perms = set_perms_fallback;
       }
   #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);
       }
   
     /* This goes after the sudoers parse since we honor sudoers options. */      /* This goes after the sudoers parse since we honor sudoers options. */
     if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {      if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
         remove_timestamp((sudo_mode == MODE_KILL));          remove_timestamp((sudo_mode == MODE_KILL));
Line 303 
Line 304 
         exit(1);          exit(1);
     }      }
   
       /* 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 no command line args and "set_home" is not set, error out. */
     if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS))      if ((sudo_mode & MODE_IMPLIED_SHELL) && !def_flag(I_SHELL_NOARGS))
         usage(1);          usage(1);
   
     /* May need to set $HOME to target user. */      /* May need to set $HOME to target user if we are running a command. */
     if ((sudo_mode & MODE_SHELL) && def_flag(I_SET_HOME))      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;          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.  */
Line 326 
Line 332 
     if (!(validated & FLAG_NOPASS))      if (!(validated & FLAG_NOPASS))
         check_user();          check_user();
   
       /* Build up custom environment that avoids any nasty bits. */
       new_environ = rebuild_env(sudo_mode, envp);
   
     if (validated & VALIDATE_OK) {      if (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 348 
Line 357 
         /* This *must* have been set if we got a match but... */          /* This *must* have been set if we got a match but... */
         if (safe_cmnd == NULL) {          if (safe_cmnd == NULL) {
             log_error(MSG_ONLY,              log_error(MSG_ONLY,
                 "internal error, cmnd_safe never got set for %s; %s",                  "internal error, safe_cmnd never got set for %s; %s",
                 user_cmnd,                  user_cmnd,
                 "please report this error at http://courtesan.com/sudo/bugs/");                  "please report this error at http://courtesan.com/sudo/bugs/");
         }          }
   
         if (def_ival(I_LOGFACSTR))          /* Reset signal handlers before we exec. */
             closelog();          sigemptyset(&sa.sa_mask);
           sa.sa_flags = SA_RESTART;
           sa.sa_handler = SIG_DFL;
           (void) sigaction(SIGINT, &sa, NULL);
           (void) sigaction(SIGQUIT, &sa, NULL);
           (void) sigaction(SIGTSTP, &sa, NULL);
   
         /* Reset signal mask before we exec. */          /* Close the password file */
 #ifdef POSIX_SIGNALS          endpwent();
         (void) sigprocmask(SIG_SETMASK, &oset, NULL);  
 #else  
         (void) sigsetmask(omask);  
 #endif /* POSIX_SIGNALS */  
   
         /* Override user's umask if configured to do so. */          /* Override user's umask if configured to do so. */
         if (def_ival(I_UMASK) != 0777)          if (def_ival(I_UMASK) != 0777)
             (void) umask(def_mode(I_UMASK));              (void) umask(def_mode(I_UMASK));
   
         /* Replace the PATH envariable with a secure one. */  
         if (def_str(I_SECURE_PATH) && !user_is_exempt())  
             sudo_setenv("PATH", def_str(I_SECURE_PATH));  
   
         /* Restore coredumpsize resource limit. */          /* Restore coredumpsize resource limit. */
 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)  #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
         (void) setrlimit(RLIMIT_CORE, &corelimit);          (void) setrlimit(RLIMIT_CORE, &corelimit);
Line 379 
Line 385 
         /* Become specified user or root. */          /* Become specified user or root. */
         set_perms(PERM_RUNAS, sudo_mode);          set_perms(PERM_RUNAS, sudo_mode);
   
         /* Set $HOME for `sudo -H'.  Only valid at PERM_RUNAS. */          /* Install the new environment. */
         if ((sudo_mode & MODE_RESET_HOME) && runas_homedir)          environ = new_environ;
             sudo_setenv("HOME", runas_homedir);  
   
 #ifndef PROFILING  #ifndef PROFILING
         if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)          if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)
Line 396 
Line 401 
          */           */
         (void) fprintf(stderr, "%s: unable to exec %s: %s\n",          (void) fprintf(stderr, "%s: unable to exec %s: %s\n",
             Argv[0], safe_cmnd, strerror(errno));              Argv[0], safe_cmnd, strerror(errno));
         exit(-1);          exit(127);
     } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {      } else if ((validated & FLAG_NO_USER) || (validated & FLAG_NO_HOST)) {
         log_auth(validated, 1);          log_auth(validated, 1);
         exit(1);          exit(1);
Line 438 
Line 443 
     int sudo_mode;      int sudo_mode;
 {  {
     char *p, thost[MAXHOSTNAMELEN];      char *p, thost[MAXHOSTNAMELEN];
       int nohostname, rval;
   
     /* Sanity check command from user. */      /* Sanity check command from user. */
     if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) {      if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) {
Line 461 
Line 467 
      * "host" is the (possibly fully-qualified) hostname and       * "host" is the (possibly fully-qualified) hostname and
      * "shost" is the unqualified form of the hostname.       * "shost" is the unqualified form of the hostname.
      */       */
     if ((gethostname(thost, sizeof(thost)))) {      nohostname = gethostname(thost, sizeof(thost));
         user_host = "localhost";      if (nohostname)
         log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");          user_host = user_shost = "localhost";
     } else  
         user_host = estrdup(thost);  
     if (def_flag(I_FQDN))  
         set_fqdn();  
     else {      else {
         if ((p = strchr(user_host, '.'))) {          user_host = estrdup(thost);
             *p = '\0';          if (def_flag(I_FQDN)) {
             user_shost = estrdup(user_host);              /* Defer call to set_fqdn() until log_error() is safe. */
             *p = '.';  
         } else {  
             user_shost = user_host;              user_shost = user_host;
           } else {
               if ((p = strchr(user_host, '.'))) {
                   *p = '\0';
                   user_shost = estrdup(user_host);
                   *p = '.';
               } else {
                   user_shost = user_host;
               }
         }          }
     }      }
   
Line 503 
Line 511 
         log_error(0, "uid %ld does not exist in the passwd file!",          log_error(0, "uid %ld does not exist in the passwd file!",
             (long) pw.pw_uid);              (long) pw.pw_uid);
     }      }
       if (user_shell == NULL || *user_shell == '\0')
           user_shell = sudo_user.pw->pw_shell;
   
     /* It is now safe to use log_error() and set_perms() */      /* 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.       * Get current working directory.  Try as user, fall back to root.
      */       */
     set_perms(PERM_USER, sudo_mode);      set_perms(PERM_USER, sudo_mode);
Line 521 
Line 540 
         set_perms(PERM_ROOT, sudo_mode);          set_perms(PERM_ROOT, sudo_mode);
   
     /*      /*
      * Load the list of local ip addresses and netmasks into  
      * the interfaces array.  
      */  
     load_interfaces();  
   
     /*  
      * If we were given the '-s' option (run shell) we need to redo       * If we were given the '-s' option (run shell) we need to redo
      * NewArgv and NewArgc.       * NewArgv and NewArgc.
      */       */
Line 550 
Line 563 
     set_loginclass(sudo_user.pw);      set_loginclass(sudo_user.pw);
   
     /* Resolve the path and return. */      /* Resolve the path and return. */
     if ((sudo_mode & MODE_RUN))      if ((sudo_mode & MODE_RUN)) {
         return(find_path(NewArgv[0], &user_cmnd));          /* XXX - should call this as runas user, not root. */
     else          rval = find_path(NewArgv[0], &user_cmnd, user_path);
         return(FOUND);          if (rval != FOUND) {
               /* Failed as root, try as invoking user. */
               set_perms(PERM_USER, sudo_mode);
               rval = find_path(NewArgv[0], &user_cmnd, user_path);
               set_perms(PERM_ROOT, sudo_mode);
           }
   
           /* set user_args */
           if (NewArgc > 1) {
               char *to, **from;
               size_t size;
   
               /* 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 {
                   for (size = 0, from = NewArgv + 1; *from; from++)
                       size += strlen(*from) + 1;
               }
   
               /* alloc and copy. */
               to = user_args = (char *) emalloc(size);
               for (from = NewArgv + 1; *from; from++) {
                   (void) strcpy(to, *from);
                   to += strlen(*from);
                   *to++ = ' ';
               }
               *--to = '\0';
           }
       } else
           rval = FOUND;
   
       return(rval);
 }  }
   
 /*  /*
Line 623 
Line 669 
                     usage(1);                      usage(1);
   
                 login_class = NewArgv[1];                  login_class = NewArgv[1];
                 def_flag(I_LOGINCLASS) = TRUE;                  def_flag(I_USE_LOGINCLASS) = TRUE;
   
                 /* Shift Argv over and adjust Argc. */                  /* Shift Argv over and adjust Argc. */
                 NewArgc--;                  NewArgc--;
Line 684 
Line 730 
             case 'H':              case 'H':
                 rval |= MODE_RESET_HOME;                  rval |= MODE_RESET_HOME;
                 break;                  break;
               case 'P':
                   rval |= MODE_PRESERVE_GROUPS;
                   break;
             case 'S':              case 'S':
                 tgetpass_flags |= TGP_STDIN;                  tgetpass_flags |= TGP_STDIN;
                 break;                  break;
Line 713 
Line 762 
 }  }
   
 /*  /*
  * Add sudo-specific variables into the environment.  
  * Sets ``cmnd_args'' as a side effect.  
  */  
 static void  
 add_env(contiguous)  
     int contiguous;  
 {  
     char idstr[MAX_UID_T_LEN + 1];  
     size_t size;  
     char *buf;  
   
     /* Add the SUDO_COMMAND envariable (cmnd + args). */  
     size = strlen(user_cmnd) + 1;  
     if (NewArgc > 1) {  
         char *to, **from;  
   
         if (contiguous) {  
             size += (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +  
                     strlen(NewArgv[NewArgc-1]) + 1;  
         } else {  
             for (from = &NewArgv[1]; *from; from++)  
                 size += strlen(*from) + 1;  
         }  
   
         buf = (char *) emalloc(size);  
   
         /*  
          * Copy the command and it's arguments info buf.  
          */  
         (void) strcpy(buf, user_cmnd);  
         to = buf + strlen(user_cmnd);  
         for (from = &NewArgv[1]; *from; from++) {  
             *to++ = ' ';  
             (void) strcpy(to, *from);  
             to += strlen(*from);  
         }  
     } else {  
         buf = user_cmnd;  
     }  
     sudo_setenv("SUDO_COMMAND", buf);  
     if (NewArgc > 1)  
         free(buf);  
   
     /* Grab a pointer to the flat arg string from the environment. */  
     if (NewArgc > 1 && (user_args = getenv("SUDO_COMMAND"))) {  
         if ((user_args = strchr(user_args, ' ')))  
             user_args++;  
         else  
             user_args = NULL;  
     }  
   
     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */  
     sudo_setenv("SUDO_USER", user_name);  
     (void) sprintf(idstr, "%ld", (long) user_uid);  
     sudo_setenv("SUDO_UID", idstr);  
     (void) sprintf(idstr, "%ld", (long) user_gid);  
     sudo_setenv("SUDO_GID", idstr);  
   
     /* Set PS1 if SUDO_PS1 is set. */  
     if ((buf = getenv("SUDO_PS1")))  
         sudo_setenv("PS1", buf);  
 }  
   
 /*  
  * Sanity check sudoers mode/owner/type.   * Sanity check sudoers mode/owner/type.
  * Leaves a file pointer to the sudoers file open in ``fp''.   * Leaves a file pointer to the sudoers file open in ``fp''.
  */   */
Line 858 
Line 843 
 }  }
   
 /*  /*
  * Remove environment variables that match the entries in badenv_table.  
  */  
 static void  
 clean_env(envp, badenv_table)  
     char **envp;  
     struct env_table *badenv_table;  
 {  
     struct env_table *bad;  
     char **cur;  
   
     /*  
      * Remove any envars that match entries in badenv_table.  
      */  
     for (cur = envp; *cur; cur++) {  
         for (bad = badenv_table; bad->name; bad++) {  
             if (strncmp(*cur, bad->name, bad->len) == 0) {  
                 /* Got a match so remove it. */  
                 char **move;  
   
                 for (move = cur; *move; move++)  
                     *move = *(move + 1);  
   
                 cur--;  
   
                 break;  
             }  
         }  
     }  
 }  
   
 /*  
  * Set real and effective uids and gids based on perm.  
  */  
 void  
 set_perms(perm, sudo_mode)  
     int perm;  
     int sudo_mode;  
 {  
     struct passwd *pw;  
   
     /*  
      * First, set real & effective uids to root.  
      * If perm is PERM_ROOT then we don't need to do anything else.  
      */  
     if (setuid(0)) {  
         perror("setuid(0)");  
         exit(1);  
     }  
   
     switch (perm) {  
         case PERM_USER:  
                                 (void) setgid(user_gid);  
   
                                 if (seteuid(user_uid)) {  
                                     perror("seteuid(user_uid)");  
                                     exit(1);  
                                 }  
                                 break;  
   
         case PERM_FULL_USER:  
                                 (void) setgid(user_gid);  
   
                                 if (setuid(user_uid)) {  
                                     perror("setuid(user_uid)");  
                                     exit(1);  
                                 }  
                                 break;  
   
         case PERM_RUNAS:  
                                 /* XXX - add group/gid support */  
                                 if (**user_runas == '#') {  
                                     if (setuid(atoi(*user_runas + 1))) {  
                                         (void) fprintf(stderr,  
                                             "%s: cannot set uid to %s: %s\n",  
                                             Argv[0], *user_runas, strerror(errno));  
                                         exit(1);  
                                     }  
                                 } else {  
                                     if (!(pw = getpwnam(*user_runas))) {  
                                         (void) fprintf(stderr,  
                                             "%s: no passwd entry for %s!\n",  
                                             Argv[0], *user_runas);  
                                         exit(1);  
                                     }  
   
                                     /* Set $USER and $LOGNAME to target user */  
                                     if (def_flag(I_LOGNAME)) {  
                                         sudo_setenv("USER", pw->pw_name);  
                                         sudo_setenv("LOGNAME", pw->pw_name);  
                                     }  
   
 #ifdef HAVE_LOGIN_CAP_H  
                                     if (def_flag(I_LOGINCLASS)) {  
                                         /*  
                                          * setusercontext() will set uid/gid/etc  
                                          * for us so no need to do it below.  
                                          */  
                                         if (setusercontext(lc, pw, pw->pw_uid,  
                                             LOGIN_SETUSER|LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY))  
                                             log_error(  
                                                 NO_MAIL|USE_ERRNO|MSG_ONLY,  
                                                 "setusercontext() failed for login class %s",  
                                                 login_class);  
                                         else  
                                             break;  
                                     }  
 #endif /* HAVE_LOGIN_CAP_H */  
   
                                     if (setgid(pw->pw_gid)) {  
                                         (void) fprintf(stderr,  
                                             "%s: cannot set gid to %ld: %s\n",  
                                             Argv[0], (long) pw->pw_gid,  
                                             strerror(errno));  
                                         exit(1);  
                                     }  
 #ifdef HAVE_INITGROUPS  
                                     /*  
                                      * Initialize group vector only if are  
                                      * going to run as a non-root user.  
                                      */  
                                     if (strcmp(*user_runas, "root") != 0 &&  
                                         initgroups(*user_runas, pw->pw_gid)  
                                         == -1) {  
                                         (void) fprintf(stderr,  
                                             "%s: cannot set group vector: %s\n",  
                                             Argv[0], strerror(errno));  
                                         exit(1);  
                                     }  
 #endif /* HAVE_INITGROUPS */  
                                     if (setuid(pw->pw_uid)) {  
                                         (void) fprintf(stderr,  
                                             "%s: cannot set uid to %ld: %s\n",  
                                             Argv[0], (long) pw->pw_uid,  
                                             strerror(errno));  
                                         exit(1);  
                                     }  
                                     if (sudo_mode & MODE_RESET_HOME)  
                                         runas_homedir = pw->pw_dir;  
                                 }  
                                 break;  
   
         case PERM_SUDOERS:  
                                 if (setgid(SUDOERS_GID)) {  
                                     perror("setgid(SUDOERS_GID)");  
                                     exit(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) && seteuid(1)) {  
                                         perror("seteuid(1)");  
                                         exit(1);  
                                     }  
                                 } else {  
                                     if (seteuid(SUDOERS_UID)) {  
                                         perror("seteuid(SUDOERS_UID)");  
                                         exit(1);  
                                     }  
                                 }  
                                 break;  
     }  
 }  
   
 /*  
  * 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()
Line 1037 
Line 853 
 #ifdef HAVE_SETRLIMIT  #ifdef HAVE_SETRLIMIT
     struct rlimit rl;      struct rlimit rl;
 #endif  #endif
 #ifdef POSIX_SIGNALS      sigaction_t sa;
     struct sigaction sa;  
 #endif  
   
 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)  #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
     /*      /*
Line 1069 
Line 883 
         (void) close(fd);          (void) close(fd);
   
     /* Catch children as they die... */      /* Catch children as they die... */
 #ifdef POSIX_SIGNALS      sigemptyset(&sa.sa_mask);
     (void) memset((VOID *)&sa, 0, sizeof(sa));      sa.sa_flags = SA_RESTART;
     sa.sa_handler = reapchild;      sa.sa_handler = reapchild;
     (void) sigaction(SIGCHLD, &sa, NULL);      (void) sigaction(SIGCHLD, &sa, NULL);
 #else  
     (void) signal(SIGCHLD, reapchild);      /* Set set_perms pointer to the correct function */
 #endif /* POSIX_SIGNALS */  #if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
       if (sysconf(_SC_SAVED_IDS) == 1 && sysconf(_SC_VERSION) >= 199009)
           set_perms = set_perms_posix;
       else
   #endif
           set_perms = set_perms_fallback;
 }  }
   
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
Line 1109 
Line 928 
     }      }
   
     lc = login_getclass(login_class);      lc = login_getclass(login_class);
     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0)      if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
         log_error(errflags, "unknown login class: %s", login_class);          log_error(errflags, "unknown login class: %s", login_class);
           if (!lc)
               lc = login_getclass(NULL);  /* needed for login_getstyle() later */
       }
 }  }
 #else  #else
 static void  static void
Line 1129 
Line 951 
     struct hostent *hp;      struct hostent *hp;
     char *p;      char *p;
   
     if (def_flag(I_FQDN)) {      if (!(hp = gethostbyname(user_host))) {
         if (!(hp = gethostbyname(user_host))) {          log_error(MSG_ONLY|NO_EXIT,
             log_error(USE_ERRNO|MSG_ONLY|NO_EXIT,              "unable to lookup %s via gethostbyname()", user_host);
                 "unable to lookup %s via gethostbyname()", user_host);      } else {
         } else {          if (user_shost != user_host)
             free(user_host);              free(user_shost);
             user_host = estrdup(hp->h_name);          free(user_host);
         }          user_host = estrdup(hp->h_name);
     }      }
     if (user_shost != user_host)  
         free(user_shost);  
     if ((p = strchr(user_host, '.'))) {      if ((p = strchr(user_host, '.'))) {
         *p = '\0';          *p = '\0';
         user_shost = estrdup(user_host);          user_shost = estrdup(user_host);
Line 1162 
Line 982 
         if ((pw = sudo_getpwuid(0)) == NULL)          if ((pw = sudo_getpwuid(0)) == NULL)
             log_error(0, "uid 0 does not exist in the passwd file!");              log_error(0, "uid 0 does not exist in the passwd file!");
     } else if (def_ival(I_RUNASPW)) {      } else if (def_ival(I_RUNASPW)) {
         if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEF))) == NULL)          if ((pw = sudo_getpwnam(def_str(I_RUNAS_DEFAULT))) == NULL)
             log_error(0, "user %s does not exist in the passwd file!",              log_error(0, "user %s does not exist in the passwd file!",
                 def_str(I_RUNAS_DEF));                  def_str(I_RUNAS_DEFAULT));
     } else if (def_ival(I_TARGETPW)) {      } else if (def_ival(I_TARGETPW)) {
         if (**user_runas == '#') {          if (**user_runas == '#') {
             if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL)              if ((pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL)
Line 1202 
Line 1022 
 {  {
   
     (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",      (void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",
         "[-H] [-S] [-b] [-p prompt]\n            [-u username/#uid] ");          "[-H] [-P] [-S] [-b] [-p prompt]\n            [-u username/#uid] ");
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
     (void) fprintf(stderr, "[-c class] ");      (void) fprintf(stderr, "[-c class] ");
 #endif  #endif

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.9.2.1