random_password.c revision 178825
155682Smarkm/* 255682Smarkm * Copyright (c) 1998, 1999 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 3555682Smarkm 36178825SdfrRCSID("$Id: random_password.c 21745 2007-07-31 16:11:25Z lha $"); 3755682Smarkm 3855682Smarkm/* This file defines some a function that generates a random password, 3955682Smarkm that can be used when creating a large amount of principals (such 4055682Smarkm as for a batch of students). Since this is a political matter, you 4155682Smarkm should think about how secure generated passwords has to be. 4255682Smarkm 4355682Smarkm Both methods defined here will give you at least 55 bits of 4455682Smarkm entropy. 4555682Smarkm */ 4655682Smarkm 4755682Smarkm/* If you want OTP-style passwords, define OTP_STYLE */ 4855682Smarkm 4955682Smarkm#ifdef OTP_STYLE 5055682Smarkm#include <otp.h> 5155682Smarkm#else 5255682Smarkmstatic void generate_password(char **pw, int num_classes, ...); 5355682Smarkm#endif 5455682Smarkm 5555682Smarkmvoid 5655682Smarkmrandom_password(char *pw, size_t len) 5755682Smarkm{ 5855682Smarkm#ifdef OTP_STYLE 5955682Smarkm { 6078527Sassar OtpKey newkey; 6155682Smarkm 6278527Sassar krb5_generate_random_block(&newkey, sizeof(newkey)); 6355682Smarkm otp_print_stddict (newkey, pw, len); 6455682Smarkm strlwr(pw); 6555682Smarkm } 6655682Smarkm#else 6755682Smarkm char *pass; 6855682Smarkm generate_password(&pass, 3, 6955682Smarkm "abcdefghijklmnopqrstuvwxyz", 7, 7055682Smarkm "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2, 7155682Smarkm "@$%&*()-+=:,/<>1234567890", 1); 7255682Smarkm strlcpy(pw, pass, len); 7355682Smarkm memset(pass, 0, strlen(pass)); 7455682Smarkm free(pass); 7555682Smarkm#endif 7655682Smarkm} 7755682Smarkm 7855682Smarkm/* some helper functions */ 7955682Smarkm 8055682Smarkm#ifndef OTP_STYLE 8155682Smarkm/* return a random value in range 0-127 */ 8255682Smarkmstatic int 8378527SassarRND(unsigned char *key, int keylen, int *left) 8455682Smarkm{ 8555682Smarkm if(*left == 0){ 8678527Sassar krb5_generate_random_block(key, keylen); 8778527Sassar *left = keylen; 8855682Smarkm } 8955682Smarkm (*left)--; 9055682Smarkm return ((unsigned char*)key)[*left]; 9155682Smarkm} 9255682Smarkm 9355682Smarkm/* This a helper function that generates a random password with a 9455682Smarkm number of characters from a set of character classes. 9555682Smarkm 9655682Smarkm If there are n classes, and the size of each class is Pi, and the 9755682Smarkm number of characters from each class is Ni, the number of possible 9855682Smarkm passwords are (given that the character classes are disjoint): 9955682Smarkm 10055682Smarkm n n 10155682Smarkm ----- / ---- \ 10255682Smarkm | | Ni | \ | 10355682Smarkm | | Pi | \ Ni| ! 10455682Smarkm | | ---- * | / | 10555682Smarkm | | Ni! | /___ | 10655682Smarkm i=1 \ i=1 / 10755682Smarkm 10855682Smarkm Since it uses the RND function above, neither the size of each 10955682Smarkm class, nor the total length of the generated password should be 11055682Smarkm larger than 127 (without fixing RND). 11155682Smarkm 11255682Smarkm */ 11355682Smarkmstatic void 11455682Smarkmgenerate_password(char **pw, int num_classes, ...) 11555682Smarkm{ 11655682Smarkm struct { 11755682Smarkm const char *str; 11855682Smarkm int len; 11955682Smarkm int freq; 12055682Smarkm } *classes; 12155682Smarkm va_list ap; 12255682Smarkm int len, i; 12378527Sassar unsigned char rbuf[8]; /* random buffer */ 12455682Smarkm int rleft = 0; 12555682Smarkm 126178825Sdfr *pw = NULL; 127178825Sdfr 12855682Smarkm classes = malloc(num_classes * sizeof(*classes)); 129178825Sdfr if(classes == NULL) 130178825Sdfr return; 13155682Smarkm va_start(ap, num_classes); 13255682Smarkm len = 0; 13355682Smarkm for(i = 0; i < num_classes; i++){ 13455682Smarkm classes[i].str = va_arg(ap, const char*); 13555682Smarkm classes[i].len = strlen(classes[i].str); 13655682Smarkm classes[i].freq = va_arg(ap, int); 13755682Smarkm len += classes[i].freq; 13855682Smarkm } 13955682Smarkm va_end(ap); 14055682Smarkm *pw = malloc(len + 1); 141178825Sdfr if(*pw == NULL) { 142178825Sdfr free(classes); 14355682Smarkm return; 144178825Sdfr } 14555682Smarkm for(i = 0; i < len; i++) { 14655682Smarkm int j; 14778527Sassar int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i); 14855682Smarkm int t = 0; 14955682Smarkm for(j = 0; j < num_classes; j++) { 15055682Smarkm if(x < t + classes[j].freq) { 15178527Sassar (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft) 15278527Sassar % classes[j].len]; 15355682Smarkm classes[j].freq--; 15455682Smarkm break; 15555682Smarkm } 15655682Smarkm t += classes[j].freq; 15755682Smarkm } 15855682Smarkm } 15955682Smarkm (*pw)[len] = '\0'; 16055682Smarkm memset(rbuf, 0, sizeof(rbuf)); 16155682Smarkm free(classes); 16255682Smarkm} 16355682Smarkm#endif 164