diff options
| author | Warner Losh <imp@FreeBSD.org> | 1998-02-13 02:13:24 +0000 | 
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 1998-02-13 02:13:24 +0000 | 
| commit | 2f253e75c830341a4fe130a3c7aa042fb0ab9a59 (patch) | |
| tree | 9cdbbd52f02c122e602ff715b6f5ed2e22563534 | |
| parent | f5295b34ac101129c1aec1a491a701435e5ec948 (diff) | |
Notes
| -rw-r--r-- | lib/libc/stdio/Makefile.inc | 3 | ||||
| -rw-r--r-- | lib/libc/stdio/mktemp.3 | 52 | ||||
| -rw-r--r-- | lib/libc/stdio/mktemp.c | 93 | 
3 files changed, 113 insertions, 35 deletions
| diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc index 97b403a25071..031e397a920f 100644 --- a/lib/libc/stdio/Makefile.inc +++ b/lib/libc/stdio/Makefile.inc @@ -1,5 +1,5 @@  #	@(#)Makefile.inc	8.3 (Berkeley) 4/17/94 -#	$Id: Makefile.inc,v 1.10 1997/10/15 16:16:07 bde Exp $ +#	$Id: Makefile.inc,v 1.11 1997/10/21 08:41:10 bde Exp $  # stdio sources  .PATH: ${.CURDIR}/../libc/stdio @@ -30,6 +30,7 @@ MLINKS+=fseek.3 fgetpos.3 fseek.3 fsetpos.3 fseek.3 ftell.3 fseek.3 rewind.3  MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3  MLINKS+=getc.3 fgetc.3 getc.3 getchar.3 getc.3 getw.3  MLINKS+=mktemp.3 mkstemp.3 +MLINKS+=mktemp.3 mkdtemp.3  MLINKS+=printf.3 asprintf.3 printf.3 fprintf.3 \  	printf.3 snprintf.3 printf.3 sprintf.3 \  	printf.3 vasprintf.3 \ diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3 index 28a662d11beb..50d7de4cda3f 100644 --- a/lib/libc/stdio/mktemp.3 +++ b/lib/libc/stdio/mktemp.3 @@ -31,7 +31,7 @@  .\"  .\"     @(#)mktemp.3	8.1 (Berkeley) 6/4/93  .\" -.Dd June 4, 1993 +.Dd February 11, 1998  .Dt MKTEMP 3  .Os  .Sh NAME @@ -43,6 +43,8 @@  .Fn mktemp "char *template"  .Ft int  .Fn mkstemp "char *template" +.Ft char * +.Fn mkdtemp "char *template"  .Sh DESCRIPTION  The  .Fn mktemp @@ -78,11 +80,18 @@ makes the same replacement to the template and creates the template file,  mode 0600, returning a file descriptor opened for reading and writing.  This avoids the race between testing for a file's existence and opening it  for use. +.Pp +The +.Fn mkdtemp +function makes the same replacement to the template as in +.Xr mktemp 3 +and creates the template directory, mode 0700.  .Sh RETURN VALUES  The  .Fn mktemp -function -returns a pointer to the template on success and +and +.Fn mkdtemp +functions return a pointer to the template on success and  .Dv NULL  on failure.  The @@ -93,9 +102,9 @@ If either call fails an error code is placed in the global variable  .Va errno .  .Sh ERRORS  The -.Fn mktemp -and  .Fn mkstemp +and +.Fn mkdtemp  functions  may set  .Va errno @@ -106,9 +115,9 @@ The pathname portion of the template is not an existing directory.  .El  .Pp  The -.Fn mktemp -and  .Fn mkstemp +and +.Fn mkdtemp  functions  may also set  .Va errno @@ -124,12 +133,22 @@ may also set  to any value specified by the  .Xr open 2  function. +.Pp +The +.Fn mkdtemp +function +may also set +.Va errno +to any value specified by the +.Xr mkdir 2 +function.  .Sh NOTES  A common problem that results in a core dump is that the programmer  passes in a read-only string to  -.Fn mktemp -or  -.Fn mkstemp . +.Fn mktemp , +.Fn mkstemp +or +.Fn mkdtemp .  This is common with programs that were developed before   .St -ansiC  compilers were common. @@ -146,13 +165,24 @@ so that it will store string constants in a writable segment of memory.  See  .Xr gcc 1  for more information. +.Sh BUGS +An attacker can guess the filenames produced by +.Fn mktemp . +Whenever it is possible +.Fn mkstemp +should be used instead.  .Sh SEE ALSO  .Xr chmod 2 ,  .Xr getpid 2 , +.Xr mkdir 2 ,  .Xr open 2 ,  .Xr stat 2  .Sh HISTORY  A -.Nm mktemp +.Fn mktemp  function appeared in  .At v7 . +The  +.Fn mkdtemp +function first appeared in +.Ox 2.2 . diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c index 19125e677ff9..561952291fb7 100644 --- a/lib/libc/stdio/mktemp.c +++ b/lib/libc/stdio/mktemp.c @@ -36,7 +36,7 @@  static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";  #endif  static const char rcsid[] = -		"$Id: mktemp.c,v 1.6 1997/02/22 15:02:16 peter Exp $"; +		"$Id: mktemp.c,v 1.7 1997/04/07 18:01:10 guido Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h> @@ -44,10 +44,11 @@ static const char rcsid[] =  #include <fcntl.h>  #include <errno.h>  #include <stdio.h> +#include <stdlib.h>  #include <ctype.h>  #include <unistd.h> -static int _gettemp(char *, int *); +static int _gettemp(char *, int *, int);  int  mkstemp(path) @@ -55,49 +56,91 @@ mkstemp(path)  {  	int fd; -	return (_gettemp(path, &fd) ? fd : -1); +	return (_gettemp(path, &fd, 0) ? fd : -1);  }  char * +mkdtemp(path) +	char *path; +{ +	return(_gettemp(path, (int *)NULL, 1) ? path : (char *)NULL); +} + +char *_mktemp(char *); + +char * +_mktemp(path) +	char *path; +{ +	return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL); +} + +#ifdef UNSAFE_WARN +__warn_references(mktemp, +    "warning: mktemp() possibly used unsafely; consider using mkstemp()"); +#endif + +char *  mktemp(path)  	char *path;  { -	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); +	return(_mktemp(path));  }  static int -_gettemp(path, doopen) +_gettemp(path, doopen, domkdir)  	char *path;  	register int *doopen; +	int domkdir;  {  	register char *start, *trv;  	struct stat sbuf; -	pid_t pid; +	int pid, rval; + +	if (doopen && domkdir) { +		errno = EINVAL; +		return(0); +	}  	pid = getpid(); -	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */ -	while (*--trv == 'X') { -		*trv = (pid % 10) + '0'; +	for (trv = path; *trv; ++trv) +		; +	--trv; +	while (*trv == 'X' && pid != 0) { +		*trv-- = (pid % 10) + '0';  		pid /= 10;  	} +	while (*trv == 'X') { +		char c; + +		pid = (arc4random() & 0xffff) % (26+26); +		if (pid < 26) +			c = pid + 'A'; +		else +			c = (pid - 26) + 'a'; +		*trv-- = c; +	}  	/*  	 * check the target directory; if you have six X's and it  	 * doesn't exist this runs for a *very* long time.  	 */ -	for (start = trv + 1;; --trv) { -		if (trv <= path) -			break; -		if (*trv == '/') { -			*trv = '\0'; -			if (stat(path, &sbuf)) -				return(0); -			if (!S_ISDIR(sbuf.st_mode)) { -				errno = ENOTDIR; -				return(0); +	if (doopen || domkdir) { +		for (start = trv + 1;; --trv) { +			if (trv <= path) +				break; +			if (*trv == '/') { +				*trv = '\0'; +				rval = stat(path, &sbuf); +				*trv = '/'; +				if (rval != 0) +					return(0); +				if (!S_ISDIR(sbuf.st_mode)) { +					errno = ENOTDIR; +					return(0); +				} +				break;  			} -			*trv = '/'; -			break;  		}  	} @@ -108,8 +151,12 @@ _gettemp(path, doopen)  				return(1);  			if (errno != EEXIST)  				return(0); -		} -		else if (lstat(path, &sbuf)) +		} else if (domkdir) { +			if (mkdir(path, 0700) == 0) +				return(1); +			if (errno != EEXIST) +				return(0); +		} else if (lstat(path, &sbuf))  			return(errno == ENOENT ? 1 : 0);  		/* tricky little algorithm for backward compatibility */ | 
