From owner-freebsd-current Wed Jun 7 18:11: 8 2000 Delivered-To: freebsd-current@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id C5A6B37B5AE for ; Wed, 7 Jun 2000 18:11:04 -0700 (PDT) (envelope-from kris@FreeBSD.org) Received: from localhost (kris@localhost) by freefall.freebsd.org (8.9.3/8.9.2) with ESMTP id SAA15265 for ; Wed, 7 Jun 2000 18:11:04 -0700 (PDT) (envelope-from kris@FreeBSD.org) X-Authentication-Warning: freefall.freebsd.org: kris owned process doing -bs Date: Wed, 7 Jun 2000 18:11:04 -0700 (PDT) From: Kris Kennaway To: current@freebsd.org Subject: mktemp() patch Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message