[BACK]Return to sudo_edit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Diff for /src/usr.bin/sudo/Attic/sudo_edit.c between version 1.3 and 1.4

version 1.3, 2004/11/29 17:29:05 version 1.4, 2007/07/26 16:10:16
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>   * Copyright (c) 2004-2005 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 14 
Line 14 
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */   */
   
 #include "config.h"  #include <config.h>
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  #include <sys/param.h>
Line 48 
Line 48 
 #endif /* HAVE_ERR_H */  #endif /* HAVE_ERR_H */
 #include <ctype.h>  #include <ctype.h>
 #include <pwd.h>  #include <pwd.h>
   #include <grp.h>
 #include <signal.h>  #include <signal.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <time.h>  #if TIME_WITH_SYS_TIME
   # include <time.h>
   #endif
   #ifndef HAVE_TIMESPEC
   # include <emul/timespec.h>
   #endif
   
 #include "sudo.h"  #include "sudo.h"
   
 #ifndef lint  #ifndef lint
 static const char rcsid[] = "$Sudo: sudo_edit.c,v 1.16 2004/09/15 16:16:20 millert Exp $";  __unused static const char rcsid[] = "$Sudo: sudo_edit.c,v 1.6.2.7 2007/07/08 18:44:41 millert Exp $";
 #endif /* lint */  #endif /* lint */
   
 extern sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;  extern sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;
   extern char **environ;
   
 /*  /*
  * Wrapper to allow users to edit privileged files with their own uid.   * Wrapper to allow users to edit privileged files with their own uid.
  */   */
 int sudo_edit(argc, argv)  int sudo_edit(argc, argv, envp)
     int argc;      int argc;
     char **argv;      char **argv;
       char **envp;
 {  {
     ssize_t nread, nwritten;      ssize_t nread, nwritten;
     pid_t kidpid, pid;      pid_t kidpid, pid;
     const char *tmpdir;      const char *tmpdir;
     char **nargv, **ap, *editor, *cp;      char **nargv, **ap, *editor, *cp;
     char buf[BUFSIZ];      char buf[BUFSIZ];
     int i, ac, ofd, tfd, nargc, rval, tmplen;      int error, i, ac, ofd, tfd, nargc, rval, tmplen, wasblank;
     sigaction_t sa;      sigaction_t sa;
     struct stat sb;      struct stat sb;
     struct timespec ts1, ts2;      struct timespec ts1, ts2;
Line 102 
Line 110 
     /*      /*
      * For each file specified by the user, make a temporary version       * For each file specified by the user, make a temporary version
      * and copy the contents of the original to it.       * and copy the contents of the original to it.
      * XXX - It would be nice to lock the original files but that means  
      *       keeping an extra fd open for each file.  
      */       */
     tf = emalloc2(argc - 1, sizeof(*tf));      tf = emalloc2(argc - 1, sizeof(*tf));
     memset(tf, 0, (argc - 1) * sizeof(*tf));      memset(tf, 0, (argc - 1) * sizeof(*tf));
     for (i = 0, ap = argv + 1; i < argc - 1 && *ap != NULL; i++, ap++) {      for (i = 0, ap = argv + 1; i < argc - 1 && *ap != NULL; i++, ap++) {
           error = -1;
         set_perms(PERM_RUNAS);          set_perms(PERM_RUNAS);
         ofd = open(*ap, O_RDONLY, 0644);  
         if (ofd != -1) {          /*
            * We close the password file before we try to open the user-specified
            * path to prevent the opening of things like /dev/fd/4.
            */
           endpwent();
           if ((ofd = open(*ap, O_RDONLY, 0644)) != -1 || errno == ENOENT) {
               if (ofd == -1) {
                   memset(&sb, 0, sizeof(sb));             /* new file */
                   error = 0;
               } else {
 #ifdef HAVE_FSTAT  #ifdef HAVE_FSTAT
             if (fstat(ofd, &sb) != 0) {                  error = fstat(ofd, &sb);
 #else  #else
             if (stat(tf[i].ofile, &sb) != 0) {                  error = stat(tf[i].ofile, &sb);
 #endif  #endif
                 close(ofd);     /* XXX - could reset errno */  
                 ofd = -1;  
             }              }
         }          }
         set_perms(PERM_ROOT);          set_perms(PERM_ROOT);
         if (ofd == -1) {          if (error || !S_ISREG(sb.st_mode)) {
             if (errno != ENOENT) {              if (error)
                 warn("%s", *ap);                  warn("%s", *ap);
                 argc--;              else
                 i--;                  warnx("%s: not a regular file", *ap);
                 continue;              if (ofd != -1)
             }                  close(ofd);
             memset(&sb, 0, sizeof(sb));  
         } else if (!S_ISREG(sb.st_mode)) {  
             warnx("%s: not a regular file", *ap);  
             close(ofd);  
             argc--;              argc--;
             i--;              i--;
             continue;              continue;
Line 189 
Line 199 
      * based on def_env_editor or def_editor since the editor runs with       * based on def_env_editor or def_editor since the editor runs with
      * the uid of the invoking user, not the runas (privileged) user.       * the uid of the invoking user, not the runas (privileged) user.
      */       */
       environ = envp;
     if (((editor = getenv("VISUAL")) != NULL && *editor != '\0') ||      if (((editor = getenv("VISUAL")) != NULL && *editor != '\0') ||
         ((editor = getenv("EDITOR")) != NULL && *editor != '\0')) {          ((editor = getenv("EDITOR")) != NULL && *editor != '\0')) {
         editor = estrdup(editor);          editor = estrdup(editor);
Line 204 
Line 215 
      * line args so look for those and alloc space for them too.       * line args so look for those and alloc space for them too.
      */       */
     nargc = argc;      nargc = argc;
     for (cp = editor + 1; *cp != '\0'; cp++) {      for (wasblank = FALSE, cp = editor; *cp != '\0'; cp++) {
         if (isblank((unsigned char)cp[0]) && !isblank((unsigned char)cp[-1]))          if (isblank((unsigned char) *cp))
               wasblank = TRUE;
           else if (wasblank) {
               wasblank = FALSE;
             nargc++;              nargc++;
           }
     }      }
     nargv = (char **) emalloc2(nargc + 1, sizeof(char *));      nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
     ac = 0;      ac = 0;
Line 238 
Line 253 
         (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);          (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
         (void) sigaction(SIGCHLD, &saved_sa_chld, NULL);          (void) sigaction(SIGCHLD, &saved_sa_chld, NULL);
         set_perms(PERM_FULL_USER);          set_perms(PERM_FULL_USER);
           endpwent();
           endgrent();
           closefrom(STDERR_FILENO + 1);
         execvp(nargv[0], nargv);          execvp(nargv[0], nargv);
         warn("unable to execute %s", nargv[0]);          warn("unable to execute %s", nargv[0]);
         _exit(127);          _exit(127);
Line 246 
Line 264 
     /*      /*
      * Wait for status from the child.  Most modern kernels       * Wait for status from the child.  Most modern kernels
      * will not let an unprivileged child process send a       * will not let an unprivileged child process send a
      * signal to its privileged parent to we have to request       * signal to its privileged parent so we have to request
      * status when the child is stopped and then send the       * status when the child is stopped and then send the
      * same signal to our own pid.       * same signal to our own pid.
      */       */
Line 271 
Line 289 
   
     /* Copy contents of temp files to real ones */      /* Copy contents of temp files to real ones */
     for (i = 0; i < argc - 1; i++) {      for (i = 0; i < argc - 1; i++) {
           error = -1;
         set_perms(PERM_USER);          set_perms(PERM_USER);
         tfd = open(tf[i].tfile, O_RDONLY, 0644);          if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) {
   #ifdef HAVE_FSTAT
               error = fstat(tfd, &sb);
   #else
               error = stat(tf[i].tfile, &sb);
   #endif
           }
         set_perms(PERM_ROOT);          set_perms(PERM_ROOT);
         if (tfd < 0) {          if (error || !S_ISREG(sb.st_mode)) {
             warn("unable to read %s", tf[i].tfile);              if (error)
                   warn("%s", tf[i].tfile);
               else
                   warnx("%s: not a regular file", tf[i].tfile);
             warnx("%s left unmodified", tf[i].ofile);              warnx("%s left unmodified", tf[i].ofile);
               if (tfd != -1)
                   close(tfd);
             continue;              continue;
         }          }
 #ifdef HAVE_FSTAT          if (tf[i].osize == sb.st_size && tf[i].omtim.tv_sec == mtim_getsec(sb)
         if (fstat(tfd, &sb) == 0) {              && tf[i].omtim.tv_nsec == mtim_getnsec(sb)) {
             if (!S_ISREG(sb.st_mode)) {              /*
                 warnx("%s: not a regular file", tf[i].tfile);               * If mtime and size match but the user spent no measurable
                 warnx("%s left unmodified", tf[i].ofile);               * time in the editor we can't tell if the file was changed.
                 continue;               */
             }  
             if (tf[i].osize == sb.st_size &&  
                 tf[i].omtim.tv_sec == mtim_getsec(sb) &&  
                 tf[i].omtim.tv_nsec == mtim_getnsec(sb)) {  
                 /*  
                  * If mtime and size match but the user spent no measurable  
                  * time in the editor we can't tell if the file was changed.  
                  */  
 #ifdef HAVE_TIMESPECSUB2  #ifdef HAVE_TIMESPECSUB2
                 timespecsub(&ts1, &ts2);              timespecsub(&ts1, &ts2);
 #else  #else
                 timespecsub(&ts1, &ts2, &ts2);              timespecsub(&ts1, &ts2, &ts2);
 #endif  #endif
                 if (timespecisset(&ts2)) {              if (timespecisset(&ts2)) {
                     warnx("%s unchanged", tf[i].ofile);                  warnx("%s unchanged", tf[i].ofile);
                     unlink(tf[i].tfile);                  unlink(tf[i].tfile);
                     close(tfd);                  close(tfd);
                     continue;                  continue;
                 }  
             }              }
         }          }
 #endif  
         set_perms(PERM_RUNAS);          set_perms(PERM_RUNAS);
         ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644);          ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644);
         set_perms(PERM_ROOT);          set_perms(PERM_ROOT);

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4