Diff for /embedaddon/sudo/plugins/sudoers/visudo.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 16:23:02 version 1.1.1.2, 2012/05/29 12:26:49
Line 1 Line 1
 /*  /*
 * Copyright (c) 1996, 1998-2005, 2007-2011 * Copyright (c) 1996, 1998-2005, 2007-2012
  *      Todd C. Miller <Todd.Miller@courtesan.com>   *      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
Line 81 Line 81
 #include "redblack.h"  #include "redblack.h"
 #include "gettext.h"  #include "gettext.h"
 #include "sudoers_version.h"  #include "sudoers_version.h"
   #include "sudo_conf.h"
 #include <gram.h>  #include <gram.h>
   
 struct sudoersfile {  struct sudoersfile {
Line 93  struct sudoersfile { Line 94  struct sudoersfile {
 };  };
 TQ_DECLARE(sudoersfile)  TQ_DECLARE(sudoersfile)
   
   sudo_conv_t sudo_conv;  /* NULL in non-plugin */
   
 /*  /*
  * Function prototypes   * Function prototypes
  */   */
Line 100  static void quit(int); Line 103  static void quit(int);
 static char *get_args(char *);  static char *get_args(char *);
 static char *get_editor(char **);  static char *get_editor(char **);
 static void get_hostname(void);  static void get_hostname(void);
static char whatnow(void);static int whatnow(void);
static int check_aliases(int, int);static int check_aliases(bool, bool);
static int check_syntax(char *, int, int);static bool check_syntax(char *, bool, bool, bool);
static int edit_sudoers(struct sudoersfile *, char *, char *, int);static bool edit_sudoers(struct sudoersfile *, char *, char *, int);
static int install_sudoers(struct sudoersfile *, int);static bool install_sudoers(struct sudoersfile *, bool);
 static int print_unused(void *, void *);  static int print_unused(void *, void *);
static int reparse_sudoers(char *, char *, int, int);static void reparse_sudoers(char *, char *, bool, bool);
 static int run_command(char *, char **);  static int run_command(char *, char **);
 static int visudo_printf(int msg_type, const char *fmt, ...);  static int visudo_printf(int msg_type, const char *fmt, ...);
 static void setup_signals(void);  static void setup_signals(void);
Line 124  extern void yyrestart(FILE *); Line 127  extern void yyrestart(FILE *);
 extern struct rbtree *aliases;  extern struct rbtree *aliases;
 extern FILE *yyin;  extern FILE *yyin;
 extern char *sudoers, *errorfile;  extern char *sudoers, *errorfile;
extern int errorlineno, parse_error;extern int errorlineno;
 extern bool parse_error;
 /* For getopt(3) */  /* For getopt(3) */
 extern char *optarg;  extern char *optarg;
 extern int optind;  extern int optind;
Line 138  struct passwd *list_pw; Line 142  struct passwd *list_pw;
 sudo_printf_t sudo_printf = visudo_printf;  sudo_printf_t sudo_printf = visudo_printf;
 static struct sudoersfile_list sudoerslist;  static struct sudoersfile_list sudoerslist;
 static struct rbtree *alias_freelist;  static struct rbtree *alias_freelist;
   static bool checkonly;
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
     struct sudoersfile *sp;      struct sudoersfile *sp;
     char *args, *editor, *sudoers_path;      char *args, *editor, *sudoers_path;
    int ch, checkonly, quiet, strict, oldperms;    int ch, exitcode = 0;
     bool quiet, strict, oldperms;
     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 163  main(int argc, char *argv[]) Line 173  main(int argc, char *argv[])
     if (argc < 1)      if (argc < 1)
         usage(1);          usage(1);
   
       /* Read sudo.conf. */
       sudo_conf_read();
   
     /*      /*
      * Arg handling.       * Arg handling.
      */       */
    checkonly = oldperms = quiet = strict = FALSE;    checkonly = oldperms = quiet = strict = false;
     sudoers_path = _PATH_SUDOERS;      sudoers_path = _PATH_SUDOERS;
     while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) {      while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) {
         switch (ch) {          switch (ch) {
             case 'V':              case 'V':
                 (void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION);                  (void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION);
                 (void) printf(_("%s grammar version %d\n"), getprogname(), SUDOERS_GRAMMAR_VERSION);                  (void) printf(_("%s grammar version %d\n"), getprogname(), SUDOERS_GRAMMAR_VERSION);
                exit(0);                goto done;
             case 'c':              case 'c':
                 checkonly++;            /* check mode */                  checkonly++;            /* check mode */
                 break;                  break;
             case 'f':              case 'f':
                 sudoers_path = optarg;  /* sudoers file path */                  sudoers_path = optarg;  /* sudoers file path */
                oldperms = TRUE;                oldperms = true;
                 break;                  break;
             case 'h':              case 'h':
                 help();                  help();
Line 194  main(int argc, char *argv[]) Line 207  main(int argc, char *argv[])
                 usage(1);                  usage(1);
         }          }
     }      }
    argc -= optind;    /* There should be no other command line arguments. */
    argv += optind;    if (argc - optind != 0)
    if (argc) 
         usage(1);          usage(1);
   
     sudo_setpwent();      sudo_setpwent();
