1/* 2 * Copyright (c) 2001, 2003, 2004, 2008-2010 3 * Todd C. Miller <Todd.Miller@courtesan.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <config.h> 19 20#include <sys/types.h> 21#include <sys/time.h> 22#include <sys/stat.h> 23 24#include <errno.h> 25#include <fcntl.h> 26#include <limits.h> 27#include <stdio.h> 28#ifdef HAVE_STDLIB_H 29# include <stdlib.h> 30#endif /* HAVE_STDLIB_H */ 31#include <ctype.h> 32#ifdef HAVE_UNISTD_H 33# include <unistd.h> 34#endif /* HAVE_UNISTD_H */ 35#if TIME_WITH_SYS_TIME 36# include <time.h> 37#endif 38 39#include "sudo.h" 40 41static unsigned int get_random __P((void)); 42static void seed_random __P((void)); 43 44#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 45#define NUM_CHARS (sizeof(TEMPCHARS) - 1) 46 47#ifndef INT_MAX 48#define INT_MAX 0x7fffffff 49#endif 50 51int 52mkstemps(path, slen) 53 char *path; 54 int slen; 55{ 56 char *start, *cp, *ep; 57 const char *tempchars = TEMPCHARS; 58 unsigned int r, tries; 59 int fd; 60 61 for (ep = path; *ep; ep++) 62 ; 63 if (path + slen >= ep) { 64 errno = EINVAL; 65 return -1; 66 } 67 ep -= slen; 68 69 tries = 1; 70 for (start = ep; start > path && start[-1] == 'X'; start--) { 71 if (tries < INT_MAX / NUM_CHARS) 72 tries *= NUM_CHARS; 73 } 74 tries *= 2; 75 76 do { 77 for (cp = start; *cp; cp++) { 78 r = get_random() % NUM_CHARS; 79 *cp = tempchars[r]; 80 } 81 82 fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); 83 if (fd != -1 || errno != EEXIST) 84 return fd; 85 } while (--tries); 86 87 errno = EEXIST; 88 return -1; 89} 90 91#ifdef HAVE_RANDOM 92# define RAND random 93# define SRAND srandom 94# define SEED_T unsigned int 95#else 96# ifdef HAVE_LRAND48 97# define RAND lrand48 98# define SRAND srand48 99# define SEED_T long 100# else 101# define RAND rand 102# define SRAND srand 103# define SEED_T unsigned int 104# endif 105#endif 106 107static void 108seed_random() 109{ 110 SEED_T seed; 111 struct timeval tv; 112 113 /* 114 * Seed from time of day and process id multiplied by small primes. 115 */ 116 (void) gettime(&tv); 117 seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 + 118 (getpid() % 1000) * 983; 119 SRAND(seed); 120} 121 122static unsigned int 123get_random() 124{ 125 static int initialized; 126 127 if (!initialized) { 128 seed_random(); 129 initialized = 1; 130 } 131 132 return RAND() & 0xffffffff; 133} 134