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) {