Diff for /embedaddon/sudo/plugins/sudoers/parse.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2012/10/09 09:29:52 version 1.1.1.4, 2013/07/22 10:46:12
Line 1 Line 1
 /*  /*
 * Copyright (c) 2004-2005, 2007-2012 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2004-2005, 2007-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 19 Line 19
 #include <config.h>  #include <config.h>
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  
 #include <stdio.h>  #include <stdio.h>
 #ifdef STDC_HEADERS  #ifdef STDC_HEADERS
 # include <stdlib.h>  # include <stdlib.h>
Line 48 Line 47
 #include <gram.h>  #include <gram.h>
   
 /* Characters that must be quoted in sudoers */  /* Characters that must be quoted in sudoers */
#define SUDOERS_QUOTED  ":\\,=#\""#define SUDOERS_QUOTED  ":\\,=#\""
   
 /* sudoers nsswitch routines */  /* sudoers nsswitch routines */
 struct sudo_nss sudo_nss_file = {  struct sudo_nss sudo_nss_file = {
Line 68  struct sudo_nss sudo_nss_file = { Line 67  struct sudo_nss sudo_nss_file = {
 /*  /*
  * Parser externs.   * Parser externs.
  */   */
extern FILE *yyin;extern FILE *sudoersin;
 extern char *errorfile;  extern char *errorfile;
 extern int errorlineno;  extern int errorlineno;
 extern bool parse_error;  extern bool parse_error;
Line 76  extern bool parse_error; Line 75  extern bool parse_error;
 /*  /*
  * Local prototypes.   * Local prototypes.
  */   */
static void print_member(struct lbuf *, char *, int, int, int);static int display_bound_defaults(int dtype, struct lbuf *lbuf);
static int display_bound_defaults(int, struct lbuf *);static void print_member(struct lbuf *lbuf, struct member *m, int alias_type);
 static void print_member2(struct lbuf *lbuf, struct member *m,
     const char *separator, int alias_type);
   
 int  int
 sudo_file_open(struct sudo_nss *nss)  sudo_file_open(struct sudo_nss *nss)
Line 100  sudo_file_close(struct sudo_nss *nss) Line 101  sudo_file_close(struct sudo_nss *nss)
     if (nss->handle != NULL) {      if (nss->handle != NULL) {
         fclose(nss->handle);          fclose(nss->handle);
         nss->handle = NULL;          nss->handle = NULL;
        yyin = NULL;        sudoersin = NULL;
     }      }
     debug_return_int(0);      debug_return_int(0);
 }  }
Line 117  sudo_file_parse(struct sudo_nss *nss) Line 118  sudo_file_parse(struct sudo_nss *nss)
         debug_return_int(-1);          debug_return_int(-1);
   
     init_parser(sudoers_file, false);      init_parser(sudoers_file, false);
    yyin = nss->handle;    sudoersin = nss->handle;
    if (yyparse() != 0 || parse_error) {    if (sudoersparse() != 0 || parse_error) {
         if (errorlineno != -1) {          if (errorlineno != -1) {
            log_error(0, _("parse error in %s near line %d"),            log_warning(0, N_("parse error in %s near line %d"),
                 errorfile, errorlineno);                  errorfile, errorlineno);
         } else {          } else {
            log_error(0, _("parse error in %s"), errorfile);            log_warning(0, N_("parse error in %s"), errorfile);
         }          }
         debug_return_int(-1);          debug_return_int(-1);
     }      }
Line 290  sudo_file_lookup(struct sudo_nss *nss, int validated,  Line 291  sudo_file_lookup(struct sudo_nss *nss, int validated, 
     debug_return_int(validated);      debug_return_int(validated);
 }  }
   
   #define TAG_SET(tt) \
           ((tt) != UNSPEC && (tt) != IMPLIED)
   
 #define TAG_CHANGED(t) \  #define TAG_CHANGED(t) \
        (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t)        (TAG_SET(cs->tags.t) && cs->tags.t != tags->t)
   
 static void  static void
 sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,  sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
     struct lbuf *lbuf)      struct lbuf *lbuf)
 {  {
     struct member *m;  
     debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)      debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)
   
 #ifdef HAVE_PRIV_SET  #ifdef HAVE_PRIV_SET
