From ea4298bb543b8eed3d5ade53ba98ec4d7c40aed2 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 9 Jul 2010 10:08:05 -0400 Subject: [PATCH] Use mkstemps() instead of mkstemp() in sudoedit. This allows sudoedit to preserve the file extension (if any) which may be used by the editor (like emacs) to choose the editing mode. --- MANIFEST | 2 +- compat/Makefile.in | 2 +- compat/{mkstemp.c => mkstemps.c} | 60 ++++++++++++++++++++------------ config.h.in | 4 +-- configure | 12 +++---- configure.in | 4 +-- include/missing.h | 4 +-- src/sudo_edit.c | 14 +++++--- 8 files changed, 61 insertions(+), 41 deletions(-) rename compat/{mkstemp.c => mkstemps.c} (71%) diff --git a/MANIFEST b/MANIFEST index 631048349..264a4a02b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -32,7 +32,7 @@ compat/isblank.c compat/memrchr.c compat/mksiglist.c compat/mksiglist.h -compat/mkstemp.c +compat/mkstemps.c compat/nanosleep.c compat/setenv.c compat/siglist.in diff --git a/compat/Makefile.in b/compat/Makefile.in index e2907dc23..a1d3e6eb9 100644 --- a/compat/Makefile.in +++ b/compat/Makefile.in @@ -83,7 +83,7 @@ getprogname.lo: $(compat)/getprogname.c $(incdir)/compat.h $(top_builddir)/confi glob.lo: $(compat)/glob.c $(compat)/glob.h $(compat)/charclass.h $(incdir)/compat.h $(top_builddir)/config.h isblank.lo: $(compat)/isblank.c $(incdir)/compat.h $(top_builddir)/config.h memrchr.lo: $(compat)/memrchr.c $(incdir)/compat.h $(top_builddir)/config.h -mkstemp.lo: $(compat)/mkstemp.c $(incdir)/compat.h $(top_builddir)/config.h +mkstemps.lo: $(compat)/mkstemps.c $(incdir)/compat.h $(top_builddir)/config.h nanosleep.lo: $(compat)/nanosleep.c $(incdir)/compat.h $(top_builddir)/config.h sigaction.lo: $(compat)/sigaction.c $(incdir)/compat.h $(incdir)/compat.h snprintf.lo: $(compat)/snprintf.c $(incdir)/compat.h $(top_builddir)/config.h diff --git a/compat/mkstemp.c b/compat/mkstemps.c similarity index 71% rename from compat/mkstemp.c rename to compat/mkstemps.c index 03ac736d0..1a79453e4 100644 --- a/compat/mkstemp.c +++ b/compat/mkstemps.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2003, 2008, 2010 + * Copyright (c) 2001, 2003, 2004, 2008-2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -21,6 +21,7 @@ #include #include #include +#include #include #ifdef HAVE_STDLIB_H # include @@ -35,36 +36,49 @@ static unsigned int get_random(void); static void seed_random(void); +#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +#define NUM_CHARS (sizeof(TEMPCHARS) - 1) + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + int -mkstemp(char *path) +mkstemps(char *path, int slen) { - char *start, *cp; - int fd, r; - char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + char *start, *cp, *ep; + const char *tempchars = TEMPCHARS; + unsigned int r, tries; + int fd; - if (*path == '\0') { - errno = EINVAL; - return(0); - } - - for (cp = path; *cp; cp++) + for (ep = path; *ep; ep++) ; - do { - cp--; - } while (cp >= path && *cp == 'X'); - start = cp + 1; + if (path + slen >= ep) { + errno = EINVAL; + return(-1); + } + ep -= slen; - for (;;) { + tries = 1; + for (start = ep; start > path && start[-1] == 'X'; start--) { + if (tries < INT_MAX / NUM_CHARS) + tries *= NUM_CHARS; + } + tries *= 2; + + do { for (cp = start; *cp; cp++) { - r = get_random % (26 + 26); - *cp = alphabet[r]; + r = get_random() % NUM_CHARS; + *cp = tempchars[r]; } fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); if (fd != -1 || errno != EEXIST) return(fd); - } - /*NOTREACHED*/ + } while (--tries); + + errno = EEXIST; + return(-1); } #ifdef HAVE_RANDOM @@ -87,13 +101,13 @@ static void seed_random(void) { SEED_T seed; - struct timespec ts; + struct timeval tv; /* * Seed from time of day and process id multiplied by small primes. */ - (void) gettime(&ts); - seed = (ts.tv_sec % 10000) * 523 + ts.tv_nsec / 1000 * 13 + + (void) gettime(&tv); + seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 + (getpid() % 1000) * 983; SRAND(seed); } diff --git a/config.h.in b/config.h.in index be9ca3776..3e06e38a7 100644 --- a/config.h.in +++ b/config.h.in @@ -337,8 +337,8 @@ /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET -/* Define to 1 if you have the `mkstemp' function. */ -#undef HAVE_MKSTEMP +/* Define to 1 if you have the `mkstemps' function. */ +#undef HAVE_MKSTEMPS /* Define to 1 if you have the header file. */ #undef HAVE_MPS_LDAP_SSL_H diff --git a/configure b/configure index de1845f95..0c25c6613 100755 --- a/configure +++ b/configure @@ -15459,12 +15459,12 @@ fi fi done -for ac_func in mkstemp +for ac_func in mkstemps do : - ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" -if test "x$ac_cv_func_mkstemp" = x""yes; then : + ac_fn_c_check_func "$LINENO" "mkstemps" "ac_cv_func_mkstemps" +if test "x$ac_cv_func_mkstemps" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_MKSTEMP 1 +#define HAVE_MKSTEMPS 1 _ACEOF else @@ -15483,8 +15483,8 @@ fi done case " $LIBOBJS " in - *" mkstemp.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" + *" mkstemps.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mkstemps.$ac_objext" ;; esac diff --git a/configure.in b/configure.in index b818b7c8b..38301f387 100644 --- a/configure.in +++ b/configure.in @@ -1979,9 +1979,9 @@ AC_CHECK_FUNCS(closefrom, [], [AC_LIBOBJ(closefrom) [ #include #include ]) ]) -AC_CHECK_FUNCS(mkstemp, [], [ +AC_CHECK_FUNCS(mkstemps, [], [ AC_CHECK_FUNCS(random lrand48, [break]) - AC_LIBOBJ(mkstemp) + AC_LIBOBJ(mkstemps) ]) AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf, , [NEED_SNPRINTF=1]) if test X"$ac_cv_type_struct_timespec" != X"no"; then diff --git a/include/missing.h b/include/missing.h index ddd94957e..3753c7593 100644 --- a/include/missing.h +++ b/include/missing.h @@ -63,8 +63,8 @@ size_t strlcpy(char *, const char *, size_t); #ifndef HAVE_MEMRCHR void *memrchr(const void *, int, size_t); #endif -#ifndef HAVE_MKSTEMP -int mkstemp(char *); +#ifndef HAVE_MKSTEMPS +int mkstemps(char *); #endif #ifndef HAVE_NANOSLEEP int nanosleep(const struct timespec *, struct timespec *); diff --git a/src/sudo_edit.c b/src/sudo_edit.c index ed2f696db..26cde3247 100644 --- a/src/sudo_edit.c +++ b/src/sudo_edit.c @@ -87,7 +87,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[]) struct command_details editor_details; ssize_t nread, nwritten; const char *tmpdir; - char *cp, **nargv, **ap, **files = NULL; + char *cp, *suff, **nargv, **ap, **files = NULL; char buf[BUFSIZ]; int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen; int editor_argc = 0, nfiles = 0; @@ -178,14 +178,20 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[]) cp++; else cp = tf[j].ofile; - easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp); + suff = strrchr(cp, '.'); + if (suff != NULL) { + easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir, + (int)(size_t)(suff - cp), cp, suff); + } else { + easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp); + } if (seteuid(user_details.uid) != 0) error(1, "seteuid(%d)", (int)user_details.uid); - tfd = mkstemp(tf[j].tfile); + tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0); if (seteuid(ROOT_UID) != 0) error(1, "seteuid(ROOT_UID)"); if (tfd == -1) { - warning("mkstemp"); + warning("mkstemps"); goto cleanup; } if (ofd != -1) {