Diff for /embedaddon/sudo/src/sudo.c between versions 1.1 and 1.1.1.3

version 1.1, 2012/02/21 16:23:02 version 1.1.1.3, 2012/10/09 09:29:52
Line 1 Line 1
 /*  /*
 * Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2009-2012 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 25 Line 25
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/wait.h>  #include <sys/wait.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #ifdef HAVE_SYS_SELECT_H  
 # include <sys/select.h>  
 #endif /* HAVE_SYS_SELECT_H */  
 #include <sys/time.h>  #include <sys/time.h>
 #include <sys/resource.h>  #include <sys/resource.h>
 #include <stdio.h>  #include <stdio.h>
Line 66 Line 63
 #endif  #endif
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
 # include <login_cap.h>  # include <login_cap.h>
   # ifndef LOGIN_SETENV
   #  define LOGIN_SETENV  0
   # endif
 #endif  #endif
 #ifdef HAVE_PROJECT_H  #ifdef HAVE_PROJECT_H
 # include <project.h>  # include <project.h>
Line 86 Line 86
 # endif /* __hpux */  # endif /* __hpux */
 # include <prot.h>  # include <prot.h>
 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */  #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
#ifdef HAVE_PRIV_SET#if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV)
# include <priv.h># include <sys/sysctl.h>
 #elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
 # include <sys/sysctl.h>
 # include <sys/user.h>
 #endif  #endif
   
 #include "sudo.h"  #include "sudo.h"
Line 102  struct plugin_container policy_plugin; Line 105  struct plugin_container policy_plugin;
 struct plugin_container_list io_plugins;  struct plugin_container_list io_plugins;
 struct user_details user_details;  struct user_details user_details;
 const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */  const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */
