Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Jun 2000 18:11:04 -0700 (PDT)
From:      Kris Kennaway <kris@FreeBSD.org>
To:        current@freebsd.org
Subject:   mktemp() patch
Message-ID:  <Pine.BSF.4.21.0006071758550.11848-100000@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
This patch was developed by Peter Jeremy and myself and increases the
number of possible temporary filenames which can be generated by the
mktemp() family, by more densely encoding the PID and using a larger set
of characters to randomly pad with.

Instead of using only alphabetic characters, the patch uses the following
character set:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#%^-_=+:,.~

which is not believed to cause any problems with shells. The PID is also
base-64 encoded into 3 characters (instead of the usual 5 for a base-10
representation) with an extra bit of randomness added in to fill the
space. All up, for the usual case of a program calling mktemp() with 6 X's
in the argument, this patch gives 74^3*2=810448 possibilities instead of
52 (assuming the PID is known), and the number increases exponentially
thereafter with additional X's.

It's not a solution to mktemp() since there's still a race condition, and
for applications which only use 6 X's there's still only a relatively
small number of possible filenames, but it does incrementally improve the
situation by making it less likely for an attacker to guess the correct
name (i.e. harder to win the race).

Unless anyone has comments, I'd like to commit this to -current. Peter, I
hope I've got the right version of the patch - any remaining bugs are
likely to be my fault (although I've been running this here for a long 
time without problems).

Kris

Index: mktemp.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/mktemp.c,v
retrieving revision 1.19
diff -u -r1.19 mktemp.c
--- mktemp.c	2000/01/27 23:06:46	1.19
+++ mktemp.c	2000/06/08 00:57:17
@@ -52,6 +52,11 @@
 
 static int _gettemp __P((char *, int *, int, int));
 
+static unsigned char base64[] =
+	".#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#%^-_=+:,.~";
+
 int
 mkstemps(path, slen)
 	char *path;
@@ -103,8 +108,10 @@
 	int slen;
 {
 	register char *start, *trv, *suffp;
+	char *pad;
 	struct stat sbuf;
-	int pid, rval;
+	int rval, n;
+	uint32_t pid;
 
 	if (doopen && domkdir) {
 		errno = EINVAL;
@@ -120,20 +127,22 @@
 		errno = EINVAL;
 		return (0);
 	}
-	pid = getpid();
-	while (*trv == 'X' && pid != 0) {
-		*trv-- = (pid % 10) + '0';
-		pid /= 10;
+
+	/* Encode the PID (with 1 bit of randomness) into 3 base-64 chars */
+	pid = getpid() | (arc4random() & 0x00020000);
+	for (n = 0; *trv == 'X' && n < 3; n++) {
+		*trv-- = base64[pid & 0x3f];
+		pid >>= 6;
 	}
-	while (*trv == 'X') {
-		char c;
+	if (n < 3) {	/* Not enough characters to encode PID */
+		errno = EINVAL;
+		return(0);
+	}
 
-		pid = (arc4random() & 0xffff) % (26+26);
-		if (pid < 26)
-			c = pid + 'A';
-		else
-			c = (pid - 26) + 'a';
-		*trv-- = c;
+	/* Fill remaining space with random characters */
+	while (*trv == 'X') {
+		pid = arc4random() % (sizeof(padchar) - 1);
+		*trv-- = padchar[pid];
 	}
 	start = trv + 1;
 
@@ -179,15 +188,11 @@
 		for (trv = start;;) {
 			if (*trv == '\0' || trv == suffp)
 				return(0);
-			if (*trv == 'Z')
-				*trv++ = 'a';
+			pad = strchr(padchar, *trv);
+			if (pad == NULL || !*++pad)
+				*trv++ = padchar[0];
 			else {
-				if (isdigit((unsigned char)*trv))
-					*trv = 'a';
-				else if (*trv == 'z')	/* inc from z to A */
-					*trv = 'A';
-				else
-					++*trv;
+				*trv++ = *pad;
 				break;
 			}
 		}

--
In God we Trust -- all others must submit an X.509 certificate.
    -- Charles Forsythe <forsythe@alum.mit.edu>



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0006071758550.11848-100000>