Line 332  sudo_file_append_cmnd(struct cmndspec *cs, struct cmnd Line 335  sudo_file_append_cmnd(struct cmndspec *cs, struct cmnd
         lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");          lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");
         tags->log_output = cs->tags.log_output;          tags->log_output = cs->tags.log_output;
     }      }
    m = cs->cmnd;    print_member(lbuf, cs->cmnd, CMNDALIAS);
    print_member(lbuf, m->name, m->type, m->negated, 
        CMNDALIAS); 
     debug_return;      debug_return;
 }  }
   
   #define RUNAS_CHANGED(cs1, cs2) \
           (cs1 == NULL || cs2 == NULL || \
            cs1->runasuserlist.first != cs2->runasuserlist.first || \
            cs1->runasuserlist.last != cs2->runasuserlist.last || \
            cs1->runasgrouplist.first != cs2->runasgrouplist.first || \
            cs1->runasgrouplist.last != cs2->runasgrouplist.last)
   
 static int  static int
 sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,  sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
     struct lbuf *lbuf)      struct lbuf *lbuf)
 {  {
    struct cmndspec *cs;    struct cmndspec *cs, *prev_cs;
     struct member *m;      struct member *m;
     struct privilege *priv;      struct privilege *priv;
     struct cmndtag tags;      struct cmndtag tags;
     int nfound = 0;      int nfound = 0;
     debug_decl(sudo_file_display_priv_short, SUDO_DEBUG_NSS)      debug_decl(sudo_file_display_priv_short, SUDO_DEBUG_NSS)
   
       /* gcc -Wuninitialized false positive */
       tags.noexec = UNSPEC;
       tags.setenv = UNSPEC;
       tags.nopasswd = UNSPEC;
       tags.log_input = UNSPEC;
       tags.log_output = UNSPEC;
     tq_foreach_fwd(&us->privileges, priv) {      tq_foreach_fwd(&us->privileges, priv) {
         if (hostlist_matches(&priv->hostlist) != ALLOW)          if (hostlist_matches(&priv->hostlist) != ALLOW)
             continue;              continue;
        tags.noexec = UNSPEC;        prev_cs = NULL;
        tags.setenv = UNSPEC; 
        tags.nopasswd = UNSPEC; 
        tags.log_input = UNSPEC; 
        tags.log_output = UNSPEC; 
        lbuf_append(lbuf, "    "); 
         tq_foreach_fwd(&priv->cmndlist, cs) {          tq_foreach_fwd(&priv->cmndlist, cs) {
            if (cs != tq_first(&priv->cmndlist))            if (RUNAS_CHANGED(cs, prev_cs)) {
                lbuf_append(lbuf, ", ");                if (cs != tq_first(&priv->cmndlist))
            lbuf_append(lbuf, "(");                    lbuf_append(lbuf, "\n");
            if (!tq_empty(&cs->runasuserlist)) {                lbuf_append(lbuf, "    (");
                tq_foreach_fwd(&cs->runasuserlist, m) {                if (!tq_empty(&cs->runasuserlist)) {
                    if (m != tq_first(&cs->runasuserlist))                    tq_foreach_fwd(&cs->runasuserlist, m) {
                        lbuf_append(lbuf, ", ");                        if (m != tq_first(&cs->runasuserlist))
                    print_member(lbuf, m->name, m->type, m->negated,                            lbuf_append(lbuf, ", ");
                        RUNASALIAS);                        print_member(lbuf, m, RUNASALIAS);
                     }
                 } else if (tq_empty(&cs->runasgrouplist)) {
                     lbuf_append(lbuf, "%s", def_runas_default);
                 } else {
                     lbuf_append(lbuf, "%s", pw->pw_name);
                 }                  }
            } else if (tq_empty(&cs->runasgrouplist)) {                if (!tq_empty(&cs->runasgrouplist)) {
                lbuf_append(lbuf, "%s", def_runas_default);                    lbuf_append(lbuf, " : ");
            } else {                    tq_foreach_fwd(&cs->runasgrouplist, m) {
                lbuf_append(lbuf, "%s", pw->pw_name);                        if (m != tq_first(&cs->runasgrouplist))
            }                            lbuf_append(lbuf, ", ");
            if (!tq_empty(&cs->runasgrouplist)) {                        print_member(lbuf, m, RUNASALIAS);
                lbuf_append(lbuf, " : ");                    }
                tq_foreach_fwd(&cs->runasgrouplist, m) { 
                    if (m != tq_first(&cs->runasgrouplist)) 
                        lbuf_append(lbuf, ", "); 
                    print_member(lbuf, m->name, m->type, m->negated, 
                        RUNASALIAS); 
                 }                  }
                   lbuf_append(lbuf, ") ");
                   tags.noexec = UNSPEC;
                   tags.setenv = UNSPEC;
                   tags.nopasswd = UNSPEC;
                   tags.log_input = UNSPEC;
                   tags.log_output = UNSPEC;
               } else if (cs != tq_first(&priv->cmndlist)) {
                   lbuf_append(lbuf, ", ");
             }              }
             lbuf_append(lbuf, ") ");  
             sudo_file_append_cmnd(cs, &tags, lbuf);              sudo_file_append_cmnd(cs, &tags, lbuf);
               prev_cs = cs;
             nfound++;              nfound++;
         }          }
         lbuf_append(lbuf, "\n");          lbuf_append(lbuf, "\n");
Line 392  sudo_file_display_priv_short(struct passwd *pw, struct Line 409  sudo_file_display_priv_short(struct passwd *pw, struct
     debug_return_int(nfound);      debug_return_int(nfound);
 }  }
   
   #define TAGS_CHANGED(ot, nt) \
           ((TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
            (TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \
            (TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \
            (TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \
            (TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output))
   
   /*
    * Compare the current cmndspec with the previous one to determine
    * whether we need to start a new long entry for "sudo -ll".
    * Returns true if we should start a new long entry, else false.
    */
   static bool
   new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
   {
       if (prev_cs == NULL)
           return true;
       if (RUNAS_CHANGED(cs, prev_cs) || TAGS_CHANGED(cs->tags, prev_cs->tags))
           return true;
   #ifdef HAVE_PRIV_SET
       if (cs->privs && (!prev_cs->privs || strcmp(cs->privs, prev_cs->privs) != 0))
           return true;
       if (cs->limitprivs && (!prev_cs->limitprivs || strcmp(cs->limitprivs, prev_cs->limitprivs) != 0))
           return true;
   #endif /* HAVE_PRIV_SET */
   #ifdef HAVE_SELINUX
       if (cs->role && (!prev_cs->role || strcmp(cs->role, prev_cs->role) != 0))
           return true;
       if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0))
           return true;
   #endif /* HAVE_SELINUX */
       return false;
   }
   
 static int  static int
 sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,  sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
     struct lbuf *lbuf)      struct lbuf *lbuf)
 {  {
    struct cmndspec *cs;    struct cmndspec *cs, *prev_cs;
     struct member *m;      struct member *m;
     struct privilege *priv;      struct privilege *priv;
    struct cmndtag tags;    int nfound = 0, olen;
    int nfound = 0; 
     debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)      debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
   
     tq_foreach_fwd(&us->privileges, priv) {      tq_foreach_fwd(&us->privileges, priv) {
         if (hostlist_matches(&priv->hostlist) != ALLOW)          if (hostlist_matches(&priv->hostlist) != ALLOW)
             continue;              continue;
        tags.noexec = UNSPEC;        prev_cs = NULL;
        tags.setenv = UNSPEC; 
        tags.nopasswd = UNSPEC; 
        tags.log_input = UNSPEC; 
        tags.log_output = UNSPEC; 
        lbuf_append(lbuf, _("\nSudoers entry:\n")); 
         tq_foreach_fwd(&priv->cmndlist, cs) {          tq_foreach_fwd(&priv->cmndlist, cs) {
            lbuf_append(lbuf, _("    RunAsUsers: "));            if (new_long_entry(cs, prev_cs)) {
            if (!tq_empty(&cs->runasuserlist)) {                lbuf_append(lbuf, _("\nSudoers entry:\n"));
                tq_foreach_fwd(&cs->runasuserlist, m) {                lbuf_append(lbuf, _("    RunAsUsers: "));
                    if (m != tq_first(&cs->runasuserlist))                if (!tq_empty(&cs->runasuserlist)) {
                        lbuf_append(lbuf, ", ");                    tq_foreach_fwd(&cs->runasuserlist, m) {
                    print_member(lbuf, m->name, m->type, m->negated,                        if (m != tq_first(&cs->runasuserlist))
                        RUNASALIAS);                            lbuf_append(lbuf, ", ");
                         print_member(lbuf, m, RUNASALIAS);
                     }
                 } else if (tq_empty(&cs->runasgrouplist)) {
                     lbuf_append(lbuf, "%s", def_runas_default);
                 } else {
                     lbuf_append(lbuf, "%s", pw->pw_name);
                 }                  }
             } else if (tq_empty(&cs->runasgrouplist)) {  
                 lbuf_append(lbuf, "%s", def_runas_default);  
             } else {  
                 lbuf_append(lbuf, "%s", pw->pw_name);  
             }  
             lbuf_append(lbuf, "\n");  
             if (!tq_empty(&cs->runasgrouplist)) {  
                 lbuf_append(lbuf, _("    RunAsGroups: "));  
                 tq_foreach_fwd(&cs->runasgrouplist, m) {  
                     if (m != tq_first(&cs->runasgrouplist))  
                         lbuf_append(lbuf, ", ");  
                     print_member(lbuf, m->name, m->type, m->negated,  
                         RUNASALIAS);  
                 }  
                 lbuf_append(lbuf, "\n");                  lbuf_append(lbuf, "\n");
                   if (!tq_empty(&cs->runasgrouplist)) {
                       lbuf_append(lbuf, _("    RunAsGroups: "));
                       tq_foreach_fwd(&cs->runasgrouplist, m) {
                           if (m != tq_first(&cs->runasgrouplist))
                               lbuf_append(lbuf, ", ");
                           print_member(lbuf, m, RUNASALIAS);
                       }
                       lbuf_append(lbuf, "\n");
                   }
                   olen = lbuf->len;
                   lbuf_append(lbuf, _("    Options: "));
                   if (TAG_SET(cs->tags.setenv))
                       lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!");
                   if (TAG_SET(cs->tags.noexec))
                       lbuf_append(lbuf, "%snoexec, ", cs->tags.noexec ? "" : "!");
                   if (TAG_SET(cs->tags.nopasswd))
                       lbuf_append(lbuf, "%sauthenticate, ", cs->tags.nopasswd ? "!" : "");
                   if (TAG_SET(cs->tags.log_input))
                       lbuf_append(lbuf, "%slog_input, ", cs->tags.log_input ? "" : "!");
                   if (TAG_SET(cs->tags.log_output))
                       lbuf_append(lbuf, "%slog_output, ", cs->tags.log_output ? "" : "!");
                   if (lbuf->buf[lbuf->len - 2] == ',') {
                       lbuf->len -= 2;     /* remove trailing ", " */
                       lbuf_append(lbuf, "\n");
                   } else {
                       lbuf->len = olen;   /* no options */
                   }
   #ifdef HAVE_PRIV_SET
                   if (cs->privs)
                       lbuf_append(lbuf, "    Privs: %s\n", cs->privs);
                   if (cs->limitprivs)
                       lbuf_append(lbuf, "    Limitprivs: %s\n", cs->limitprivs);
   #endif /* HAVE_PRIV_SET */
   #ifdef HAVE_SELINUX
                   if (cs->role)
                       lbuf_append(lbuf, "    Role: %s\n", cs->role);
                   if (cs->type)
                       lbuf_append(lbuf, "    Type: %s\n", cs->type);
   #endif /* HAVE_SELINUX */
                   lbuf_append(lbuf, _("    Commands:\n"));
             }              }
            lbuf_append(lbuf, _("    Commands:\n\t"));            lbuf_append(lbuf, "\t");
            sudo_file_append_cmnd(cs, &tags, lbuf);            print_member2(lbuf, cs->cmnd, "\n\t", CMNDALIAS);
             lbuf_append(lbuf, "\n");              lbuf_append(lbuf, "\n");
               prev_cs = cs;
             nfound++;              nfound++;
         }          }
     }      }
Line 585  display_bound_defaults(int dtype, struct lbuf *lbuf) Line 663  display_bound_defaults(int dtype, struct lbuf *lbuf)
             for (m = binding; m != NULL; m = m->next) {              for (m = binding; m != NULL; m = m->next) {
                 if (m != binding)                  if (m != binding)
                     lbuf_append(lbuf, ",");                      lbuf_append(lbuf, ",");
                print_member(lbuf, m->name, m->type, m->negated, atype);                print_member(lbuf, m, atype);
                 lbuf_append(lbuf, " ");                  lbuf_append(lbuf, " ");
             }              }
         } else          } else
Line 651  done: Line 729  done:
  */   */
 static void  static void
 _print_member(struct lbuf *lbuf, char *name, int type, int negated,  _print_member(struct lbuf *lbuf, char *name, int type, int negated,
    int alias_type)    const char *separator, int alias_type)
 {  {
     struct alias *a;      struct alias *a;
     struct member *m;      struct member *m;
Line 676  _print_member(struct lbuf *lbuf, char *name, int type, Line 754  _print_member(struct lbuf *lbuf, char *name, int type,
             }              }
             break;              break;
         case ALIAS:          case ALIAS:
            if ((a = alias_find(name, alias_type)) != NULL) {            if ((a = alias_get(name, alias_type)) != NULL) {
                 tq_foreach_fwd(&a->members, m) {                  tq_foreach_fwd(&a->members, m) {
                     if (m != tq_first(&a->members))                      if (m != tq_first(&a->members))
                        lbuf_append(lbuf, ", ");                        lbuf_append(lbuf, "%s", separator);
                     _print_member(lbuf, m->name, m->type,                      _print_member(lbuf, m->name, m->type,
                        negated ? !m->negated : m->negated, alias_type);                        negated ? !m->negated : m->negated, separator,
                         alias_type);
                 }                  }
                   alias_put(a);
                 break;                  break;
             }              }
             /* FALLTHROUGH */              /* FALLTHROUGH */
Line 694  _print_member(struct lbuf *lbuf, char *name, int type, Line 774  _print_member(struct lbuf *lbuf, char *name, int type,
 }  }
   
 static void  static void
print_member(struct lbuf *lbuf, char *name, int type, int negated,print_member(struct lbuf *lbuf, struct member *m, int alias_type)
 {
     _print_member(lbuf, m->name, m->type, m->negated, ", ", alias_type);
 }
 
 static void
 print_member2(struct lbuf *lbuf, struct member *m, const char *separator,
     int alias_type)      int alias_type)
 {  {
    alias_seqno++;    _print_member(lbuf, m->name, m->type, m->negated, separator, alias_type);
    _print_member(lbuf, name, type, negated, alias_type); 
 }  }

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


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