Diff for /embedaddon/sudo/common/sudo_conf.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/10/09 09:29:52 version 1.1.1.3, 2013/07/22 10:46:11
Line 1 Line 1
 /*  /*
 * Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2009-2013 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 17 Line 17
 #include <config.h>  #include <config.h>
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <stdio.h>  #include <stdio.h>
 #ifdef STDC_HEADERS  #ifdef STDC_HEADERS
Line 44 Line 43
 #endif /* HAVE_UNISTD_H */  #endif /* HAVE_UNISTD_H */
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
   #include <limits.h>
   
 #define SUDO_ERROR_WRAP 0  #define SUDO_ERROR_WRAP 0
   
Line 56 Line 56
 #include "sudo_conf.h"  #include "sudo_conf.h"
 #include "sudo_debug.h"  #include "sudo_debug.h"
 #include "secure_path.h"  #include "secure_path.h"
   
   #define DEFAULT_TEXT_DOMAIN     "sudo"
 #include "gettext.h"  #include "gettext.h"
   
 #ifdef __TANDEM  #ifdef __TANDEM
Line 64 Line 66
 # define ROOT_UID       0  # define ROOT_UID       0
 #endif  #endif
   
 #ifndef _PATH_SUDO_ASKPASS  
 # define _PATH_SUDO_ASKPASS     NULL  
 #endif  
   
 extern bool atobool(const char *str); /* atobool.c */  extern bool atobool(const char *str); /* atobool.c */
   
 struct sudo_conf_table {  struct sudo_conf_table {
     const char *name;      const char *name;
     unsigned int namelen;      unsigned int namelen;
    bool (*setter)(const char *entry);    void (*setter)(const char *entry, const char *conf_file);
 };  };
   
 struct sudo_conf_paths {  struct sudo_conf_paths {
Line 82  struct sudo_conf_paths { Line 80  struct sudo_conf_paths {
     const char *pval;      const char *pval;
 };  };
   
static bool set_debug(const char *entry);static void set_debug(const char *entry, const char *conf_file);
static bool set_path(const char *entry);static void set_path(const char *entry, const char *conf_file);
static bool set_plugin(const char *entry);static void set_plugin(const char *entry, const char *conf_file);
static bool set_variable(const char *entry);static void set_variable(const char *entry, const char *conf_file);
 static void set_var_disable_coredump(const char *entry, const char *conf_file);
 static void set_var_group_source(const char *entry, const char *conf_file);
 static void set_var_max_groups(const char *entry, const char *conf_file);
   
   static unsigned int conf_lineno;
   
 static struct sudo_conf_table sudo_conf_table[] = {  static struct sudo_conf_table sudo_conf_table[] = {
     { "Debug", sizeof("Debug") - 1, set_debug },      { "Debug", sizeof("Debug") - 1, set_debug },
     { "Path", sizeof("Path") - 1, set_path },      { "Path", sizeof("Path") - 1, set_path },
Line 95  static struct sudo_conf_table sudo_conf_table[] = { Line 98  static struct sudo_conf_table sudo_conf_table[] = {
     { NULL }      { NULL }
 };  };
   
   static struct sudo_conf_table sudo_conf_table_vars[] = {
       { "disable_coredump", sizeof("disable_coredump") - 1, set_var_disable_coredump },
       { "group_source", sizeof("group_source") - 1, set_var_group_source },
       { "max_groups", sizeof("max_groups") - 1, set_var_max_groups },
       { NULL }
   };
   
 static struct sudo_conf_data {  static struct sudo_conf_data {
     bool disable_coredump;      bool disable_coredump;
       int group_source;
       int max_groups;
     const char *debug_flags;      const char *debug_flags;
    struct sudo_conf_paths paths[3];    struct sudo_conf_paths paths[4];
     struct plugin_info_list plugins;      struct plugin_info_list plugins;
 } sudo_conf_data = {  } sudo_conf_data = {
     true,      true,
       GROUP_SOURCE_ADAPTIVE,
       -1,
     NULL,      NULL,
     {      {
 #define SUDO_CONF_ASKPASS_IDX   0  #define SUDO_CONF_ASKPASS_IDX   0
         { "askpass", sizeof("askpass") - 1, _PATH_SUDO_ASKPASS },          { "askpass", sizeof("askpass") - 1, _PATH_SUDO_ASKPASS },
   #define SUDO_CONF_SESH_IDX      1
           { "sesh", sizeof("sesh") - 1, _PATH_SUDO_SESH },
 #ifdef _PATH_SUDO_NOEXEC  #ifdef _PATH_SUDO_NOEXEC
#define SUDO_CONF_NOEXEC_IDX    1#define SUDO_CONF_NOEXEC_IDX    2
         { "noexec", sizeof("noexec") - 1, _PATH_SUDO_NOEXEC },          { "noexec", sizeof("noexec") - 1, _PATH_SUDO_NOEXEC },
 #endif  #endif
         { NULL }          { NULL }
Line 117  static struct sudo_conf_data { Line 133  static struct sudo_conf_data {
 /*  /*
  * "Set variable_name value"   * "Set variable_name value"
  */   */
static boolstatic void
set_variable(const char *entry)set_variable(const char *entry, const char *conf_file)
 {  {
#undef DC_LEN    struct sudo_conf_table *var;
#define DC_LEN (sizeof("disable_coredump") - 1)
    /* Currently the only variable supported is "disable_coredump". */    for (var = sudo_conf_table_vars; var->name != NULL; var++) {
    if (strncmp(entry, "disable_coredump", DC_LEN) == 0 &&        if (strncmp(entry, var->name, var->namelen) == 0 &&
        isblank((unsigned char)entry[DC_LEN])) {            isblank((unsigned char)entry[var->namelen])) {
        entry += DC_LEN + 1;            entry += var->namelen + 1;
        while (isblank((unsigned char)*entry))            while (isblank((unsigned char)*entry))
            entry++;                entry++;
        sudo_conf_data.disable_coredump = atobool(entry);            var->setter(entry, conf_file);
             break;
         }
     }      }
 #undef DC_LEN  
     return true;  
 }  }
   
   static void
   set_var_disable_coredump(const char *entry, const char *conf_file)
   {
       int val = atobool(entry);
   
       if (val != -1)
           sudo_conf_data.disable_coredump = val;
   }
   
   static void
   set_var_group_source(const char *entry, const char *conf_file)
   {
       if (strcasecmp(entry, "adaptive") == 0) {
           sudo_conf_data.group_source = GROUP_SOURCE_ADAPTIVE;
       } else if (strcasecmp(entry, "static") == 0) {
           sudo_conf_data.group_source = GROUP_SOURCE_STATIC;
       } else if (strcasecmp(entry, "dynamic") == 0) {
           sudo_conf_data.group_source = GROUP_SOURCE_DYNAMIC;
       } else {
           warningx(_("unsupported group source `%s' in %s, line %d"), entry,
               conf_file, conf_lineno);
       }
   }
   
   static void
   set_var_max_groups(const char *entry, const char *conf_file)
   {
       long lval;
       char *ep;
   
       lval = strtol(entry, &ep, 10);
       if (*entry == '\0' || *ep != '\0' || lval < 0 || lval > INT_MAX ||
           (errno == ERANGE && lval == LONG_MAX)) {
           warningx(_("invalid max groups `%s' in %s, line %d"), entry,
                       conf_file, conf_lineno);
       } else {
           sudo_conf_data.max_groups = (int)lval;
       }
   }
   
 /*  /*
  * "Debug progname debug_file debug_flags"   * "Debug progname debug_file debug_flags"
  */   */
static boolstatic void
set_debug(const char *entry)set_debug(const char *entry, const char *conf_file)
 {  {
     size_t filelen, proglen;      size_t filelen, proglen;
     const char *progname;      const char *progname;
Line 151  set_debug(const char *entry) Line 207  set_debug(const char *entry)
     proglen = strlen(progname);      proglen = strlen(progname);
     if (strncmp(entry, progname, proglen) != 0 ||      if (strncmp(entry, progname, proglen) != 0 ||
         !isblank((unsigned char)entry[proglen]))          !isblank((unsigned char)entry[proglen]))
        return false;        return;
     entry += proglen + 1;      entry += proglen + 1;
     while (isblank((unsigned char)*entry))      while (isblank((unsigned char)*entry))
         entry++;          entry++;
   
     debug_flags = strpbrk(entry, " \t");      debug_flags = strpbrk(entry, " \t");
     if (debug_flags == NULL)      if (debug_flags == NULL)
        return false;        return;
     filelen = (size_t)(debug_flags - entry);      filelen = (size_t)(debug_flags - entry);
     while (isblank((unsigned char)*debug_flags))      while (isblank((unsigned char)*debug_flags))
         debug_flags++;          debug_flags++;
Line 170  set_debug(const char *entry) Line 226  set_debug(const char *entry)
     efree(debug_file);      efree(debug_file);
   
     sudo_conf_data.debug_flags = debug_flags;      sudo_conf_data.debug_flags = debug_flags;
   
     return true;  
 }  }
   
static boolstatic void
set_path(const char *entry)set_path(const char *entry, const char *conf_file)
 {  {
     const char *name, *path;      const char *name, *path;
     struct sudo_conf_paths *cur;      struct sudo_conf_paths *cur;
Line 184  set_path(const char *entry) Line 238  set_path(const char *entry)
     name = entry;      name = entry;
     path = strpbrk(entry, " \t");      path = strpbrk(entry, " \t");
     if (path == NULL)      if (path == NULL)
        return false;        return;
     while (isblank((unsigned char)*path))      while (isblank((unsigned char)*path))
         path++;          path++;
   
Line 196  set_path(const char *entry) Line 250  set_path(const char *entry)
             break;              break;
         }          }
     }      }
   
     return true;  
 }  }
   
static boolstatic void
set_plugin(const char *entry)set_plugin(const char *entry, const char *conf_file)
 {  {
     struct plugin_info *info;      struct plugin_info *info;
     const char *name, *path, *cp, *ep;      const char *name, *path, *cp, *ep;
Line 213  set_plugin(const char *entry) Line 265  set_plugin(const char *entry)
     name = entry;      name = entry;
     path = strpbrk(entry, " \t");      path = strpbrk(entry, " \t");
     if (path == NULL)      if (path == NULL)
        return false;        return;
     namelen = (size_t)(path - name);      namelen = (size_t)(path - name);
     while (isblank((unsigned char)*path))      while (isblank((unsigned char)*path))
         path++;          path++;
Line 248  set_plugin(const char *entry) Line 300  set_plugin(const char *entry)
     info->options = options;      info->options = options;
     info->prev = info;      info->prev = info;
     /* info->next = NULL; */      /* info->next = NULL; */
       info->lineno = conf_lineno;
     tq_append(&sudo_conf_data.plugins, info);      tq_append(&sudo_conf_data.plugins, info);
   
     return true;  
 }  }
   
 const char *  const char *
Line 259  sudo_conf_askpass_path(void) Line 310  sudo_conf_askpass_path(void)
     return sudo_conf_data.paths[SUDO_CONF_ASKPASS_IDX].pval;      return sudo_conf_data.paths[SUDO_CONF_ASKPASS_IDX].pval;
 }  }
   
   const char *
   sudo_conf_sesh_path(void)
   {
       return sudo_conf_data.paths[SUDO_CONF_SESH_IDX].pval;
   }
   
 #ifdef _PATH_SUDO_NOEXEC  #ifdef _PATH_SUDO_NOEXEC
 const char *  const char *
 sudo_conf_noexec_path(void)  sudo_conf_noexec_path(void)
Line 273  sudo_conf_debug_flags(void) Line 330  sudo_conf_debug_flags(void)
     return sudo_conf_data.debug_flags;      return sudo_conf_data.debug_flags;
 }  }
   
   int
   sudo_conf_group_source(void)
   {
       return sudo_conf_data.group_source;
   }
   
   int
   sudo_conf_max_groups(void)
   {
       return sudo_conf_data.max_groups;
   }
   
 struct plugin_info_list *  struct plugin_info_list *
 sudo_conf_plugins(void)  sudo_conf_plugins(void)
 {  {
Line 289  sudo_conf_disable_coredump(void) Line 358  sudo_conf_disable_coredump(void)
  * Reads in /etc/sudo.conf and populates sudo_conf_data.   * Reads in /etc/sudo.conf and populates sudo_conf_data.
  */   */
 void  void
sudo_conf_read(void)sudo_conf_read(const char *conf_file)
 {  {
     struct sudo_conf_table *cur;      struct sudo_conf_table *cur;
     struct stat sb;      struct stat sb;
     FILE *fp;      FILE *fp;
    char *cp;    char *cp, *line = NULL;
     char *prev_locale = estrdup(setlocale(LC_ALL, NULL));
     size_t linesize = 0;
   
    switch (sudo_secure_file(_PATH_SUDO_CONF, ROOT_UID, -1, &sb)) {    /* Parse sudo.conf in the "C" locale. */
        case SUDO_PATH_SECURE:    if (prev_locale[0] != 'C' || prev_locale[1] != '\0')
            break;        setlocale(LC_ALL, "C");
        case SUDO_PATH_MISSING:
            /* Root should always be able to read sudo.conf. */    if (conf_file == NULL) {
            if (errno != ENOENT && geteuid() == ROOT_UID)        conf_file = _PATH_SUDO_CONF;
                warning(_("unable to stat %s"), _PATH_SUDO_CONF);        switch (sudo_secure_file(conf_file, ROOT_UID, -1, &sb)) {
            goto done;            case SUDO_PATH_SECURE:
        case SUDO_PATH_BAD_TYPE:                break;
            warningx(_("%s is not a regular file"), _PATH_SUDO_CONF);            case SUDO_PATH_MISSING:
            goto done;                /* Root should always be able to read sudo.conf. */
        case SUDO_PATH_WRONG_OWNER:                if (errno != ENOENT && geteuid() == ROOT_UID)
            warningx(_("%s is owned by uid %u, should be %u"),                    warning(_("unable to stat %s"), conf_file);
                _PATH_SUDO_CONF, (unsigned int) sb.st_uid, ROOT_UID);                goto done;
            goto done;            case SUDO_PATH_BAD_TYPE:
        case SUDO_PATH_WORLD_WRITABLE:                warningx(_("%s is not a regular file"), conf_file);
            warningx(_("%s is world writable"), _PATH_SUDO_CONF);                goto done;
            goto done;            case SUDO_PATH_WRONG_OWNER:
        case SUDO_PATH_GROUP_WRITABLE:                warningx(_("%s is owned by uid %u, should be %u"),
            warningx(_("%s is group writable"), _PATH_SUDO_CONF);                    conf_file, (unsigned int) sb.st_uid, ROOT_UID);
            goto done;                goto done;
        default:            case SUDO_PATH_WORLD_WRITABLE:
            /* NOTREACHED */                warningx(_("%s is world writable"), conf_file);
            goto done;                goto done;
             case SUDO_PATH_GROUP_WRITABLE:
                 warningx(_("%s is group writable"), conf_file);
                 goto done;
             default:
                 /* NOTREACHED */
                 goto done;
         }
     }      }
   
    if ((fp = fopen(_PATH_SUDO_CONF, "r")) == NULL) {    if ((fp = fopen(conf_file, "r")) == NULL) {
         if (errno != ENOENT && geteuid() == ROOT_UID)          if (errno != ENOENT && geteuid() == ROOT_UID)
            warning(_("unable to open %s"), _PATH_SUDO_CONF);            warning(_("unable to open %s"), conf_file);
         goto done;          goto done;
     }      }
   
    while ((cp = sudo_parseln(fp)) != NULL) {    conf_lineno = 0;
        /* Skip blank or comment lines */    while (sudo_parseln(&line, &linesize, &conf_lineno, fp) != -1) {
        if (*cp == '\0')        if (*(cp = line) == '\0')
            continue;            continue;           /* empty line or comment */
   
         for (cur = sudo_conf_table; cur->name != NULL; cur++) {          for (cur = sudo_conf_table; cur->name != NULL; cur++) {
             if (strncasecmp(cp, cur->name, cur->namelen) == 0 &&              if (strncasecmp(cp, cur->name, cur->namelen) == 0 &&
Line 339  sudo_conf_read(void) Line 417  sudo_conf_read(void)
                 cp += cur->namelen;                  cp += cur->namelen;
                 while (isblank((unsigned char)*cp))                  while (isblank((unsigned char)*cp))
                     cp++;                      cp++;
                if (cur->setter(cp))                cur->setter(cp, conf_file);
                    break;                break;
             }              }
         }          }
     }      }
     fclose(fp);      fclose(fp);
       free(line);
 done:  done:
    return;    /* Restore locale if needed. */
     if (prev_locale[0] != 'C' || prev_locale[1] != '\0')
         setlocale(LC_ALL, prev_locale);
     efree(prev_locale);
 }  }

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


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