Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 15 Aug 2008 10:32:58 -0400
From: "Todd C. Miller" <Todd.Miller@...rtesan.com>
To: oss-security@...ts.openwall.com
Subject: Re: CVE id request: mktemp 

In message <20080815115550.GD31878@...lde.de>
	so spake Nico Golde (oss-security+ml):

> Hi,
> mktemp (not the coreutils one) from
> ftp://ftp.mktemp.org/pub/mktemp/ is not generating fully
> random names. Steve, can you assign a CVE id to this?
> 
> This is=20
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D495193
> I wrote an explanation on why this happens, available on:
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D495193#30

The private version of mktemp(3) used by mktemp(1) is based on the
BSD version which uses the pid as part of the file name.  If there
is a small number X's, only the pid will be used when constructing
the file name.

It's probably fine to just remove the pid from the equation entirely.
I'll look at putting out a new version of mktemp(1) in the next few
days with this fix and some other changes.

In the meantime, the following diff should suffice.

 - todd

Index: priv_mktemp.c
===================================================================
RCS file: /home/cvs/courtesan/mktemp/priv_mktemp.c,v
retrieving revision 1.8
diff -u -p -u -r1.8 priv_mktemp.c
--- priv_mktemp.c	26 Apr 2004 18:31:35 -0000	1.8
+++ priv_mktemp.c	15 Aug 2008 14:31:32 -0000
@@ -84,22 +84,23 @@ _gettemp(path, doopen, domkdir)
 		return(0);
 	}
 
-	pid = getpid();
+	if (*path == '\0') {
+		errno = EINVAL;
+		return(0);
+	}
+
 	for (trv = path; *trv; ++trv)
 		;
-	--trv;
-	while (trv >= path && *trv == 'X' && pid != 0) {
-		*trv-- = (pid % 10) + '0';
-		pid /= 10;
-	}
-	while (trv >= path && *trv == 'X') {
-		char c;
+	do {
+		--trv;
+	} while (trv >= path && *trv == 'X');
+	start = trv + 1;
 
+again:
+	for (trv = start; *trv; ++trv) {
 		pid = (get_random() & 0xffff) % (26+26);
-		c = alphabet[pid];
-		*trv-- = c;
+		*trv = alphabet[pid];
 	}
-	start = trv + 1;
 
 	/*
 	 * check the target directory; if you have six X's and it
@@ -124,58 +125,20 @@ _gettemp(path, doopen, domkdir)
 		}
 	}
 
-	for (;;) {
-		if (doopen) {
-			if ((*doopen =
-			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
-				return(1);
-			if (errno != EEXIST)
-				return(0);
-		} 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);
+	if (doopen) {
+		if ((*doopen =
+		    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+			return(1);
+		if (errno != EEXIST)
+			return(0);
+	} 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 */
-		for (trv = start;;) {
-			if (!*trv)
-				return (0);
-			if (*trv == 'Z')
-				*trv++ = 'a';
-			else {
-				if (isdigit((unsigned char)(*trv)))
-					*trv = 'a';
-				else if (*trv == 'z')	/* wrap from z to A */
-					*trv = 'A';
-				else {
-#ifdef HAVE_EBCDIC
-					switch(*trv) {
-					case 'i':
-						*trv = 'j';
-						break;
-					case 'r':
-						*trv = 's';
-						break;
-					case 'I':
-						*trv = 'J';
-						break;
-					case 'R':
-						*trv = 'S';
-						break;
-					default:
-						++*trv;
-						break;
-					}
-#else
-					++*trv;
-#endif
-				}
-				break;
-			}
-		}
-	}
+	goto again;
 	/*NOTREACHED*/
 }

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.