1b528cefcSMark Murray /* 2b528cefcSMark Murray * Copyright (c) 1998, 1999 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "kadmin_locl.h" 35b528cefcSMark Murray 36adb0ddaeSAssar Westerlund RCSID("$Id: random_password.c,v 1.4 2001/02/15 04:20:53 assar Exp $"); 37b528cefcSMark Murray 38b528cefcSMark Murray /* This file defines some a function that generates a random password, 39b528cefcSMark Murray that can be used when creating a large amount of principals (such 40b528cefcSMark Murray as for a batch of students). Since this is a political matter, you 41b528cefcSMark Murray should think about how secure generated passwords has to be. 42b528cefcSMark Murray 43b528cefcSMark Murray Both methods defined here will give you at least 55 bits of 44b528cefcSMark Murray entropy. 45b528cefcSMark Murray */ 46b528cefcSMark Murray 47b528cefcSMark Murray /* If you want OTP-style passwords, define OTP_STYLE */ 48b528cefcSMark Murray 49b528cefcSMark Murray #ifdef OTP_STYLE 50b528cefcSMark Murray #include <otp.h> 51b528cefcSMark Murray #else 52b528cefcSMark Murray static void generate_password(char **pw, int num_classes, ...); 53b528cefcSMark Murray #endif 54b528cefcSMark Murray 55b528cefcSMark Murray void 56b528cefcSMark Murray random_password(char *pw, size_t len) 57b528cefcSMark Murray { 58b528cefcSMark Murray #ifdef OTP_STYLE 59b528cefcSMark Murray { 60adb0ddaeSAssar Westerlund OtpKey newkey; 61b528cefcSMark Murray 62adb0ddaeSAssar Westerlund krb5_generate_random_block(&newkey, sizeof(newkey)); 63b528cefcSMark Murray otp_print_stddict (newkey, pw, len); 64b528cefcSMark Murray strlwr(pw); 65b528cefcSMark Murray } 66b528cefcSMark Murray #else 67b528cefcSMark Murray char *pass; 68b528cefcSMark Murray generate_password(&pass, 3, 69b528cefcSMark Murray "abcdefghijklmnopqrstuvwxyz", 7, 70b528cefcSMark Murray "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2, 71b528cefcSMark Murray "@$%&*()-+=:,/<>1234567890", 1); 72b528cefcSMark Murray strlcpy(pw, pass, len); 73b528cefcSMark Murray memset(pass, 0, strlen(pass)); 74b528cefcSMark Murray free(pass); 75b528cefcSMark Murray #endif 76b528cefcSMark Murray } 77b528cefcSMark Murray 78b528cefcSMark Murray /* some helper functions */ 79b528cefcSMark Murray 80b528cefcSMark Murray #ifndef OTP_STYLE 81b528cefcSMark Murray /* return a random value in range 0-127 */ 82b528cefcSMark Murray static int 83adb0ddaeSAssar Westerlund RND(unsigned char *key, int keylen, int *left) 84b528cefcSMark Murray { 85b528cefcSMark Murray if(*left == 0){ 86adb0ddaeSAssar Westerlund krb5_generate_random_block(key, keylen); 87adb0ddaeSAssar Westerlund *left = keylen; 88b528cefcSMark Murray } 89b528cefcSMark Murray (*left)--; 90b528cefcSMark Murray return ((unsigned char*)key)[*left]; 91b528cefcSMark Murray } 92b528cefcSMark Murray 93b528cefcSMark Murray /* This a helper function that generates a random password with a 94b528cefcSMark Murray number of characters from a set of character classes. 95b528cefcSMark Murray 96b528cefcSMark Murray If there are n classes, and the size of each class is Pi, and the 97b528cefcSMark Murray number of characters from each class is Ni, the number of possible 98b528cefcSMark Murray passwords are (given that the character classes are disjoint): 99b528cefcSMark Murray 100b528cefcSMark Murray n n 101b528cefcSMark Murray ----- / ---- \ 102b528cefcSMark Murray | | Ni | \ | 103b528cefcSMark Murray | | Pi | \ Ni| ! 104b528cefcSMark Murray | | ---- * | / | 105b528cefcSMark Murray | | Ni! | /___ | 106b528cefcSMark Murray i=1 \ i=1 / 107b528cefcSMark Murray 108b528cefcSMark Murray Since it uses the RND function above, neither the size of each 109b528cefcSMark Murray class, nor the total length of the generated password should be 110b528cefcSMark Murray larger than 127 (without fixing RND). 111b528cefcSMark Murray 112b528cefcSMark Murray */ 113b528cefcSMark Murray static void 114b528cefcSMark Murray generate_password(char **pw, int num_classes, ...) 115b528cefcSMark Murray { 116b528cefcSMark Murray struct { 117b528cefcSMark Murray const char *str; 118b528cefcSMark Murray int len; 119b528cefcSMark Murray int freq; 120b528cefcSMark Murray } *classes; 121b528cefcSMark Murray va_list ap; 122b528cefcSMark Murray int len, i; 123adb0ddaeSAssar Westerlund unsigned char rbuf[8]; /* random buffer */ 124b528cefcSMark Murray int rleft = 0; 125b528cefcSMark Murray 126b528cefcSMark Murray classes = malloc(num_classes * sizeof(*classes)); 127b528cefcSMark Murray va_start(ap, num_classes); 128b528cefcSMark Murray len = 0; 129b528cefcSMark Murray for(i = 0; i < num_classes; i++){ 130b528cefcSMark Murray classes[i].str = va_arg(ap, const char*); 131b528cefcSMark Murray classes[i].len = strlen(classes[i].str); 132b528cefcSMark Murray classes[i].freq = va_arg(ap, int); 133b528cefcSMark Murray len += classes[i].freq; 134b528cefcSMark Murray } 135b528cefcSMark Murray va_end(ap); 136b528cefcSMark Murray *pw = malloc(len + 1); 137b528cefcSMark Murray if(*pw == NULL) 138b528cefcSMark Murray return; 139b528cefcSMark Murray for(i = 0; i < len; i++) { 140b528cefcSMark Murray int j; 141adb0ddaeSAssar Westerlund int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i); 142b528cefcSMark Murray int t = 0; 143b528cefcSMark Murray for(j = 0; j < num_classes; j++) { 144b528cefcSMark Murray if(x < t + classes[j].freq) { 145adb0ddaeSAssar Westerlund (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft) 146adb0ddaeSAssar Westerlund % classes[j].len]; 147b528cefcSMark Murray classes[j].freq--; 148b528cefcSMark Murray break; 149b528cefcSMark Murray } 150b528cefcSMark Murray t += classes[j].freq; 151b528cefcSMark Murray } 152b528cefcSMark Murray } 153b528cefcSMark Murray (*pw)[len] = '\0'; 154b528cefcSMark Murray memset(rbuf, 0, sizeof(rbuf)); 155b528cefcSMark Murray free(classes); 156b528cefcSMark Murray } 157b528cefcSMark Murray #endif 158