Line 211  main(int argc, char *argv[]) Line 223  main(int argc, char *argv[])
     /* Setup defaults data structures. */      /* Setup defaults data structures. */
     init_defaults();      init_defaults();
   
    if (checkonly)    if (checkonly) {
        exit(check_syntax(sudoers_path, quiet, strict));        exitcode = check_syntax(sudoers_path, quiet, strict, oldperms) ? 0 : 1;
         goto done;
     }
   
     /*      /*
      * Parse the existing sudoers file(s) in quiet mode to highlight any       * Parse the existing sudoers file(s) in quiet mode to highlight any
      * existing errors and to pull in editor and env_editor conf values.       * existing errors and to pull in editor and env_editor conf values.
      */       */
    if ((yyin = open_sudoers(sudoers_path, TRUE, NULL)) == NULL) {    if ((yyin = open_sudoers(sudoers_path, true, NULL)) == NULL) {
         error(1, "%s", sudoers_path);          error(1, "%s", sudoers_path);
     }      }
     init_parser(sudoers_path, 0);      init_parser(sudoers_path, 0);
Line 245  main(int argc, char *argv[]) Line 259  main(int argc, char *argv[])
     /* Check edited files for a parse error and re-edit any that fail. */      /* Check edited files for a parse error and re-edit any that fail. */
     reparse_sudoers(editor, args, strict, quiet);      reparse_sudoers(editor, args, strict, quiet);
   
    /* Install the sudoers temp files. */    /* Install the sudoers temp files as needed. */
     tq_foreach_fwd(&sudoerslist, sp) {      tq_foreach_fwd(&sudoerslist, sp) {
        if (!sp->modified)        (void) install_sudoers(sp, oldperms);
            (void) unlink(sp->tpath); 
        else 
            (void) install_sudoers(sp, oldperms); 
     }      }
   
    exit(0);done:
     sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);                
     exit(exitcode);
 }  }
   
 /*  /*
Line 282  static char *lineno_editors[] = { Line 295  static char *lineno_editors[] = {
   
 /*  /*
  * Edit each sudoers file.   * Edit each sudoers file.
 * Returns TRUE on success, else FALSE. * Returns true on success, else false.
  */   */
