summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>1998-02-13 02:13:24 +0000
committerimp <imp@FreeBSD.org>1998-02-13 02:13:24 +0000
commit9461b07207276f197a45e7ed0bc94bda8106f779 (patch)
treebf29f53d22853e188a325419db4e6bdeecab1744 /lib
parentb31dde27bfeaed94b1026c0788c4e98b1af47f3c (diff)
downloadFreeBSD-src-9461b07207276f197a45e7ed0bc94bda8106f779.zip
FreeBSD-src-9461b07207276f197a45e7ed0bc94bda8106f779.tar.gz
Many security improvements from OpenBSD:
implement mkdtemp improve man page for mk*temp use arc4random to seed extra XXX's randomly Optionally warn of unsafe mktemp uses From various commits by theo de raadt and Todd Miller. Obtained from: OpenBSD This should go into 2.2 after a testing period.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdio/Makefile.inc3
-rw-r--r--lib/libc/stdio/mktemp.352
-rw-r--r--lib/libc/stdio/mktemp.c93
3 files changed, 113 insertions, 35 deletions
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index 97b403a..031e397 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 28a662d..50d7de4 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 19125e6..5619522 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 */
OpenPOWER on IntegriCloud