int debug_level;static int sudo_mode;
   
 /*  /*
  * Local functions   * Local functions
  */   */
 static void fix_fds(void);  static void fix_fds(void);
 static void disable_coredumps(void);  static void disable_coredumps(void);
   static void sudo_check_suid(const char *path);
 static char **get_user_info(struct user_details *);  static char **get_user_info(struct user_details *);
 static void command_info_to_details(char * const info[],  static void command_info_to_details(char * const info[],
     struct command_details *details);      struct command_details *details);
 static int policy_open(struct plugin_container *plugin, char * const settings[],  
     char * const user_info[], char * const user_env[]);  
 static void policy_close(struct plugin_container *plugin, int exit_status,  
     int error);  
 static int iolog_open(struct plugin_container *plugin, char * const settings[],  
     char * const user_info[], char * const command_details[],  
     int argc, char * const argv[], char * const user_env[]);  
 static void iolog_close(struct plugin_container *plugin, int exit_status,  
     int error);  
   
 /* Policy plugin convenience functions. */  /* Policy plugin convenience functions. */
 static int policy_open(struct plugin_container *plugin, char * const settings[],  static int policy_open(struct plugin_container *plugin, char * const settings[],
Line 135  static int policy_list(struct plugin_container *plugin Line 130  static int policy_list(struct plugin_container *plugin
     char * const argv[], int verbose, const char *list_user);      char * const argv[], int verbose, const char *list_user);
 static int policy_validate(struct plugin_container *plugin);  static int policy_validate(struct plugin_container *plugin);
 static void policy_invalidate(struct plugin_container *plugin, int remove);  static void policy_invalidate(struct plugin_container *plugin, int remove);
 static int policy_init_session(struct plugin_container *plugin,  
     struct passwd *pwd);  
   
 /* I/O log plugin convenience functions. */  /* I/O log plugin convenience functions. */
 static int iolog_open(struct plugin_container *plugin, char * const settings[],  static int iolog_open(struct plugin_container *plugin, char * const settings[],
Line 145  static int iolog_open(struct plugin_container *plugin, Line 138  static int iolog_open(struct plugin_container *plugin,
 static void iolog_close(struct plugin_container *plugin, int exit_status,  static void iolog_close(struct plugin_container *plugin, int exit_status,
     int error);      int error);
 static int iolog_show_version(struct plugin_container *plugin, int verbose);  static int iolog_show_version(struct plugin_container *plugin, int verbose);
   static void iolog_unlink(struct plugin_container *plugin);
   
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)#ifdef RLIMIT_CORE
 static struct rlimit corelimit;  static struct rlimit corelimit;
#endif /* RLIMIT_CORE && !SUDO_DEVEL */#endif /* RLIMIT_CORE */
 #if defined(__linux__)  #if defined(__linux__)
 static struct rlimit nproclimit;  static struct rlimit nproclimit;
 #endif  #endif
Line 156  static struct rlimit nproclimit; Line 150  static struct rlimit nproclimit;
 int  int
 main(int argc, char *argv[], char *envp[])  main(int argc, char *argv[], char *envp[])
 {  {
    int nargc, sudo_mode, exitcode = 0;    int nargc, ok, exitcode = 0;
     char **nargv, **settings, **env_add;      char **nargv, **settings, **env_add;
     char **user_info, **command_info, **argv_out, **user_env_out;      char **user_info, **command_info, **argv_out, **user_env_out;
     struct plugin_container *plugin, *next;      struct plugin_container *plugin, *next;
     struct command_details command_details;      struct command_details command_details;
     sigset_t mask;      sigset_t mask;
    int ok;    debug_decl(main, SUDO_DEBUG_MAIN)
 
 #if defined(SUDO_DEVEL) && defined(__OpenBSD__)  #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
    extern char *malloc_options;    {
    malloc_options = "AFGJPR";        extern char *malloc_options;
         malloc_options = "AFGJPR";
     }
 #endif  #endif
   
 #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)  #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
Line 187  main(int argc, char *argv[], char *envp[]) Line 184  main(int argc, char *argv[], char *envp[])
 # endif  # endif
 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */  #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
   
    if (geteuid() != 0)    /* Make sure we are setuid root. */
        errorx(1, _("must be setuid root"));    sudo_check_suid(argv[0]);
   
    /* Reset signal mask, disable core dumps and make sure fds 0-2 are open. */    /* Reset signal mask and make sure fds 0-2 are open. */
     (void) sigemptyset(&mask);      (void) sigemptyset(&mask);
     (void) sigprocmask(SIG_SETMASK, &mask, NULL);      (void) sigprocmask(SIG_SETMASK, &mask, NULL);
     disable_coredumps();  
     fix_fds();      fix_fds();
   
       /* Read sudo.conf. */
       sudo_conf_read();
   
     /* Fill in user_info with user name, uid, cwd, etc. */      /* Fill in user_info with user name, uid, cwd, etc. */
     memset(&user_details, 0, sizeof(user_details));      memset(&user_details, 0, sizeof(user_details));
     user_info = get_user_info(&user_details);      user_info = get_user_info(&user_details);
   
       /* Disable core dumps if not enabled in sudo.conf. */
       disable_coredumps();
   
     /* Parse command line arguments. */      /* Parse command line arguments. */
     sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);      sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
    sudo_debug(9, "sudo_mode %d", sudo_mode);    sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_mode %d", sudo_mode);
   
     /* Print sudo version early, in case of plugin init failure. */      /* Print sudo version early, in case of plugin init failure. */
     if (ISSET(sudo_mode, MODE_VERSION)) {      if (ISSET(sudo_mode, MODE_VERSION)) {
Line 211  main(int argc, char *argv[], char *envp[]) Line 213  main(int argc, char *argv[], char *envp[])
             (void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);              (void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
     }      }
   
    /* Read sudo.conf and load plugins. */    /* Load plugins. */
    if (!sudo_load_plugins(_PATH_SUDO_CONF, &policy_plugin, &io_plugins))    if (!sudo_load_plugins(&policy_plugin, &io_plugins))
         errorx(1, _("fatal error, unable to load plugins"));          errorx(1, _("fatal error, unable to load plugins"));
   
     /* Open policy plugin. */      /* Open policy plugin. */
     ok = policy_open(&policy_plugin, settings, user_info, envp);      ok = policy_open(&policy_plugin, settings, user_info, envp);
    if (ok != TRUE) {    if (ok != 1) {
         if (ok == -2)          if (ok == -2)
             usage(1);              usage(1);
         else          else
Line 230  main(int argc, char *argv[], char *envp[]) Line 232  main(int argc, char *argv[], char *envp[])
             tq_foreach_fwd(&io_plugins, plugin) {              tq_foreach_fwd(&io_plugins, plugin) {
                 ok = iolog_open(plugin, settings, user_info, NULL,                  ok = iolog_open(plugin, settings, user_info, NULL,
                     nargc, nargv, envp);                      nargc, nargv, envp);
                if (ok == TRUE)                if (ok == 1)
                     iolog_show_version(plugin, !user_details.uid);                      iolog_show_version(plugin, !user_details.uid);
             }              }
             break;              break;
         case MODE_VALIDATE:          case MODE_VALIDATE:
         case MODE_VALIDATE|MODE_INVALIDATE:          case MODE_VALIDATE|MODE_INVALIDATE:
             ok = policy_validate(&policy_plugin);              ok = policy_validate(&policy_plugin);
            exit(ok != TRUE);            exit(ok != 1);
         case MODE_KILL:          case MODE_KILL:
         case MODE_INVALIDATE:          case MODE_INVALIDATE:
             policy_invalidate(&policy_plugin, sudo_mode == MODE_KILL);              policy_invalidate(&policy_plugin, sudo_mode == MODE_KILL);
Line 249  main(int argc, char *argv[], char *envp[]) Line 251  main(int argc, char *argv[], char *envp[])
         case MODE_LIST|MODE_INVALIDATE:          case MODE_LIST|MODE_INVALIDATE:
             ok = policy_list(&policy_plugin, nargc, nargv,              ok = policy_list(&policy_plugin, nargc, nargv,
                 ISSET(sudo_mode, MODE_LONG_LIST), list_user);                  ISSET(sudo_mode, MODE_LONG_LIST), list_user);
            exit(ok != TRUE);            exit(ok != 1);
         case MODE_EDIT:          case MODE_EDIT:
         case MODE_RUN:          case MODE_RUN:
             ok = policy_check(&policy_plugin, nargc, nargv, env_add,              ok = policy_check(&policy_plugin, nargc, nargv, env_add,
                 &command_info, &argv_out, &user_env_out);                  &command_info, &argv_out, &user_env_out);
            sudo_debug(8, "policy plugin returns %d", ok);            sudo_debug_printf(SUDO_DEBUG_INFO, "policy plugin returns %d", ok);
            if (ok != TRUE) {            if (ok != 1) {
                 if (ok == -2)                  if (ok == -2)
                     usage(1);                      usage(1);
                 exit(1); /* plugin printed error message */                  exit(1); /* plugin printed error message */
Line 266  main(int argc, char *argv[], char *envp[]) Line 268  main(int argc, char *argv[], char *envp[])
                 ok = iolog_open(plugin, settings, user_info,                  ok = iolog_open(plugin, settings, user_info,
                     command_info, nargc, nargv, envp);                      command_info, nargc, nargv, envp);
                 switch (ok) {                  switch (ok) {
                case TRUE:                case 1:
                     break;                      break;
                case FALSE:                case 0:
                    /* I/O plugin asked to be disabled, remove from list. */                    /* I/O plugin asked to be disabled, remove and free. */
                    tq_remove(&io_plugins, plugin);                    iolog_unlink(plugin);
                     break;                      break;
                 case -2:                  case -2:
                     usage(1);                      usage(1);
Line 280  main(int argc, char *argv[], char *envp[]) Line 282  main(int argc, char *argv[], char *envp[])
                         plugin->name);                          plugin->name);
                 }                  }
             }              }
               /* Setup command details and run command/edit. */
             command_info_to_details(command_info, &command_details);              command_info_to_details(command_info, &command_details);
             command_details.argv = argv_out;              command_details.argv = argv_out;
             command_details.envp = user_env_out;              command_details.envp = user_env_out;
             if (ISSET(sudo_mode, MODE_BACKGROUND))              if (ISSET(sudo_mode, MODE_BACKGROUND))
                 SET(command_details.flags, CD_BACKGROUND);                  SET(command_details.flags, CD_BACKGROUND);
               /* Become full root (not just setuid) so user cannot kill us. */
               (void) setuid(ROOT_UID);
             /* Restore coredumpsize resource limit before running. */              /* Restore coredumpsize resource limit before running. */
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)#ifdef RLIMIT_CORE
            (void) setrlimit(RLIMIT_CORE, &corelimit);            if (sudo_conf_disable_coredump())
#endif /* RLIMIT_CORE && !SUDO_DEVEL */                (void) setrlimit(RLIMIT_CORE, &corelimit);
 #endif /* RLIMIT_CORE */
             if (ISSET(command_details.flags, CD_SUDOEDIT)) {              if (ISSET(command_details.flags, CD_SUDOEDIT)) {
                 exitcode = sudo_edit(&command_details);                  exitcode = sudo_edit(&command_details);
             } else {              } else {
Line 299  main(int argc, char *argv[], char *envp[]) Line 305  main(int argc, char *argv[], char *envp[])
         default:          default:
             errorx(1, _("unexpected sudo mode 0x%x"), sudo_mode);              errorx(1, _("unexpected sudo mode 0x%x"), sudo_mode);
     }      }
       sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);                
     exit(exitcode);      exit(exitcode);
 }  }
   
Line 310  static void Line 317  static void
 fix_fds(void)  fix_fds(void)
 {  {
     int miss[3], devnull = -1;      int miss[3], devnull = -1;
       debug_decl(fix_fds, SUDO_DEBUG_UTIL)
   
     /*      /*
      * stdin, stdout and stderr must be open; set them to /dev/null       * stdin, stdout and stderr must be open; set them to /dev/null
Line 330  fix_fds(void) Line 338  fix_fds(void)
         if (devnull > STDERR_FILENO)          if (devnull > STDERR_FILENO)
             close(devnull);              close(devnull);
     }      }
       debug_return;
 }  }
   
 /*  /*
Line 340  static int Line 349  static int
 fill_group_list(struct user_details *ud)  fill_group_list(struct user_details *ud)
 {  {
     int maxgroups, tries, rval = -1;      int maxgroups, tries, rval = -1;
       debug_decl(fill_group_list, SUDO_DEBUG_UTIL)
   
 #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)  #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
     maxgroups = (int)sysconf(_SC_NGROUPS_MAX);      maxgroups = (int)sysconf(_SC_NGROUPS_MAX);
Line 360  fill_group_list(struct user_details *ud) Line 370  fill_group_list(struct user_details *ud)
         ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));          ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
         rval = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);          rval = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
     }      }
    return rval;    debug_return_int(rval);
 }  }
   
 static char *  static char *
Line 369  get_user_groups(struct user_details *ud) Line 379  get_user_groups(struct user_details *ud)
     char *cp, *gid_list = NULL;      char *cp, *gid_list = NULL;
     size_t glsize;      size_t glsize;
     int i, len;      int i, len;
       debug_decl(get_user_groups, SUDO_DEBUG_UTIL)
   
     /*      /*
      * Systems with mbr_check_membership() support more than NGROUPS_MAX       * Systems with mbr_check_membership() support more than NGROUPS_MAX
Line 402  get_user_groups(struct user_details *ud) Line 413  get_user_groups(struct user_details *ud)
             i ? "," : "", (unsigned int)ud->groups[i]);              i ? "," : "", (unsigned int)ud->groups[i]);
         cp += len;          cp += len;
     }      }
    return gid_list;    debug_return_str(gid_list);
 }  }
   
 /*  /*
Line 412  get_user_groups(struct user_details *ud) Line 423  get_user_groups(struct user_details *ud)
 static char **  static char **
 get_user_info(struct user_details *ud)  get_user_info(struct user_details *ud)
 {  {
    char cwd[PATH_MAX];    char *cp, **user_info, cwd[PATH_MAX], host[MAXHOSTNAMELEN];
    char host[MAXHOSTNAMELEN]; 
    char **user_info, *cp; 
     struct passwd *pw;      struct passwd *pw;
    int i = 0;    int fd, i = 0;
     debug_decl(get_user_info, SUDO_DEBUG_UTIL)
   
     /* XXX - bound check number of entries */      /* XXX - bound check number of entries */
     user_info = emalloc2(32, sizeof(char *));      user_info = emalloc2(32, sizeof(char *));
   
       ud->pid = getpid();
       ud->ppid = getppid();
       ud->pgid = getpgid(0);
       ud->tcpgid = (pid_t)-1;
       fd = open(_PATH_TTY, O_RDWR|O_NOCTTY|O_NONBLOCK, 0);
       if (fd != -1) {
           ud->tcpgid = tcgetpgrp(fd);
           close(fd);
       }
       ud->sid = getsid(0);
   
     ud->uid = getuid();      ud->uid = getuid();
     ud->euid = geteuid();      ud->euid = geteuid();
     ud->gid = getgid();      ud->gid = getgid();
Line 441  get_user_info(struct user_details *ud) Line 462  get_user_info(struct user_details *ud)
     }      }
     ud->shell = estrdup(ud->shell);      ud->shell = estrdup(ud->shell);
   
       easprintf(&user_info[++i], "pid=%d", (int)ud->pid);
       easprintf(&user_info[++i], "ppid=%d", (int)ud->ppid);
       easprintf(&user_info[++i], "pgid=%d", (int)ud->pgid);
       easprintf(&user_info[++i], "tcpgid=%d", (int)ud->tcpgid);
       easprintf(&user_info[++i], "sid=%d", (int)ud->sid);
   
     easprintf(&user_info[++i], "uid=%u", (unsigned int)ud->uid);      easprintf(&user_info[++i], "uid=%u", (unsigned int)ud->uid);
     easprintf(&user_info[++i], "euid=%u", (unsigned int)ud->euid);      easprintf(&user_info[++i], "euid=%u", (unsigned int)ud->euid);
     easprintf(&user_info[++i], "gid=%u", (unsigned int)ud->gid);      easprintf(&user_info[++i], "gid=%u", (unsigned int)ud->gid);
Line 456  get_user_info(struct user_details *ud) Line 483  get_user_info(struct user_details *ud)
         ud->cwd = user_info[i] + sizeof("cwd=") - 1;          ud->cwd = user_info[i] + sizeof("cwd=") - 1;
     }      }
   
    if ((cp = ttyname(STDIN_FILENO)) || (cp = ttyname(STDOUT_FILENO)) ||    if ((cp = get_process_ttyname()) != NULL) {
        (cp = ttyname(STDERR_FILENO))) { 
         user_info[++i] = fmt_string("tty", cp);          user_info[++i] = fmt_string("tty", cp);
         if (user_info[i] == NULL)          if (user_info[i] == NULL)
             errorx(1, _("unable to allocate memory"));              errorx(1, _("unable to allocate memory"));
         ud->tty = user_info[i] + sizeof("tty=") - 1;          ud->tty = user_info[i] + sizeof("tty=") - 1;
           efree(cp);
     }      }
   
     if (gethostname(host, sizeof(host)) == 0)      if (gethostname(host, sizeof(host)) == 0)
Line 479  get_user_info(struct user_details *ud) Line 506  get_user_info(struct user_details *ud)
   
     user_info[++i] = NULL;      user_info[++i] = NULL;
   
    return user_info;    debug_return_ptr(user_info);
 }  }
   
 /*  /*
Line 492  command_info_to_details(char * const info[], struct co Line 519  command_info_to_details(char * const info[], struct co
     long lval;      long lval;
     unsigned long ulval;      unsigned long ulval;
     char *cp, *ep;      char *cp, *ep;
       debug_decl(command_info_to_details, SUDO_DEBUG_PCOMM)
   
     memset(details, 0, sizeof(*details));      memset(details, 0, sizeof(*details));
     details->closefrom = -1;      details->closefrom = -1;
Line 502  command_info_to_details(char * const info[], struct co Line 530  command_info_to_details(char * const info[], struct co
         break; \          break; \
     }      }
   
       sudo_debug_printf(SUDO_DEBUG_INFO, "command info from plugin:");
     for (i = 0; info[i] != NULL; i++) {      for (i = 0; info[i] != NULL; i++) {
        sudo_debug(9, "command info: %s", info[i]);        sudo_debug_printf(SUDO_DEBUG_INFO, "    %d: %s", i, info[i]);
         switch (info[i][0]) {          switch (info[i][0]) {
             case 'c':              case 'c':
                 SET_STRING("chroot=", chroot)                  SET_STRING("chroot=", chroot)
Line 545  command_info_to_details(char * const info[], struct co Line 574  command_info_to_details(char * const info[], struct co
                     break;                      break;
                 }                  }
                 if (strncmp("noexec=", info[i], sizeof("noexec=") - 1) == 0) {                  if (strncmp("noexec=", info[i], sizeof("noexec=") - 1) == 0) {
                    if (atobool(info[i] + sizeof("noexec=") - 1) == TRUE)                    if (atobool(info[i] + sizeof("noexec=") - 1) == true)
                         SET(details->flags, CD_NOEXEC);                          SET(details->flags, CD_NOEXEC);
                     break;                      break;
                 }                  }
 #ifdef _PATH_SUDO_NOEXEC  
                 /* XXX - deprecated */  
                 if (strncmp("noexec_file=", info[i], sizeof("noexec_file=") - 1) == 0) {  
                     noexec_path = info[i] + sizeof("noexec_file=") - 1;  
                     break;  
                 }  
 #endif /* _PATH_SUDO_NOEXEC */  
                 break;                  break;
             case 'p':              case 'p':
                 if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {                  if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {
                    if (atobool(info[i] + sizeof("preserve_groups=") - 1) == TRUE)                    if (atobool(info[i] + sizeof("preserve_groups=") - 1) == true)
                         SET(details->flags, CD_PRESERVE_GROUPS);                          SET(details->flags, CD_PRESERVE_GROUPS);
                     break;                      break;
                 }                  }
