]> granicus.if.org Git - sudo/commitdiff
Change how we handle the sudoedit argv. We now require that there
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 13 May 2010 21:11:31 +0000 (17:11 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 13 May 2010 21:11:31 +0000 (17:11 -0400)
be a "--" in argv to separate the editor and any command line arguments
from the files to be edited.

plugins/sudoers/sudoers.c
src/sudo.c
src/sudo.h
src/sudo_edit.c

index 36106c235ae2b3c56e28fb34531e311394c42873..1746a41ebe4392b4cf635f55f7534abbc0b4391e 100644 (file)
@@ -122,7 +122,7 @@ static void set_runaspw(char *);
 static int sudoers_policy_version(int verbose);
 static struct passwd *get_authpw(void);
 static int deserialize_info(char * const settings[], char * const user_info[]);
-static char *find_editor(char ***argv_out);
+static char *find_editor(int nfiles, char **files, char ***argv_out);
 
 /* XXX */
 extern int runas_ngroups;
@@ -561,7 +561,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
     sudo_endgrent();
 
     if (ISSET(sudo_mode, MODE_EDIT)) {
-       char *editor = find_editor(&edit_argv);
+       char *editor = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv);
        if (!editor)
            goto done;
        command_info[info_len++] = fmt_string("command", editor);
@@ -1324,10 +1324,10 @@ deserialize_info(char * const settings[], char * const user_info[])
 }
 
 static char *
