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.
This commit is contained in:
Todd C. Miller
2010-07-09 10:08:05 -04:00
parent 432d27573d
commit ea4298bb54
8 changed files with 61 additions and 41 deletions

View File

@@ -32,7 +32,7 @@ compat/isblank.c
compat/memrchr.c compat/memrchr.c
compat/mksiglist.c compat/mksiglist.c
compat/mksiglist.h compat/mksiglist.h
compat/mkstemp.c compat/mkstemps.c
compat/nanosleep.c compat/nanosleep.c
compat/setenv.c compat/setenv.c
compat/siglist.in compat/siglist.in

View File

@@ -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 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 isblank.lo: $(compat)/isblank.c $(incdir)/compat.h $(top_builddir)/config.h
memrchr.lo: $(compat)/memrchr.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 nanosleep.lo: $(compat)/nanosleep.c $(incdir)/compat.h $(top_builddir)/config.h
sigaction.lo: $(compat)/sigaction.c $(incdir)/compat.h $(incdir)/compat.h sigaction.lo: $(compat)/sigaction.c $(incdir)/compat.h $(incdir)/compat.h
snprintf.lo: $(compat)/snprintf.c $(incdir)/compat.h $(top_builddir)/config.h snprintf.lo: $(compat)/snprintf.c $(incdir)/compat.h $(top_builddir)/config.h

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2003, 2008, 2010 * Copyright (c) 2001, 2003, 2004, 2008-2010
* 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
@@ -21,6 +21,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
# include <stdlib.h> # include <stdlib.h>
@@ -35,36 +36,49 @@
static unsigned int get_random(void); static unsigned int get_random(void);
static void seed_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 int
mkstemp(char *path) mkstemps(char *path, int slen)
{ {
char *start, *cp; char *start, *cp, *ep;
int fd, r; const char *tempchars = TEMPCHARS;
char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; unsigned int r, tries;
int fd;
if (*path == '\0') { for (ep = path; *ep; ep++)
errno = EINVAL;
return(0);
}
for (cp = path; *cp; cp++)
; ;
do { if (path + slen >= ep) {
cp--; errno = EINVAL;
} while (cp >= path && *cp == 'X'); return(-1);
start = cp + 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++) { for (cp = start; *cp; cp++) {
r = get_random % (26 + 26); r = get_random() % NUM_CHARS;
*cp = alphabet[r]; *cp = tempchars[r];
} }
fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
if (fd != -1 || errno != EEXIST) if (fd != -1 || errno != EEXIST)
return(fd); return(fd);
} } while (--tries);
/*NOTREACHED*/
errno = EEXIST;
return(-1);
} }
#ifdef HAVE_RANDOM #ifdef HAVE_RANDOM
@@ -87,13 +101,13 @@ static void
seed_random(void) seed_random(void)
{ {
SEED_T seed; SEED_T seed;
struct timespec ts; struct timeval tv;
/* /*
* Seed from time of day and process id multiplied by small primes. * Seed from time of day and process id multiplied by small primes.
*/ */
(void) gettime(&ts); (void) gettime(&tv);
seed = (ts.tv_sec % 10000) * 523 + ts.tv_nsec / 1000 * 13 + seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 +
(getpid() % 1000) * 983; (getpid() % 1000) * 983;
SRAND(seed); SRAND(seed);
} }

View File

@@ -337,8 +337,8 @@
/* Define to 1 if you have the `memset' function. */ /* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET #undef HAVE_MEMSET
/* Define to 1 if you have the `mkstemp' function. */ /* Define to 1 if you have the `mkstemps' function. */
#undef HAVE_MKSTEMP #undef HAVE_MKSTEMPS
/* Define to 1 if you have the <mps/ldap_ssl.h> header file. */ /* Define to 1 if you have the <mps/ldap_ssl.h> header file. */
#undef HAVE_MPS_LDAP_SSL_H #undef HAVE_MPS_LDAP_SSL_H

12
configure vendored
View File

@@ -15459,12 +15459,12 @@ fi
fi fi
done done
for ac_func in mkstemp for ac_func in mkstemps
do : do :
ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" ac_fn_c_check_func "$LINENO" "mkstemps" "ac_cv_func_mkstemps"
if test "x$ac_cv_func_mkstemp" = x""yes; then : if test "x$ac_cv_func_mkstemps" = x""yes; then :
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
#define HAVE_MKSTEMP 1 #define HAVE_MKSTEMPS 1
_ACEOF _ACEOF
else else
@@ -15483,8 +15483,8 @@ fi
done done
case " $LIBOBJS " in case " $LIBOBJS " in
*" mkstemp.$ac_objext "* ) ;; *" mkstemps.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" *) LIBOBJS="$LIBOBJS mkstemps.$ac_objext"
;; ;;
esac esac

View File

@@ -1979,9 +1979,9 @@ AC_CHECK_FUNCS(closefrom, [], [AC_LIBOBJ(closefrom)
[ #include <limits.h> [ #include <limits.h>
#include <fcntl.h> ]) #include <fcntl.h> ])
]) ])
AC_CHECK_FUNCS(mkstemp, [], [ AC_CHECK_FUNCS(mkstemps, [], [
AC_CHECK_FUNCS(random lrand48, [break]) AC_CHECK_FUNCS(random lrand48, [break])
AC_LIBOBJ(mkstemp) AC_LIBOBJ(mkstemps)
]) ])
AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf, , [NEED_SNPRINTF=1]) AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf, , [NEED_SNPRINTF=1])
if test X"$ac_cv_type_struct_timespec" != X"no"; then if test X"$ac_cv_type_struct_timespec" != X"no"; then

View File

@@ -63,8 +63,8 @@ size_t strlcpy(char *, const char *, size_t);
#ifndef HAVE_MEMRCHR #ifndef HAVE_MEMRCHR
void *memrchr(const void *, int, size_t); void *memrchr(const void *, int, size_t);
#endif #endif
#ifndef HAVE_MKSTEMP #ifndef HAVE_MKSTEMPS
int mkstemp(char *); int mkstemps(char *);
#endif #endif
#ifndef HAVE_NANOSLEEP #ifndef HAVE_NANOSLEEP
int nanosleep(const struct timespec *, struct timespec *); int nanosleep(const struct timespec *, struct timespec *);

View File

@@ -87,7 +87,7 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
struct command_details editor_details; struct command_details editor_details;
ssize_t nread, nwritten; ssize_t nread, nwritten;
const char *tmpdir; const char *tmpdir;
char *cp, **nargv, **ap, **files = NULL; char *cp, *suff, **nargv, **ap, **files = NULL;
char buf[BUFSIZ]; char buf[BUFSIZ];
int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen; int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen;
int editor_argc = 0, nfiles = 0; int editor_argc = 0, nfiles = 0;
@@ -178,14 +178,20 @@ sudo_edit(struct command_details *command_details, char *argv[], char *envp[])
cp++; cp++;
else else
cp = tf[j].ofile; 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) if (seteuid(user_details.uid) != 0)
error(1, "seteuid(%d)", (int)user_details.uid); 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) if (seteuid(ROOT_UID) != 0)
error(1, "seteuid(ROOT_UID)"); error(1, "seteuid(ROOT_UID)");
if (tfd == -1) { if (tfd == -1) {
warning("mkstemp"); warning("mkstemps");
goto cleanup; goto cleanup;
} }
if (ofd != -1) { if (ofd != -1) {