Line 648  command_info_to_details(char * const info[], struct co Line 670  command_info_to_details(char * const info[], struct co
                     }                      }
                     break;                      break;
                 }                  }
   #ifdef HAVE_PRIV_SET
                   if (strncmp("runas_privs=", info[i], sizeof("runas_privs=") - 1) == 0) {
                       const char *endp;
                       cp = info[i] + sizeof("runas_privs=") - 1;
                       if (*cp == '\0')
                           break;
                       errno = 0;
                       details->privs = priv_str_to_set(cp, ",", &endp);
                       if (details->privs == NULL)
                               warning("invalid runas_privs %s", endp);
                   }
                   if (strncmp("runas_limitprivs=", info[i], sizeof("runas_limitprivs=") - 1) == 0) {
                       const char *endp;
                       cp = info[i] + sizeof("runas_limitprivs=") - 1;
                       if (*cp == '\0')
                           break;
                       errno = 0;
                       details->limitprivs = priv_str_to_set(cp, ",", &endp);
                       if (details->limitprivs == NULL)
                               warning("invalid runas_limitprivs %s", endp);
                   }
   #endif /* HAVE_PRIV_SET */
                 break;                  break;
             case 's':              case 's':
                 SET_STRING("selinux_role=", selinux_role)                  SET_STRING("selinux_role=", selinux_role)
                 SET_STRING("selinux_type=", selinux_type)                  SET_STRING("selinux_type=", selinux_type)
                 if (strncmp("set_utmp=", info[i], sizeof("set_utmp=") - 1) == 0) {                  if (strncmp("set_utmp=", info[i], sizeof("set_utmp=") - 1) == 0) {
                    if (atobool(info[i] + sizeof("set_utmp=") - 1) == TRUE)                    if (atobool(info[i] + sizeof("set_utmp=") - 1) == true)
                         SET(details->flags, CD_SET_UTMP);                          SET(details->flags, CD_SET_UTMP);
                     break;                      break;
                 }                  }
                 if (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) {                  if (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) {
                    if (atobool(info[i] + sizeof("sudoedit=") - 1) == TRUE)                    if (atobool(info[i] + sizeof("sudoedit=") - 1) == true)
                         SET(details->flags, CD_SUDOEDIT);                          SET(details->flags, CD_SUDOEDIT);
                     break;                      break;
                 }                  }