static intstatic bool
 edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)  edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
 {  {
     int tfd;                            /* sudoers temp file descriptor */      int tfd;                            /* sudoers temp file descriptor */
    int modified;                      /* was the file modified? */    bool modified;                      /* was the file modified? */
     int ac;                             /* argument count */      int ac;                             /* argument count */
     char **av;                          /* argument vector for run_command */      char **av;                          /* argument vector for run_command */
     char *cp;                           /* scratch char pointer */      char *cp;                           /* scratch char pointer */
Line 299  edit_sudoers(struct sudoersfile *sp, char *editor, cha Line 312  edit_sudoers(struct sudoersfile *sp, char *editor, cha
     off_t orig_size;                    /* starting size of sudoers file */      off_t orig_size;                    /* starting size of sudoers file */
     ssize_t nread;                      /* number of bytes read */      ssize_t nread;                      /* number of bytes read */
     struct stat sb;                     /* stat buffer */      struct stat sb;                     /* stat buffer */
       bool rval = false;                  /* return value */
       debug_decl(edit_sudoers, SUDO_DEBUG_UTIL)
   
     if (fstat(sp->fd, &sb) == -1)      if (fstat(sp->fd, &sb) == -1)
         error(1, _("unable to stat %s"), sp->path);          error(1, _("unable to stat %s"), sp->path);
Line 361  edit_sudoers(struct sudoersfile *sp, char *editor, cha Line 376  edit_sudoers(struct sudoersfile *sp, char *editor, cha
     /* Find the length of the argument vector */      /* Find the length of the argument vector */
     ac = 3 + (lineno > 0);      ac = 3 + (lineno > 0);
     if (args) {      if (args) {
        int wasblank;        bool wasblank;
   
         ac++;          ac++;
        for (wasblank = FALSE, cp = args; *cp; cp++) {        for (wasblank = false, cp = args; *cp; cp++) {
             if (isblank((unsigned char) *cp))              if (isblank((unsigned char) *cp))
                wasblank = TRUE;                wasblank = true;
             else if (wasblank) {              else if (wasblank) {
                wasblank = FALSE;                wasblank = false;
                 ac++;                  ac++;
             }              }
         }          }
Line 407  edit_sudoers(struct sudoersfile *sp, char *editor, cha Line 422  edit_sudoers(struct sudoersfile *sp, char *editor, cha
         if (stat(sp->tpath, &sb) < 0) {          if (stat(sp->tpath, &sb) < 0) {
             warningx(_("unable to stat temporary file (%s), %s unchanged"),              warningx(_("unable to stat temporary file (%s), %s unchanged"),
                 sp->tpath, sp->path);                  sp->tpath, sp->path);
            return FALSE;            goto done;
         }          }
         if (sb.st_size == 0 && orig_size != 0) {          if (sb.st_size == 0 && orig_size != 0) {
             warningx(_("zero length temporary file (%s), %s unchanged"),              warningx(_("zero length temporary file (%s), %s unchanged"),
                 sp->tpath, sp->path);                  sp->tpath, sp->path);
            sp->modified = TRUE;            sp->modified = true;
            return FALSE;            goto done;
         }          }
     } else {      } else {
         warningx(_("editor (%s) failed, %s unchanged"), editor, sp->path);          warningx(_("editor (%s) failed, %s unchanged"), editor, sp->path);
        return FALSE;        goto done;
     }      }
   
     /* Set modified bit if use changed the file. */      /* Set modified bit if use changed the file. */
    modified = TRUE;    modified = true;
     mtim_get(&sb, &tv);      mtim_get(&sb, &tv);
     if (orig_size == sb.st_size && timevalcmp(&orig_mtim, &tv, ==)) {      if (orig_size == sb.st_size && timevalcmp(&orig_mtim, &tv, ==)) {
         /*          /*
Line 430  edit_sudoers(struct sudoersfile *sp, char *editor, cha Line 445  edit_sudoers(struct sudoersfile *sp, char *editor, cha
          */           */
         timevalsub(&tv1, &tv2);          timevalsub(&tv1, &tv2);
         if (timevalisset(&tv2))          if (timevalisset(&tv2))
            modified = FALSE;            modified = false;
     }      }
   
     /*      /*
Line 441  edit_sudoers(struct sudoersfile *sp, char *editor, cha Line 456  edit_sudoers(struct sudoersfile *sp, char *editor, cha
     else      else
         warningx(_("%s unchanged"), sp->tpath);          warningx(_("%s unchanged"), sp->tpath);
   
    return TRUE;    rval = true;
 done:
     debug_return_bool(rval);
 }  }
   
 /*  /*
  * Parse sudoers after editing and re-edit any ones that caused a parse error.   * Parse sudoers after editing and re-edit any ones that caused a parse error.
  * Returns TRUE on success, else FALSE.  
  */   */
static intstatic void
reparse_sudoers(char *editor, char *args, int strict, int quiet)reparse_sudoers(char *editor, char *args, bool strict, bool quiet)
 {  {
     struct sudoersfile *sp, *last;      struct sudoersfile *sp, *last;
     FILE *fp;      FILE *fp;
     int ch;      int ch;
       debug_decl(reparse_sudoers, SUDO_DEBUG_UTIL)
   
     /*      /*
      * Parse the edited sudoers files and do sanity checking       * Parse the edited sudoers files and do sanity checking
Line 475  reparse_sudoers(char *editor, char *args, int strict,  Line 492  reparse_sudoers(char *editor, char *args, int strict, 
         if (yyparse() && !parse_error) {          if (yyparse() && !parse_error) {
             warningx(_("unabled to parse temporary file (%s), unknown error"),              warningx(_("unabled to parse temporary file (%s), unknown error"),
                 sp->tpath);                  sp->tpath);
            parse_error = TRUE;            parse_error = true;
             errorfile = sp->path;              errorfile = sp->path;
         }          }
         fclose(yyin);          fclose(yyin);
         if (!parse_error) {          if (!parse_error) {
             if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER) ||              if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER) ||
                 check_aliases(strict, quiet) != 0) {                  check_aliases(strict, quiet) != 0) {
                parse_error = TRUE;                parse_error = true;
                 errorfile = sp->path;                  errorfile = sp->path;
             }              }
         }          }
Line 492  reparse_sudoers(char *editor, char *args, int strict,  Line 509  reparse_sudoers(char *editor, char *args, int strict, 
          */           */
         if (parse_error) {          if (parse_error) {
             switch (whatnow()) {              switch (whatnow()) {
                case 'Q' :      parse_error = FALSE;       /* ignore parse error */                case 'Q' :      parse_error = false;       /* ignore parse error */
                                 break;                                  break;
                case 'x' :      cleanup(0);                case 'x' :      /* XXX - should return instead of exiting */
                                 cleanup(0);
                                 sudo_debug_exit_int(__func__, __FILE__,
                                     __LINE__, sudo_debug_subsys, 0);
                                 exit(0);                                  exit(0);
                                 break;                                  break;
             }              }
Line 522  reparse_sudoers(char *editor, char *args, int strict,  Line 542  reparse_sudoers(char *editor, char *args, int strict, 
         }          }
     } while (parse_error);      } while (parse_error);
   
    return TRUE;    debug_return;
 }  }
   
 /*  /*
  * Set the owner and mode on a sudoers temp file and   * Set the owner and mode on a sudoers temp file and
 * move it into place.  Returns TRUE on success, else FALSE. * move it into place.  Returns true on success, else false.
  */   */
static intstatic bool
install_sudoers(struct sudoersfile *sp, int oldperms)install_sudoers(struct sudoersfile *sp, bool oldperms)
 {  {
     struct stat sb;      struct stat sb;
       bool rval = false;
       debug_decl(install_sudoers, SUDO_DEBUG_UTIL)
   
       if (!sp->modified) {
           /*
            * No changes but fix owner/mode if needed.
            */
           (void) unlink(sp->tpath);
           if (!oldperms && fstat(sp->fd, &sb) != -1) {
               if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID)
                   ignore_result(chown(sp->path, SUDOERS_UID, SUDOERS_GID));
               if ((sb.st_mode & 0777) != SUDOERS_MODE)
                   ignore_result(chmod(sp->path, SUDOERS_MODE));
           }
           rval = true;
           goto done;
       }
   
     /*      /*
      * Change mode and ownership of temp file so when       * Change mode and ownership of temp file so when
      * we move it to sp->path things are kosher.       * we move it to sp->path things are kosher.
Line 554  install_sudoers(struct sudoersfile *sp, int oldperms) Line 591  install_sudoers(struct sudoersfile *sp, int oldperms)
         if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) {          if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) {
             warning(_("unable to set (uid, gid) of %s to (%u, %u)"),              warning(_("unable to set (uid, gid) of %s to (%u, %u)"),
                 sp->tpath, SUDOERS_UID, SUDOERS_GID);                  sp->tpath, SUDOERS_UID, SUDOERS_GID);
            return FALSE;            goto done;
         }          }
         if (chmod(sp->tpath, SUDOERS_MODE) != 0) {          if (chmod(sp->tpath, SUDOERS_MODE) != 0) {
             warning(_("unable to change mode of %s to 0%o"), sp->tpath,              warning(_("unable to change mode of %s to 0%o"), sp->tpath,
                 SUDOERS_MODE);                  SUDOERS_MODE);
            return FALSE;            goto done;
         }          }
     }      }
   
Line 593  install_sudoers(struct sudoersfile *sp, int oldperms) Line 630  install_sudoers(struct sudoersfile *sp, int oldperms)
                 (void) unlink(sp->tpath);                  (void) unlink(sp->tpath);
                 efree(sp->tpath);                  efree(sp->tpath);
                 sp->tpath = NULL;                  sp->tpath = NULL;
                return FALSE;                goto done;
             }              }
             efree(sp->tpath);              efree(sp->tpath);
             sp->tpath = NULL;              sp->tpath = NULL;
         } else {          } else {
             warning(_("error renaming %s, %s unchanged"), sp->tpath, sp->path);              warning(_("error renaming %s, %s unchanged"), sp->tpath, sp->path);
             (void) unlink(sp->tpath);              (void) unlink(sp->tpath);
            return FALSE;            goto done;
         }          }
     }      }
    return TRUE;    rval = true;
 done:
     debug_return_bool(rval);
 }  }
   
 /* STUB */  /* STUB */
Line 621  init_envtables(void) Line 660  init_envtables(void)
 }  }
   
 /* STUB */  /* STUB */
intbool
 user_is_exempt(void)  user_is_exempt(void)
 {  {
    return FALSE;    return false;
 }  }
   
 /* STUB */  /* STUB */
Line 645  sudo_endspent(void) Line 684  sudo_endspent(void)
 int  int
 group_plugin_query(const char *user, const char *group, const struct passwd *pw)  group_plugin_query(const char *user, const char *group, const struct passwd *pw)
 {  {
    return FALSE;    return false;
 }  }
   
 /*  /*
  * Assuming a parse error occurred, prompt the user for what they want   * Assuming a parse error occurred, prompt the user for what they want
  * to do now.  Returns the first letter of their choice.   * to do now.  Returns the first letter of their choice.
  */   */
static charstatic int
 whatnow(void)  whatnow(void)
 {  {
     int choice, c;      int choice, c;
       debug_decl(whatnow, SUDO_DEBUG_UTIL)
   
     for (;;) {      for (;;) {
         (void) fputs(_("What now? "), stdout);          (void) fputs(_("What now? "), stdout);
Line 670  whatnow(void) Line 710  whatnow(void)
             case 'e':              case 'e':
             case 'x':              case 'x':
             case 'Q':              case 'Q':
                return choice;                debug_return_int(choice);
             default:              default:
                 (void) puts(_("Options are:\n"                  (void) puts(_("Options are:\n"
                     "  (e)dit sudoers file again\n"                      "  (e)dit sudoers file again\n"
Line 686  whatnow(void) Line 726  whatnow(void)
 static void  static void
 setup_signals(void)  setup_signals(void)
 {  {
        sigaction_t sa;    sigaction_t sa;
     debug_decl(setup_signals, SUDO_DEBUG_UTIL)
   
        /*    /*
         * Setup signal handlers to cleanup nicely.     * Setup signal handlers to cleanup nicely.
         */     */
        zero_bytes(&sa, sizeof(sa));    zero_bytes(&sa, sizeof(sa));
        sigemptyset(&sa.sa_mask);    sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;    sa.sa_flags = SA_RESTART;
        sa.sa_handler = quit;    sa.sa_handler = quit;
        (void) sigaction(SIGTERM, &sa, NULL);    (void) sigaction(SIGTERM, &sa, NULL);
        (void) sigaction(SIGHUP, &sa, NULL);    (void) sigaction(SIGHUP, &sa, NULL);
        (void) sigaction(SIGINT, &sa, NULL);    (void) sigaction(SIGINT, &sa, NULL);
        (void) sigaction(SIGQUIT, &sa, NULL);    (void) sigaction(SIGQUIT, &sa, NULL);
 
     debug_return;
 }  }
   
 static int  static int
Line 706  run_command(char *path, char **argv) Line 749  run_command(char *path, char **argv)
 {  {
     int status;      int status;
     pid_t pid, rv;      pid_t pid, rv;
       debug_decl(run_command, SUDO_DEBUG_UTIL)
   
    switch (pid = fork()) {    switch (pid = sudo_debug_fork()) {
         case -1:          case -1:
             error(1, _("unable to execute %s"), path);              error(1, _("unable to execute %s"), path);
             break;      /* NOTREACHED */              break;      /* NOTREACHED */
Line 725  run_command(char *path, char **argv) Line 769  run_command(char *path, char **argv)
         rv = waitpid(pid, &status, 0);          rv = waitpid(pid, &status, 0);
     } while (rv == -1 && errno == EINTR);      } while (rv == -1 && errno == EINTR);
   
    if (rv == -1 || !WIFEXITED(status))    if (rv != -1)
        return -1;        rv = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
    return WEXITSTATUS(status);    debug_return_int(rv);
 }  }
   
static intstatic bool
check_syntax(char *sudoers_path, int quiet, int strict)check_owner(const char *path, bool quiet)
 {  {
     struct stat sb;      struct stat sb;
    int error;    bool ok = true;
     debug_decl(check_owner, SUDO_DEBUG_UTIL)
   
       if (stat(path, &sb) == 0) {
           if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID) {
               ok = false;
               if (!quiet) {
                   fprintf(stderr,
                       _("%s: wrong owner (uid, gid) should be (%u, %u)\n"),
                       path, SUDOERS_UID, SUDOERS_GID);
                   }
           }
           if ((sb.st_mode & 07777) != SUDOERS_MODE) {
               ok = false;
               if (!quiet) {
                   fprintf(stderr, _("%s: bad permissions, should be mode 0%o\n"),
                       path, SUDOERS_MODE);
               }
           }
       }
       debug_return_bool(ok);
   }
   
   static bool
   check_syntax(char *sudoers_path, bool quiet, bool strict, bool oldperms)
   {
       bool ok = false;
       debug_decl(check_syntax, SUDO_DEBUG_UTIL)
   
     if (strcmp(sudoers_path, "-") == 0) {      if (strcmp(sudoers_path, "-") == 0) {
         yyin = stdin;          yyin = stdin;
         sudoers_path = "stdin";          sudoers_path = "stdin";
     } else if ((yyin = fopen(sudoers_path, "r")) == NULL) {      } else if ((yyin = fopen(sudoers_path, "r")) == NULL) {
         if (!quiet)          if (!quiet)
             warning(_("unable to open %s"), sudoers_path);              warning(_("unable to open %s"), sudoers_path);
        exit(1);        goto done;
     }      }
     init_parser(sudoers_path, quiet);      init_parser(sudoers_path, quiet);
     if (yyparse() && !parse_error) {      if (yyparse() && !parse_error) {
         if (!quiet)          if (!quiet)
             warningx(_("failed to parse %s file, unknown error"), sudoers_path);              warningx(_("failed to parse %s file, unknown error"), sudoers_path);
        parse_error = TRUE;        parse_error = true;
         errorfile = sudoers_path;          errorfile = sudoers_path;
     }      }
     if (!parse_error && check_aliases(strict, quiet) != 0) {      if (!parse_error && check_aliases(strict, quiet) != 0) {
        parse_error = TRUE;        parse_error = true;
         errorfile = sudoers_path;          errorfile = sudoers_path;
     }      }
    error = parse_error;    ok = !parse_error;
    if (!quiet) {
        if (parse_error) {    if (parse_error) {
         if (!quiet) {
             if (errorlineno != -1)              if (errorlineno != -1)
                 (void) printf(_("parse error in %s near line %d\n"),                  (void) printf(_("parse error in %s near line %d\n"),
                     errorfile, errorlineno);                      errorfile, errorlineno);
             else              else
                 (void) printf(_("parse error in %s\n"), errorfile);                  (void) printf(_("parse error in %s\n"), errorfile);
        } else {        }
     } else {
         struct sudoersfile *sp;
 
         /* Parsed OK, check mode and owner. */
         if (oldperms || check_owner(sudoers_path, quiet))
             (void) printf(_("%s: parsed OK\n"), sudoers_path);              (void) printf(_("%s: parsed OK\n"), sudoers_path);
           else
               ok = false;
           tq_foreach_fwd(&sudoerslist, sp) {
               if (oldperms || check_owner(sp->path, quiet))
                   (void) printf(_("%s: parsed OK\n"), sp->path);
               else
                   ok = false;
         }          }
     }      }
     /* Check mode and owner in strict mode. */  
     if (strict && yyin != stdin && fstat(fileno(yyin), &sb) == 0) {  
         if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID) {  
             error = TRUE;  
             if (!quiet) {  
                 fprintf(stderr,  
                     _("%s: wrong owner (uid, gid) should be (%u, %u)\n"),  
                     sudoers_path, SUDOERS_UID, SUDOERS_GID);  
                 }  
         }  
         if ((sb.st_mode & 07777) != SUDOERS_MODE) {  
             error = TRUE;  
             if (!quiet) {  
                 fprintf(stderr, _("%s: bad permissions, should be mode 0%o\n"),  
                     sudoers_path, SUDOERS_MODE);  
             }  
         }  
     }  
   
    return error;done:
     debug_return_bool(ok);
 }  }
   
 /*  /*
Line 794  check_syntax(char *sudoers_path, int quiet, int strict Line 861  check_syntax(char *sudoers_path, int quiet, int strict
  * any subsequent files #included via a callback from the parser.   * any subsequent files #included via a callback from the parser.
  */   */
 FILE *  FILE *
open_sudoers(const char *path, int doedit, int *keepopen)open_sudoers(const char *path, bool doedit, bool *keepopen)
 {  {
     struct sudoersfile *entry;      struct sudoersfile *entry;
     FILE *fp;      FILE *fp;
       int open_flags;
       debug_decl(open_sudoers, SUDO_DEBUG_UTIL)
   
       if (checkonly)
           open_flags = O_RDONLY;
       else
           open_flags = O_RDWR | O_CREAT;
   
     /* Check for existing entry */      /* Check for existing entry */
     tq_foreach_fwd(&sudoerslist, entry) {      tq_foreach_fwd(&sudoerslist, entry) {
         if (strcmp(path, entry->path) == 0)          if (strcmp(path, entry->path) == 0)
             break;              break;
     }      }
     if (entry == NULL) {      if (entry == NULL) {
        entry = emalloc(sizeof(*entry));        entry = ecalloc(1, sizeof(*entry));
         entry->path = estrdup(path);          entry->path = estrdup(path);
        entry->modified = 0;        /* entry->modified = 0; */
         entry->prev = entry;          entry->prev = entry;
        entry->next = NULL;        /* entry->next = NULL; */
        entry->fd = open(entry->path, O_RDWR | O_CREAT, SUDOERS_MODE);        entry->fd = open(entry->path, open_flags, SUDOERS_MODE);
        entry->tpath = NULL;        /* entry->tpath = NULL; */
         entry->doedit = doedit;          entry->doedit = doedit;
         if (entry->fd == -1) {          if (entry->fd == -1) {
             warning("%s", entry->path);              warning("%s", entry->path);
             efree(entry);              efree(entry);
            return NULL;            debug_return_ptr(NULL);
         }          }
        if (!lock_file(entry->fd, SUDO_TLOCK))        if (!checkonly && !lock_file(entry->fd, SUDO_TLOCK))
             errorx(1, _("%s busy, try again later"), entry->path);              errorx(1, _("%s busy, try again later"), entry->path);
         if ((fp = fdopen(entry->fd, "r")) == NULL)          if ((fp = fdopen(entry->fd, "r")) == NULL)
             error(1, "%s", entry->path);              error(1, "%s", entry->path);
Line 835  open_sudoers(const char *path, int doedit, int *keepop Line 909  open_sudoers(const char *path, int doedit, int *keepop
         }          }
     }      }
     if (keepopen != NULL)      if (keepopen != NULL)
        *keepopen = TRUE;        *keepopen = true;
    return fp;    debug_return_ptr(fp);
 }  }
   
 static char *  static char *
 get_editor(char **args)  get_editor(char **args)
 {  {
     char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs;      char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs;
       debug_decl(get_editor, SUDO_DEBUG_UTIL)
   
     /*      /*
      * Check VISUAL and EDITOR environment variables to see which editor       * Check VISUAL and EDITOR environment variables to see which editor
Line 936  get_editor(char **args) Line 1011  get_editor(char **args)
             errorx(1, _("no editor found (editor path = %s)"), def_editor);              errorx(1, _("no editor found (editor path = %s)"), def_editor);
     }      }
     *args = EditorArgs;      *args = EditorArgs;
    return Editor;    debug_return_str(Editor);
 }  }
   
 /*  /*
Line 946  static char * Line 1021  static char *
 get_args(char *cmnd)  get_args(char *cmnd)
 {  {
     char *args;      char *args;
       debug_decl(get_args, SUDO_DEBUG_UTIL)
   
     args = cmnd;      args = cmnd;
     while (*args && !isblank((unsigned char) *args))      while (*args && !isblank((unsigned char) *args))
Line 955  get_args(char *cmnd) Line 1031  get_args(char *cmnd)
         while (*args && isblank((unsigned char) *args))          while (*args && isblank((unsigned char) *args))
             args++;              args++;
     }      }
    return *args ? args : NULL;    debug_return_str(*args ? args : NULL);
 }  }
   
 /*  /*
Line 965  static void Line 1041  static void
 get_hostname(void)  get_hostname(void)
 {  {
     char *p, thost[MAXHOSTNAMELEN + 1];      char *p, thost[MAXHOSTNAMELEN + 1];
       debug_decl(get_hostname, SUDO_DEBUG_UTIL)
   
    if (gethostname(thost, sizeof(thost)) != 0) {    if (gethostname(thost, sizeof(thost)) != -1) {
        user_host = user_shost = "localhost";        thost[sizeof(thost) - 1] = '\0';
        return;        user_host = estrdup(thost);
    } 
    thost[sizeof(thost) - 1] = '\0'; 
    user_host = estrdup(thost); 
   
    if ((p = strchr(user_host, '.'))) {        if ((p = strchr(user_host, '.'))) {
        *p = '\0';            *p = '\0';
        user_shost = estrdup(user_host);            user_shost = estrdup(user_host);
        *p = '.';            *p = '.';
         } else {
             user_shost = user_host;
         }
     } else {      } else {
        user_shost = user_host;        user_host = user_shost = "localhost";
     }      }
       debug_return;
 }  }
   
static intstatic bool
alias_remove_recursive(char *name, int type, int strict, int quiet)alias_remove_recursive(char *name, int type)
 {  {
     struct member *m;      struct member *m;
     struct alias *a;      struct alias *a;
    int error = 0;    bool rval = true;
     debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS)
   
     if ((a = alias_find(name, type)) != NULL) {      if ((a = alias_find(name, type)) != NULL) {
         tq_foreach_fwd(&a->members, m) {          tq_foreach_fwd(&a->members, m) {
             if (m->type == ALIAS) {              if (m->type == ALIAS) {
                if (!alias_remove_recursive(m->name, type, strict, quiet))                if (!alias_remove_recursive(m->name, type))
                    error = 1;                    rval = false;
             }              }
         }          }
     }      }
Line 1001  alias_remove_recursive(char *name, int type, int stric Line 1080  alias_remove_recursive(char *name, int type, int stric
     a = alias_remove(name, type);      a = alias_remove(name, type);
     if (a)      if (a)
         rbinsert(alias_freelist, a);          rbinsert(alias_freelist, a);
    return error;    debug_return_bool(rval);
 }  }
   
 static int  static int
Line 1009  check_alias(char *name, int type, int strict, int quie Line 1088  check_alias(char *name, int type, int strict, int quie
 {  {
     struct member *m;      struct member *m;
     struct alias *a;      struct alias *a;
    int error = 0;    int errors = 0;
     debug_decl(check_alias, SUDO_DEBUG_ALIAS)
   
     if ((a = alias_find(name, type)) != NULL) {      if ((a = alias_find(name, type)) != NULL) {
         /* check alias contents */          /* check alias contents */
         tq_foreach_fwd(&a->members, m) {          tq_foreach_fwd(&a->members, m) {
             if (m->type == ALIAS)              if (m->type == ALIAS)
                error += check_alias(m->name, type, strict, quiet);                errors += check_alias(m->name, type, strict, quiet);
         }          }
     } else {      } else {
         if (!quiet) {          if (!quiet) {
Line 1034  check_alias(char *name, int type, int strict, int quie Line 1114  check_alias(char *name, int type, int strict, int quie
                 type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" :                  type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" :
                 "Unknown", name);                  "Unknown", name);
         }          }
        error++;        errors++;
     }      }
   
    return error;    debug_return_int(errors);
 }  }
   
 /*  /*
Line 1045  check_alias(char *name, int type, int strict, int quie Line 1125  check_alias(char *name, int type, int strict, int quie
  * aliases or unused aliases.   * aliases or unused aliases.
  */   */
 static int  static int
check_aliases(int strict, int quiet)check_aliases(bool strict, bool quiet)
 {  {
     struct cmndspec *cs;      struct cmndspec *cs;
     struct member *m, *binding;      struct member *m, *binding;
     struct privilege *priv;      struct privilege *priv;
     struct userspec *us;      struct userspec *us;
     struct defaults *d;      struct defaults *d;
    int atype, error = 0;    int atype, errors = 0;
     debug_decl(check_aliases, SUDO_DEBUG_ALIAS)
   
     alias_freelist = rbcreate(alias_compare);      alias_freelist = rbcreate(alias_compare);
   
Line 1061  check_aliases(int strict, int quiet) Line 1142  check_aliases(int strict, int quiet)
         tq_foreach_fwd(&us->users, m) {          tq_foreach_fwd(&us->users, m) {
             if (m->type == ALIAS) {              if (m->type == ALIAS) {
                 alias_seqno++;                  alias_seqno++;
                error += check_alias(m->name, USERALIAS, strict, quiet);                errors += check_alias(m->name, USERALIAS, strict, quiet);
             }              }
         }          }
         tq_foreach_fwd(&us->privileges, priv) {          tq_foreach_fwd(&us->privileges, priv) {
             tq_foreach_fwd(&priv->hostlist, m) {              tq_foreach_fwd(&priv->hostlist, m) {
                 if (m->type == ALIAS) {                  if (m->type == ALIAS) {
                     alias_seqno++;                      alias_seqno++;
                    error += check_alias(m->name, HOSTALIAS, strict, quiet);                    errors += check_alias(m->name, HOSTALIAS, strict, quiet);
                 }                  }
             }              }
             tq_foreach_fwd(&priv->cmndlist, cs) {              tq_foreach_fwd(&priv->cmndlist, cs) {
                 tq_foreach_fwd(&cs->runasuserlist, m) {                  tq_foreach_fwd(&cs->runasuserlist, m) {
                     if (m->type == ALIAS) {                      if (m->type == ALIAS) {
                         alias_seqno++;                          alias_seqno++;
                        error += check_alias(m->name, RUNASALIAS, strict, quiet);                        errors += check_alias(m->name, RUNASALIAS, strict, quiet);
                     }                      }
                 }                  }
                 if ((m = cs->cmnd)->type == ALIAS) {                  if ((m = cs->cmnd)->type == ALIAS) {
                     alias_seqno++;                      alias_seqno++;
                    error += check_alias(m->name, CMNDALIAS, strict, quiet);                    errors += check_alias(m->name, CMNDALIAS, strict, quiet);
                 }                  }
             }              }
         }          }
Line 1091  check_aliases(int strict, int quiet) Line 1172  check_aliases(int strict, int quiet)
         tq_foreach_fwd(&us->users, m) {          tq_foreach_fwd(&us->users, m) {
             if (m->type == ALIAS) {              if (m->type == ALIAS) {
                 alias_seqno++;                  alias_seqno++;
                if (!alias_remove_recursive(m->name, USERALIAS, strict, quiet))                if (!alias_remove_recursive(m->name, USERALIAS))
                    error++;                    errors++;
             }              }
         }          }
         tq_foreach_fwd(&us->privileges, priv) {          tq_foreach_fwd(&us->privileges, priv) {
             tq_foreach_fwd(&priv->hostlist, m) {              tq_foreach_fwd(&priv->hostlist, m) {
                 if (m->type == ALIAS) {                  if (m->type == ALIAS) {
                     alias_seqno++;                      alias_seqno++;
                    if (!alias_remove_recursive(m->name, HOSTALIAS, strict,                    if (!alias_remove_recursive(m->name, HOSTALIAS))
                        quiet))                        errors++;
                        error++; 
                 }                  }
             }              }
             tq_foreach_fwd(&priv->cmndlist, cs) {              tq_foreach_fwd(&priv->cmndlist, cs) {
                 tq_foreach_fwd(&cs->runasuserlist, m) {                  tq_foreach_fwd(&cs->runasuserlist, m) {
                     if (m->type == ALIAS) {                      if (m->type == ALIAS) {
                         alias_seqno++;                          alias_seqno++;
                        if (!alias_remove_recursive(m->name, RUNASALIAS,                        if (!alias_remove_recursive(m->name, RUNASALIAS))
                            strict, quiet))                            errors++;
                            error++; 
                     }                      }
                 }                  }
                 if ((m = cs->cmnd)->type == ALIAS) {                  if ((m = cs->cmnd)->type == ALIAS) {
                     alias_seqno++;                      alias_seqno++;
                    if (!alias_remove_recursive(m->name, CMNDALIAS, strict,                    if (!alias_remove_recursive(m->name, CMNDALIAS))
                        quiet))                        errors++;
                        error++; 
                 }                  }
             }              }
         }          }
Line 1143  check_aliases(int strict, int quiet) Line 1221  check_aliases(int strict, int quiet)
             for (m = binding; m != NULL; m = m->next) {              for (m = binding; m != NULL; m = m->next) {
                 if (m->type == ALIAS) {                  if (m->type == ALIAS) {
                     alias_seqno++;                      alias_seqno++;
                    if (!alias_remove_recursive(m->name, atype, strict, quiet))                    if (!alias_remove_recursive(m->name, atype))
                        error++;                        errors++;
                 }                  }
             }              }
         }          }
Line 1155  check_aliases(int strict, int quiet) Line 1233  check_aliases(int strict, int quiet)
     if (!no_aliases() && !quiet)      if (!no_aliases() && !quiet)
         alias_apply(print_unused, strict ? "Error" : "Warning");          alias_apply(print_unused, strict ? "Error" : "Warning");
   
    return strict ? error : 0;    debug_return_int(strict ? errors : 0);
 }  }
   
 static int  static int
Line 1164  print_unused(void *v1, void *v2) Line 1242  print_unused(void *v1, void *v2)
     struct alias *a = (struct alias *)v1;      struct alias *a = (struct alias *)v1;
     char *prefix = (char *)v2;      char *prefix = (char *)v2;
   
    warningx(_("%s: unused %s_Alias %s"), prefix,    warningx2(_("%s: unused %s_Alias %s"), prefix,
         a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" :          a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" :
         a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" :          a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" :
         "Unknown", a->name);          "Unknown", a->name);
Line 1201  quit(int signo) Line 1279  quit(int signo)
 #define emsg     " exiting due to signal: "  #define emsg     " exiting due to signal: "
     myname = getprogname();      myname = getprogname();
     signame = strsignal(signo);      signame = strsignal(signo);
    if (write(STDERR_FILENO, myname, strlen(myname)) == -1 ||    ignore_result(write(STDERR_FILENO, myname, strlen(myname)));
        write(STDERR_FILENO, emsg, sizeof(emsg) - 1) == -1 ||    ignore_result(write(STDERR_FILENO, emsg, sizeof(emsg) - 1));
        write(STDERR_FILENO, signame, strlen(signame)) == -1 ||    ignore_result(write(STDERR_FILENO, signame, strlen(signame)));
        write(STDERR_FILENO, "\n", 1) == -1)    ignore_result(write(STDERR_FILENO, "\n", 1));
        /* shut up glibc */; 
     _exit(signo);      _exit(signo);
 }  }
   

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


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