-resolve_editor(char *editor, char ***argv_out)
+resolve_editor(char *editor, int nfiles, char **files, char ***argv_out)
 {
     char *cp, **nargv, *editor_path = NULL;
-    int ac, nargc, wasblank;
+    int ac, i, nargc, wasblank;
 
     /*
      * Split editor into an argument vector; editor is reused (do not free).
@@ -1349,11 +1349,14 @@ resolve_editor(char *editor, char ***argv_out)
        find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) {
        return NULL;
     }
-    nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
+    nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *));
     for (ac = 0; cp != NULL && ac < nargc; ac++) {
        nargv[ac] = cp;
        cp = strtok(NULL, " \t");
     }
+    nargv[ac++] = "--";
+    for (i = 0; i < nfiles; )
+       nargv[ac++] = files[i++];
     nargv[ac] = NULL;
 
     *argv_out = nargv;
@@ -1366,7 +1369,7 @@ resolve_editor(char *editor, char ***argv_out)
  * not the runas (privileged) user.
  */
 static char *
-find_editor(char ***argv_out)
+find_editor(int nfiles, char **files, char ***argv_out)
 {
     char *cp, *editor, *editor_path = NULL, **ev, *ev0[4];
 
@@ -1379,7 +1382,7 @@ find_editor(char ***argv_out)
     ev0[3] = NULL;
     for (ev = ev0; *ev != NULL; ev++) {
        if ((editor = getenv(*ev)) != NULL && *editor != '\0') {
-           editor_path = resolve_editor(editor, argv_out);
+           editor_path = resolve_editor(editor, nfiles, files, argv_out);
            if (editor_path != NULL)
                break;
        }
@@ -1388,7 +1391,7 @@ find_editor(char ***argv_out)
        editor = estrdup(def_editor);
        if ((cp = strchr(editor, ':')) != NULL)
            *cp = '\0';                 /* def_editor could be a path */
-       editor_path = resolve_editor(cp, argv_out);
+       editor_path = resolve_editor(cp, nfiles, files, argv_out);
     }
     if (!editor_path) {
        audit_failure(NewArgv, "%s: command not found", editor);
index d7621f1ef682cd5e7cf997a97df461a52c62c1e9..95222fbcaf44c0c5bf7c7ed36bbc51214acf29d8 100644 (file)
@@ -246,7 +246,7 @@ main(int argc, char *argv[], char *envp[])
 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
            /* run_command will call the close method for us */
            if (sudo_mode & MODE_EDIT) {
-               exitcode = sudo_edit(&command_details, argv_out, nargv + 1, user_env_out);
+               exitcode = sudo_edit(&command_details, argv_out, user_env_out);
            } else {
                exitcode = run_command(&command_details, argv_out, user_env_out);
            }
index fd913299bff84058ba520f56b929b2b1ec6cc3a2..d7e345ae106a925d16245cc220850146529f879f 100644 (file)
@@ -192,8 +192,7 @@ extern int debug_level;
 extern struct plugin_container_list io_plugins;
 
 /* sudo_edit.c */
-int sudo_edit(struct command_details *details, char *argv[], char *files[],
-    char *envp[]);
+int sudo_edit(struct command_details *details, char *argv[], char *envp[]);
 
 /* parse_args.c */
 void usage(int) __attribute__((__noreturn__));
index 0b7d3ee80a668449ce46b74e871639e9ff541c78..20b7fbd8f3ffc4da9752f7cd65e2e69ea323f0ce 100644 (file)
@@ -83,15 +83,15 @@ switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
  * Wrapper to allow users to edit privileged files with their own uid.
  */
 int
-sudo_edit(struct command_details *command_details, char *argv[], char *files[],
-    char *envp[])
+sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
 {
     struct command_details editor_details;
     ssize_t nread, nwritten;
     const char *tmpdir;
-    char **nargv, **ap, *cp;
+    char *cp, **nargv, **ap, **files = NULL;
     char buf[BUFSIZ];
-    int retval, i, j, ac, ofd, tfd, nargc, nfiles, rval, tmplen;
+    int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen;
+    int editor_argc = 0, nfiles = 0;
     struct stat sb;
     struct timeval tv, tv1, tv2;
     struct tempfile {
@@ -129,34 +129,47 @@ sudo_edit(struct command_details *command_details, char *argv[], char *files[],
     endpwent();
     endgrent();
 
+    /*
+     * The user's editor must be separated from the files to be
+     * edited by a "--" option.
+     */
+    for (ap = argv; *ap != NULL; ap++) {
+       if (files)
+           nfiles++;
+       else if (strcmp(*ap, "--") == 0)
+           files = ap + 1;
+       else
+           editor_argc++;
+    }
+    if (nfiles == 0)
+       return 1;
+
     /*
      * For each file specified by the user, make a temporary version
      * and copy the contents of the original to it.
      */
-    for (nfiles = 0; files[nfiles] != NULL; nfiles++)
-       continue;
     tf = emalloc2(nfiles, sizeof(*tf));
     zero_bytes(tf, nfiles * sizeof(*tf));
     for (i = 0, j = 0; i < nfiles; i++) {
-       retval = -1;
+       rc = -1;
        switch_user(command_details->euid, command_details->egid,
            command_details->ngroups, command_details->groups);
        if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) {
            if (ofd == -1) {
                zero_bytes(&sb, sizeof(sb));            /* new file */
-               retval = 0;
+               rc = 0;
            } else {
 #ifdef HAVE_FSTAT
-               retval = fstat(ofd, &sb);
+               rc = fstat(ofd, &sb);
 #else
-               retval = stat(tf[j].ofile, &sb);
+               rc = stat(tf[j].ofile, &sb);
 #endif
            }
        }
        switch_user(ROOT_UID, user_details.egid,
            user_details.ngroups, user_details.groups);
-       if (retval || (ofd != -1 && !S_ISREG(sb.st_mode))) {
-           if (retval)
+       if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) {
+           if (rc)
                warning("%s", files[i]);
            else
                warningx("%s: not a regular file", files[i]);
@@ -202,30 +215,27 @@ sudo_edit(struct command_details *command_details, char *argv[], char *files[],
         */
        (void) touch(tfd, NULL, &tf[j].omtim);
 #ifdef HAVE_FSTAT
-       retval = fstat(tfd, &sb);
+       rc = fstat(tfd, &sb);
 #else
-       retval = stat(tf[j].tfile, &sb);
+       rc = stat(tf[j].tfile, &sb);
 #endif
-       if (!retval)
+       if (!rc)
            mtim_get(&sb, &tf[j].omtim);
        close(tfd);
        j++;
     }
-    if (nfiles == 0)
+    if ((nfiles = j) == 0)
        return(1);                      /* no files readable, you lose */
 
     /*
      * Allocate space for the new argument vector and fill it in.
-     * We concatenate argv (the editor with its args) and the file list
+     * We concatenate the editor with its args and the file list
      * to create a new argv.
      */
-    for (ap = argv; *ap != NULL; ap++)
-       continue;
-    nargc = (int)(ap - argv) + nfiles;
+    nargc = editor_argc + nfiles;
     nargv = (char **) emalloc2(nargc + 1, sizeof(char *));
-    ac = 0;
-    for (ap = argv; *ap != NULL; ap++)
-       nargv[ac++] = *ap;
+    for (ac = 0; ac < editor_argc; ac++)
+       nargv[ac] = argv[ac];
     for (i = 0; i < nfiles && ac < nargc; )
        nargv[ac++] = tf[i++].tfile;
     nargv[ac] = NULL;
@@ -247,20 +257,20 @@ sudo_edit(struct command_details *command_details, char *argv[], char *files[],
 
     /* Copy contents of temp files to real ones */
     for (i = 0; i < nfiles; i++) {
-       retval = -1;
+       rc = -1;
        if (seteuid(user_details.uid) != 0)
            error(1, "seteuid(%d)", (int)user_details.uid);
        if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) {
 #ifdef HAVE_FSTAT
-           retval = fstat(tfd, &sb);
+           rc = fstat(tfd, &sb);
 #else
-           retval = stat(tf[i].tfile, &sb);
+           rc = stat(tf[i].tfile, &sb);
 #endif
        }
        if (seteuid(ROOT_UID) != 0)
            error(1, "seteuid(ROOT_UID)");
-       if (retval || !S_ISREG(sb.st_mode)) {
-           if (retval)
+       if (rc || !S_ISREG(sb.st_mode)) {
+           if (rc)
                warning("%s", tf[i].tfile);
            else
                warningx("%s: not a regular file", tf[i].tfile);