Line 695  command_info_to_details(char * const info[], struct co Line 739  command_info_to_details(char * const info[], struct co
                     break;                      break;
                 }                  }
                 if (strncmp("use_pty=", info[i], sizeof("use_pty=") - 1) == 0) {                  if (strncmp("use_pty=", info[i], sizeof("use_pty=") - 1) == 0) {
                    if (atobool(info[i] + sizeof("use_pty=") - 1) == TRUE)                    if (atobool(info[i] + sizeof("use_pty=") - 1) == true)
                         SET(details->flags, CD_USE_PTY);                          SET(details->flags, CD_USE_PTY);
                     break;                      break;
                 }                  }
Line 707  command_info_to_details(char * const info[], struct co Line 751  command_info_to_details(char * const info[], struct co
     if (!ISSET(details->flags, CD_SET_EUID))      if (!ISSET(details->flags, CD_SET_EUID))
         details->euid = details->uid;          details->euid = details->uid;
   
   #ifdef HAVE_SETAUTHDB
       aix_setauthdb(IDtouser(details->euid));
   #endif
       details->pw = getpwuid(details->euid);
       if (details->pw != NULL && (details->pw = pw_dup(details->pw)) == NULL)
           errorx(1, _("unable to allocate memory"));
   #ifdef HAVE_SETAUTHDB
       aix_restoreauthdb();
   #endif
   
 #ifdef HAVE_SELINUX  #ifdef HAVE_SELINUX
     if (details->selinux_role != NULL && is_selinux_enabled() > 0)      if (details->selinux_role != NULL && is_selinux_enabled() > 0)
         SET(details->flags, CD_RBAC_ENABLED);          SET(details->flags, CD_RBAC_ENABLED);
 #endif  #endif
       debug_return;
 }  }
   
   static void
   sudo_check_suid(const char *path)
   {
       struct stat sb;
       debug_decl(sudo_check_suid, SUDO_DEBUG_PCOMM)
   
       if (geteuid() != 0) {
           if (strchr(path, '/') != NULL && stat(path, &sb) == 0) {
               /* Try to determine why sudo was not running as root. */
               if (sb.st_uid != ROOT_UID || !ISSET(sb.st_mode, S_ISUID)) {
                   errorx(1,
                       _("%s must be owned by uid %d and have the setuid bit set"),
                       path, ROOT_UID);
               } else {
                   errorx(1, _("effective uid is not %d, is %s on a file system "
                       "with the 'nosuid' option set or an NFS file system without"
                       " root privileges?"), ROOT_UID, path);
               }
           } else {
               errorx(1,
                   _("effective uid is not %d, is sudo installed setuid root?"),
                   ROOT_UID);
           }
       }
       debug_return;
   }
   
 /*  /*
  * Disable core dumps to avoid dropping a core with user password in it.   * Disable core dumps to avoid dropping a core with user password in it.
  * We will reset this limit before executing the command.   * We will reset this limit before executing the command.
Line 721  command_info_to_details(char * const info[], struct co Line 803  command_info_to_details(char * const info[], struct co
 static void  static void
 disable_coredumps(void)  disable_coredumps(void)
 {  {
#if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL))#if defined(__linux__) || defined(RLIMIT_CORE)
     struct rlimit rl;      struct rlimit rl;
 #endif  #endif
       debug_decl(disable_coredumps, SUDO_DEBUG_UTIL)
   
 #if defined(__linux__)  #if defined(__linux__)
     /*      /*
Line 739  disable_coredumps(void) Line 822  disable_coredumps(void)
         (void)setrlimit(RLIMIT_NPROC, &rl);          (void)setrlimit(RLIMIT_NPROC, &rl);
     }      }
 #endif /* __linux__ */  #endif /* __linux__ */
#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)#ifdef RLIMIT_CORE
     /*      /*
     * Turn off core dumps.     * Turn off core dumps?
      */       */
    (void) getrlimit(RLIMIT_CORE, &corelimit);    if (sudo_conf_disable_coredump()) {
    memcpy(&rl, &corelimit, sizeof(struct rlimit));        (void) getrlimit(RLIMIT_CORE, &corelimit);
    rl.rlim_cur = 0;        memcpy(&rl, &corelimit, sizeof(struct rlimit));
    (void) setrlimit(RLIMIT_CORE, &rl);        rl.rlim_cur = 0;
#endif /* RLIMIT_CORE && !SUDO_DEVEL */        (void) setrlimit(RLIMIT_CORE, &rl);
     }
 #endif /* RLIMIT_CORE */
     debug_return;
 }  }
   
 #ifdef HAVE_PROJECT_H  #ifdef HAVE_PROJECT_H
Line 757  set_project(struct passwd *pw) Line 843  set_project(struct passwd *pw)
     struct project proj;      struct project proj;
     char buf[PROJECT_BUFSZ];      char buf[PROJECT_BUFSZ];
     int errval;      int errval;
       debug_decl(set_project, SUDO_DEBUG_UTIL)
   
     /*      /*
      * Collect the default project for the user and settaskid       * Collect the default project for the user and settaskid
Line 809  set_project(struct passwd *pw) Line 896  set_project(struct passwd *pw)
         warning("getdefaultproj");          warning("getdefaultproj");
     }      }
     endprojent();      endprojent();
       debug_return;
 }  }
 #endif /* HAVE_PROJECT_H */  #endif /* HAVE_PROJECT_H */
   
 /*  /*
  * Disable execution of child processes in the command we are about  
  * to run.  On systems with privilege sets, we can remove the exec  
  * privilege.  On other systems we use LD_PRELOAD and the like.  
  */  
 static void  
 disable_execute(struct command_details *details)  
 {  
 #ifdef _PATH_SUDO_NOEXEC  
     char *cp, **ev, **nenvp;  
     int env_len = 0, env_size = 128;  
 #endif /* _PATH_SUDO_NOEXEC */  
   
 #ifdef HAVE_PRIV_SET  
     /* Solaris privileges, remove PRIV_PROC_EXEC post-execve. */  
     if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == 0)  
         return;  
     warning(_("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"));  
 #endif /* HAVE_PRIV_SET */  
   
 #ifdef _PATH_SUDO_NOEXEC  
     nenvp = emalloc2(env_size, sizeof(char *));  
     for (ev = details->envp; *ev != NULL; ev++) {  
         if (env_len + 2 > env_size) {  
             env_size += 128;  
             nenvp = erealloc3(nenvp, env_size, sizeof(char *));  
         }  
         /*  
          * Prune out existing preloaded libraries.  
          * XXX - should save and append instead of replacing.  
          */  
 # if defined(__darwin__) || defined(__APPLE__)  
         if (strncmp(*ev, "DYLD_INSERT_LIBRARIES=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0)  
             continue;  
         if (strncmp(*ev, "DYLD_FORCE_FLAT_NAMESPACE=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0)  
             continue;  
 # elif defined(__osf__) || defined(__sgi)  
         if (strncmp(*ev, "_RLD_LIST=", sizeof("_RLD_LIST=") - 1) == 0)  
             continue;  
 # elif defined(_AIX)  
         if (strncmp(*ev, "LDR_PRELOAD=", sizeof("LDR_PRELOAD=") - 1) == 0)  
             continue;  
 # else  
         if (strncmp(*ev, "LD_PRELOAD=", sizeof("LD_PRELOAD=") - 1) == 0)  
             continue;  
 # endif  
         nenvp[env_len++] = *ev;  
     }  
   
     /*  
      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see  
      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html  
      * XXX - need to support 32-bit and 64-bit variants  
      */  
 # if defined(__darwin__) || defined(__APPLE__)  
     nenvp[env_len++] = "DYLD_FORCE_FLAT_NAMESPACE=";  
     cp = fmt_string("DYLD_INSERT_LIBRARIES", noexec_path);  
 # elif defined(__osf__) || defined(__sgi)  
     easprintf(&cp, "_RLD_LIST=%s:DEFAULT", noexec_path);  
 # elif defined(_AIX)  
     cp = fmt_string("LDR_PRELOAD", noexec_path);  
 # else  
     cp = fmt_string("LD_PRELOAD", noexec_path);  
 # endif  
     if (cp == NULL)  
         error(1, NULL);  
     nenvp[env_len++] = cp;  
     nenvp[env_len] = NULL;  
   
     details->envp = nenvp;  
 #endif /* _PATH_SUDO_NOEXEC */  
 }  
   
 /*  
  * Setup the execution environment immediately prior to the call to execve()   * Setup the execution environment immediately prior to the call to execve()
 * Returns TRUE on success and FALSE on failure. * Returns true on success and false on failure.
  */   */
intbool
 exec_setup(struct command_details *details, const char *ptyname, int ptyfd)  exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
 {  {
    int rval = FALSE;    bool rval = false;
    struct passwd *pw;    debug_decl(exec_setup, SUDO_DEBUG_EXEC)
   
 #ifdef HAVE_SETAUTHDB  
     aix_setauthdb(IDtouser(details->euid));  
 #endif  
     pw = getpwuid(details->euid);  
 #ifdef HAVE_SETAUTHDB  
     aix_restoreauthdb();  
 #endif  
   
     /*  
      * Call policy plugin's session init before other setup occurs.  
      * The session init code is expected to print an error as needed.  
      */  
     if (policy_init_session(&policy_plugin, pw) != TRUE)  
         goto done;  
   
 #ifdef HAVE_SELINUX  #ifdef HAVE_SELINUX
     if (ISSET(details->flags, CD_RBAC_ENABLED)) {      if (ISSET(details->flags, CD_RBAC_ENABLED)) {
         if (selinux_setup(details->selinux_role, details->selinux_type,          if (selinux_setup(details->selinux_role, details->selinux_type,
Line 918  exec_setup(struct command_details *details, const char Line 918  exec_setup(struct command_details *details, const char
     }      }
 #endif  #endif
   
    if (pw != NULL) {    if (details->pw != NULL) {
 #ifdef HAVE_PROJECT_H  #ifdef HAVE_PROJECT_H
        set_project(pw);        set_project(details->pw);
 #endif  #endif
   #ifdef HAVE_PRIV_SET
       if (details->privs != NULL) {
           if (setppriv(PRIV_SET, PRIV_INHERITABLE, details->privs) != 0) {
               warning("unable to set privileges");
               goto done;
           }
       }
       if (details->limitprivs != NULL) {
           if (setppriv(PRIV_SET, PRIV_LIMIT, details->limitprivs) != 0) {
               warning("unable to set limit privileges");
               goto done;
           }
       } else if (details->privs != NULL) {
           if (setppriv(PRIV_SET, PRIV_LIMIT, details->privs) != 0) {
               warning("unable to set limit privileges");
               goto done;
           }
       }
   #endif /* HAVE_PRIV_SET */
   
 #ifdef HAVE_GETUSERATTR  #ifdef HAVE_GETUSERATTR
        aix_prep_user(pw->pw_name, ptyname ? ptyname : user_details.tty);        aix_prep_user(details->pw->pw_name, ptyname ? ptyname : user_details.tty);
 #endif  #endif
 #ifdef HAVE_LOGIN_CAP_H  #ifdef HAVE_LOGIN_CAP_H
         if (details->login_class) {          if (details->login_class) {
Line 931  exec_setup(struct command_details *details, const char Line 951  exec_setup(struct command_details *details, const char
             login_cap_t *lc;              login_cap_t *lc;
   
             /*              /*
             * We only use setusercontext() to set the nice value and rlimits.             * We only use setusercontext() to set the nice value and rlimits
              * unless this is a login shell (sudo -i).
              */               */
             lc = login_getclass((char *)details->login_class);              lc = login_getclass((char *)details->login_class);
             if (!lc) {              if (!lc) {
Line 939  exec_setup(struct command_details *details, const char Line 960  exec_setup(struct command_details *details, const char
                 errno = ENOENT;                  errno = ENOENT;
                 goto done;                  goto done;
             }              }
            flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;            if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
            if (setusercontext(lc, pw, pw->pw_uid, flags)) {                /* Set everything except user, group and login name. */
                if (pw->pw_uid != ROOT_UID) {                flags = LOGIN_SETALL;
                 CLR(flags, LOGIN_SETGROUP|LOGIN_SETLOGIN|LOGIN_SETUSER|LOGIN_SETENV|LOGIN_SETPATH);
                 CLR(details->flags, CD_SET_UMASK); /* LOGIN_UMASK instead */
             } else {
                 flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
             }
             if (setusercontext(lc, details->pw, details->pw->pw_uid, flags)) {
                 if (details->pw->pw_uid != ROOT_UID) {
                     warning(_("unable to set user context"));                      warning(_("unable to set user context"));
                     goto done;                      goto done;
                 } else                  } else
Line 954  exec_setup(struct command_details *details, const char Line 982  exec_setup(struct command_details *details, const char
     /*      /*
      * Set groups, including supplementary group vector.       * Set groups, including supplementary group vector.
      */       */
       if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {
           if (details->ngroups >= 0) {
               if (sudo_setgroups(details->ngroups, details->groups) < 0) {
                   warning(_("unable to set supplementary group IDs"));
                   goto done;
               }
           }
       }
 #ifdef HAVE_SETEUID  #ifdef HAVE_SETEUID
     if (ISSET(details->flags, CD_SET_EGID) && setegid(details->egid)) {      if (ISSET(details->flags, CD_SET_EGID) && setegid(details->egid)) {
         warning(_("unable to set effective gid to runas gid %u"),          warning(_("unable to set effective gid to runas gid %u"),
Line 967  exec_setup(struct command_details *details, const char Line 1003  exec_setup(struct command_details *details, const char
         goto done;          goto done;
     }      }
   
     if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {  
         if (details->ngroups >= 0) {  
             if (sudo_setgroups(details->ngroups, details->groups) < 0) {  
                 warning(_("unable to set supplementary group IDs"));  
                 goto done;  
             }  
         }  
     }  
   
     if (ISSET(details->flags, CD_SET_PRIORITY)) {      if (ISSET(details->flags, CD_SET_PRIORITY)) {
         if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) {          if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) {
             warning(_("unable to set process priority"));              warning(_("unable to set process priority"));
Line 991  exec_setup(struct command_details *details, const char Line 1018  exec_setup(struct command_details *details, const char
         }          }
     }      }
   
     if (ISSET(details->flags, CD_NOEXEC))  
         disable_execute(details);  
   
 #ifdef HAVE_SETRESUID  #ifdef HAVE_SETRESUID
     if (setresuid(details->uid, details->euid, details->euid) != 0) {      if (setresuid(details->uid, details->euid, details->euid) != 0) {
         warning(_("unable to change to runas uid (%u, %u)"), details->uid,          warning(_("unable to change to runas uid (%u, %u)"), details->uid,
Line 1029  exec_setup(struct command_details *details, const char Line 1053  exec_setup(struct command_details *details, const char
     }      }
   
     /*      /*
     * Restore nproc resource limit if pam_limits didn't do it for us.     * SuSE Enterprise Linux uses RLIMIT_NPROC and _SC_CHILD_MAX
      * interchangably.  This causes problems when setting RLIMIT_NPROC
      * to RLIM_INFINITY due to a bug in bash where bash tries to honor
      * the value of _SC_CHILD_MAX but treats a value of -1 as an error,
      * and uses a default value of 32 instead.
      *
      * To work around this problem, we restore the nproc resource limit
      * if sysconf(_SC_CHILD_MAX) is negative.  In most cases, pam_limits
      * will set RLIMIT_NPROC for us.
      *
      * We must do this *after* the uid change to avoid potential EAGAIN       * We must do this *after* the uid change to avoid potential EAGAIN
      * from setuid().       * from setuid().
      */       */
#if defined(__linux__)#if defined(__linux__) && defined(_SC_CHILD_MAX)
     {      {
         struct rlimit rl;          struct rlimit rl;
        if (getrlimit(RLIMIT_NPROC, &rl) == 0) {        long l;
         errno = 0;
         l = sysconf(_SC_CHILD_MAX);
         if (l == -1 && errno == 0 && getrlimit(RLIMIT_NPROC, &rl) == 0) {
             if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY)              if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY)
                 (void) setrlimit(RLIMIT_NPROC, &nproclimit);                  (void) setrlimit(RLIMIT_NPROC, &nproclimit);
         }          }
     }      }
 #endif  #endif
   
    rval = TRUE;    rval = true;
   
 done:  done:
    return rval;    debug_return_bool(rval);
 }  }
   
 /*  /*
Line 1058  run_command(struct command_details *details) Line 1094  run_command(struct command_details *details)
     struct plugin_container *plugin;      struct plugin_container *plugin;
     struct command_status cstat;      struct command_status cstat;
     int exitcode = 1;      int exitcode = 1;
       debug_decl(run_command, SUDO_DEBUG_EXEC)
   
     cstat.type = CMD_INVALID;      cstat.type = CMD_INVALID;
     cstat.val = 0;      cstat.val = 0;
   
    sudo_execve(details, &cstat);    sudo_execute(details, &cstat);
   
     switch (cstat.type) {      switch (cstat.type) {
     case CMD_ERRNO:      case CMD_ERRNO:
         /* exec_setup() or execve() returned an error. */          /* exec_setup() or execve() returned an error. */
        sudo_debug(9, "calling policy close with errno");        sudo_debug_printf(SUDO_DEBUG_DEBUG,
             "calling policy close with errno %d", cstat.val);
         policy_close(&policy_plugin, 0, cstat.val);          policy_close(&policy_plugin, 0, cstat.val);
         tq_foreach_fwd(&io_plugins, plugin) {          tq_foreach_fwd(&io_plugins, plugin) {
            sudo_debug(9, "calling I/O close with errno");            sudo_debug_printf(SUDO_DEBUG_DEBUG,
                 "calling I/O close with errno %d", cstat.val);
             iolog_close(plugin, 0, cstat.val);              iolog_close(plugin, 0, cstat.val);
         }          }
         exitcode = 1;          exitcode = 1;
         break;          break;
     case CMD_WSTATUS:      case CMD_WSTATUS:
         /* Command ran, exited or was killed. */          /* Command ran, exited or was killed. */
        sudo_debug(9, "calling policy close with wait status");        sudo_debug_printf(SUDO_DEBUG_DEBUG,
             "calling policy close with wait status %d", cstat.val);
         policy_close(&policy_plugin, cstat.val, 0);          policy_close(&policy_plugin, cstat.val, 0);
         tq_foreach_fwd(&io_plugins, plugin) {          tq_foreach_fwd(&io_plugins, plugin) {
            sudo_debug(9, "calling I/O close with wait status");            sudo_debug_printf(SUDO_DEBUG_DEBUG,
                 "calling I/O close with wait status %d", cstat.val);
             iolog_close(plugin, cstat.val, 0);              iolog_close(plugin, cstat.val, 0);
         }          }
         if (WIFEXITED(cstat.val))          if (WIFEXITED(cstat.val))
Line 1092  run_command(struct command_details *details) Line 1133  run_command(struct command_details *details)
         warningx(_("unexpected child termination condition: %d"), cstat.type);          warningx(_("unexpected child termination condition: %d"), cstat.type);
         break;          break;
     }      }
    return exitcode;    debug_return_int(exitcode);
 }  }
   
 static int  static int
 policy_open(struct plugin_container *plugin, char * const settings[],  policy_open(struct plugin_container *plugin, char * const settings[],
     char * const user_info[], char * const user_env[])      char * const user_info[], char * const user_env[])
 {  {
    return plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation,    int rval;
        _sudo_printf, settings, user_info, user_env);    debug_decl(policy_open, SUDO_DEBUG_PCOMM)
 
     /*
      * Backwards compatibility for older API versions
      */
     switch (plugin->u.generic->version) {
     case SUDO_API_MKVERSION(1, 0):
     case SUDO_API_MKVERSION(1, 1):
         rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version,
             sudo_conversation, _sudo_printf, settings, user_info, user_env);
         break;
     default:
         rval = plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation,
             _sudo_printf, settings, user_info, user_env, plugin->options);
     }
 
     debug_return_bool(rval);
 }  }
   
 static void  static void
 policy_close(struct plugin_container *plugin, int exit_status, int error)  policy_close(struct plugin_container *plugin, int exit_status, int error)
 {  {
       debug_decl(policy_close, SUDO_DEBUG_PCOMM)
     plugin->u.policy->close(exit_status, error);      plugin->u.policy->close(exit_status, error);
       debug_return;
 }  }
   
 static int  static int
 policy_show_version(struct plugin_container *plugin, int verbose)  policy_show_version(struct plugin_container *plugin, int verbose)
 {  {
    return plugin->u.policy->show_version(verbose);    debug_decl(policy_show_version, SUDO_DEBUG_PCOMM)
     debug_return_bool(plugin->u.policy->show_version(verbose));
 }  }
   
 static int  static int
Line 1120  policy_check(struct plugin_container *plugin, int argc Line 1180  policy_check(struct plugin_container *plugin, int argc
     char *env_add[], char **command_info[], char **argv_out[],      char *env_add[], char **command_info[], char **argv_out[],
     char **user_env_out[])      char **user_env_out[])
 {  {
    return plugin->u.policy->check_policy(argc, argv, env_add, command_info,    debug_decl(policy_check, SUDO_DEBUG_PCOMM)
        argv_out, user_env_out);    debug_return_bool(plugin->u.policy->check_policy(argc, argv, env_add,
         command_info, argv_out, user_env_out));
 }  }
   
 static int  static int
 policy_list(struct plugin_container *plugin, int argc, char * const argv[],  policy_list(struct plugin_container *plugin, int argc, char * const argv[],
     int verbose, const char *list_user)      int verbose, const char *list_user)
 {  {
       debug_decl(policy_list, SUDO_DEBUG_PCOMM)
     if (plugin->u.policy->list == NULL) {      if (plugin->u.policy->list == NULL) {
         warningx(_("policy plugin %s does not support listing privileges"),          warningx(_("policy plugin %s does not support listing privileges"),
             plugin->name);              plugin->name);
        return FALSE;        debug_return_bool(false);
     }      }
    return plugin->u.policy->list(argc, argv, verbose, list_user);    debug_return_bool(plugin->u.policy->list(argc, argv, verbose, list_user));
 }  }
   
 static int  static int
 policy_validate(struct plugin_container *plugin)  policy_validate(struct plugin_container *plugin)
 {  {
       debug_decl(policy_validate, SUDO_DEBUG_PCOMM)
     if (plugin->u.policy->validate == NULL) {      if (plugin->u.policy->validate == NULL) {
         warningx(_("policy plugin %s does not support the -v option"),          warningx(_("policy plugin %s does not support the -v option"),
             plugin->name);              plugin->name);
        return FALSE;        debug_return_bool(false);
     }      }
    return plugin->u.policy->validate();    debug_return_bool(plugin->u.policy->validate());
 }  }
   
 static void  static void
 policy_invalidate(struct plugin_container *plugin, int remove)  policy_invalidate(struct plugin_container *plugin, int remove)
 {  {
       debug_decl(policy_invalidate, SUDO_DEBUG_PCOMM)
     if (plugin->u.policy->invalidate == NULL) {      if (plugin->u.policy->invalidate == NULL) {
         errorx(1, _("policy plugin %s does not support the -k/-K options"),          errorx(1, _("policy plugin %s does not support the -k/-K options"),
             plugin->name);              plugin->name);
     }      }
     plugin->u.policy->invalidate(remove);      plugin->u.policy->invalidate(remove);
       debug_return;
 }  }
   
static intint
policy_init_session(struct plugin_container *plugin, struct passwd *pwd)policy_init_session(struct command_details *details)
 {  {
    if (plugin->u.policy->init_session)    int rval = true;
        return plugin->u.policy->init_session(pwd);    debug_decl(policy_init_session, SUDO_DEBUG_PCOMM)
    return TRUE;
     if (policy_plugin.u.policy->init_session) {
         /*
          * Backwards compatibility for older API versions
          */
         switch (policy_plugin.u.generic->version) {
         case SUDO_API_MKVERSION(1, 0):
         case SUDO_API_MKVERSION(1, 1):
             rval = policy_plugin.u.policy_1_0->init_session(details->pw);
             break;
         default:
             rval = policy_plugin.u.policy->init_session(details->pw,
                 &details->envp);
         }
     }
     debug_return_bool(rval);
 }  }
   
 static int  static int
Line 1171  iolog_open(struct plugin_container *plugin, char * con Line 1251  iolog_open(struct plugin_container *plugin, char * con
     int argc, char * const argv[], char * const user_env[])      int argc, char * const argv[], char * const user_env[])
 {  {
     int rval;      int rval;
       debug_decl(iolog_open, SUDO_DEBUG_PCOMM)
   
     /*      /*
     * Backwards compatibility for API major 1, minor 0     * Backwards compatibility for older API versions
      */       */
     switch (plugin->u.generic->version) {      switch (plugin->u.generic->version) {
     case SUDO_API_MKVERSION(1, 0):      case SUDO_API_MKVERSION(1, 0):
Line 1181  iolog_open(struct plugin_container *plugin, char * con Line 1262  iolog_open(struct plugin_container *plugin, char * con
             sudo_conversation, _sudo_printf, settings, user_info, argc, argv,              sudo_conversation, _sudo_printf, settings, user_info, argc, argv,
             user_env);              user_env);
         break;          break;
       case SUDO_API_MKVERSION(1, 1):
           rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
               sudo_conversation, _sudo_printf, settings, user_info,
               command_info, argc, argv, user_env);
           break;
     default:      default:
         rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,          rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
            _sudo_printf, settings, user_info, command_info, argc, argv,            _sudo_printf, settings, user_info, command_info,
            user_env);            argc, argv, user_env, plugin->options);
     }      }
    return rval;    debug_return_bool(rval);
 }  }
   
 static void  static void
 iolog_close(struct plugin_container *plugin, int exit_status, int error)  iolog_close(struct plugin_container *plugin, int exit_status, int error)
 {  {
       debug_decl(iolog_close, SUDO_DEBUG_PCOMM)
     plugin->u.io->close(exit_status, error);      plugin->u.io->close(exit_status, error);
       debug_return;
 }  }
   
 static int  static int
 iolog_show_version(struct plugin_container *plugin, int verbose)  iolog_show_version(struct plugin_container *plugin, int verbose)
 {  {
    return plugin->u.io->show_version(verbose);    debug_decl(iolog_show_version, SUDO_DEBUG_PCOMM)
     debug_return_bool(plugin->u.io->show_version(verbose));
 }  }
   
 /*  /*
 * Simple debugging/logging. * Remove the specified I/O logging plugin from the io_plugins list.
  * Deregisters any hooks before unlinking, then frees the container.
  */   */
voidstatic void
sudo_debug(int level, const char *fmt, ...)iolog_unlink(struct plugin_container *plugin)
 {  {
    va_list ap;    debug_decl(iolog_unlink, SUDO_DEBUG_PCOMM)
    char *buf; 
   
    if (level > debug_level)    /* Deregister hooks, if any. */
        return;    if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 2)) {
         if (plugin->u.io->deregister_hooks != NULL)
             plugin->u.io->deregister_hooks(SUDO_HOOK_VERSION,
                 deregister_hook);
     }
     /* Remove from io_plugins list and free. */
     tq_remove(&io_plugins, plugin);
     efree(plugin);
   
    /* Bracket fmt with program name and a newline to make it a single write */    debug_return;
    va_start(ap, fmt); 
    evasprintf(&buf, fmt, ap); 
    va_end(ap); 
    fprintf(stderr, "%s: %s\n", getprogname(), buf); 
    efree(buf); 
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>