155682Smarkm/* 2233294Sstas * Copyright (c) 1998, 1999 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 3555682Smarkm 3655682Smarkm/* This file defines some a function that generates a random password, 3755682Smarkm that can be used when creating a large amount of principals (such 3855682Smarkm as for a batch of students). Since this is a political matter, you 3955682Smarkm should think about how secure generated passwords has to be. 40233294Sstas 4155682Smarkm Both methods defined here will give you at least 55 bits of 4255682Smarkm entropy. 4355682Smarkm */ 4455682Smarkm 4555682Smarkm/* If you want OTP-style passwords, define OTP_STYLE */ 4655682Smarkm 4755682Smarkm#ifdef OTP_STYLE 4855682Smarkm#include <otp.h> 4955682Smarkm#else 5055682Smarkmstatic void generate_password(char **pw, int num_classes, ...); 5155682Smarkm#endif 5255682Smarkm 5355682Smarkmvoid 5455682Smarkmrandom_password(char *pw, size_t len) 5555682Smarkm{ 5655682Smarkm#ifdef OTP_STYLE 5755682Smarkm { 5878527Sassar OtpKey newkey; 5955682Smarkm 6078527Sassar krb5_generate_random_block(&newkey, sizeof(newkey)); 6155682Smarkm otp_print_stddict (newkey, pw, len); 6255682Smarkm strlwr(pw); 6355682Smarkm } 6455682Smarkm#else 6555682Smarkm char *pass; 66233294Sstas generate_password(&pass, 3, 67233294Sstas "abcdefghijklmnopqrstuvwxyz", 7, 68233294Sstas "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2, 6955682Smarkm "@$%&*()-+=:,/<>1234567890", 1); 7055682Smarkm strlcpy(pw, pass, len); 7155682Smarkm memset(pass, 0, strlen(pass)); 7255682Smarkm free(pass); 7355682Smarkm#endif 7455682Smarkm} 7555682Smarkm 7655682Smarkm/* some helper functions */ 7755682Smarkm 7855682Smarkm#ifndef OTP_STYLE 7955682Smarkm/* return a random value in range 0-127 */ 8055682Smarkmstatic int 8178527SassarRND(unsigned char *key, int keylen, int *left) 8255682Smarkm{ 8355682Smarkm if(*left == 0){ 8478527Sassar krb5_generate_random_block(key, keylen); 8578527Sassar *left = keylen; 8655682Smarkm } 8755682Smarkm (*left)--; 8855682Smarkm return ((unsigned char*)key)[*left]; 8955682Smarkm} 9055682Smarkm 9155682Smarkm/* This a helper function that generates a random password with a 9255682Smarkm number of characters from a set of character classes. 9355682Smarkm 9455682Smarkm If there are n classes, and the size of each class is Pi, and the 9555682Smarkm number of characters from each class is Ni, the number of possible 9655682Smarkm passwords are (given that the character classes are disjoint): 9755682Smarkm 9855682Smarkm n n 9955682Smarkm ----- / ---- \ 10055682Smarkm | | Ni | \ | 10155682Smarkm | | Pi | \ Ni| ! 10255682Smarkm | | ---- * | / | 10355682Smarkm | | Ni! | /___ | 10455682Smarkm i=1 \ i=1 / 105233294Sstas 10655682Smarkm Since it uses the RND function above, neither the size of each 10755682Smarkm class, nor the total length of the generated password should be 10855682Smarkm larger than 127 (without fixing RND). 109233294Sstas 11055682Smarkm */ 11155682Smarkmstatic void 11255682Smarkmgenerate_password(char **pw, int num_classes, ...) 11355682Smarkm{ 11455682Smarkm struct { 11555682Smarkm const char *str; 11655682Smarkm int len; 11755682Smarkm int freq; 11855682Smarkm } *classes; 11955682Smarkm va_list ap; 12055682Smarkm int len, i; 12178527Sassar unsigned char rbuf[8]; /* random buffer */ 12255682Smarkm int rleft = 0; 12355682Smarkm 124178825Sdfr *pw = NULL; 125178825Sdfr 12655682Smarkm classes = malloc(num_classes * sizeof(*classes)); 127178825Sdfr if(classes == NULL) 128178825Sdfr return; 12955682Smarkm va_start(ap, num_classes); 13055682Smarkm len = 0; 13155682Smarkm for(i = 0; i < num_classes; i++){ 13255682Smarkm classes[i].str = va_arg(ap, const char*); 13355682Smarkm classes[i].len = strlen(classes[i].str); 13455682Smarkm classes[i].freq = va_arg(ap, int); 13555682Smarkm len += classes[i].freq; 13655682Smarkm } 13755682Smarkm va_end(ap); 13855682Smarkm *pw = malloc(len + 1); 139178825Sdfr if(*pw == NULL) { 140178825Sdfr free(classes); 14155682Smarkm return; 142178825Sdfr } 14355682Smarkm for(i = 0; i < len; i++) { 14455682Smarkm int j; 14578527Sassar int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i); 14655682Smarkm int t = 0; 14755682Smarkm for(j = 0; j < num_classes; j++) { 14855682Smarkm if(x < t + classes[j].freq) { 14978527Sassar (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft) 15078527Sassar % classes[j].len]; 15155682Smarkm classes[j].freq--; 15255682Smarkm break; 15355682Smarkm } 15455682Smarkm t += classes[j].freq; 15555682Smarkm } 15655682Smarkm } 15755682Smarkm (*pw)[len] = '\0'; 15855682Smarkm memset(rbuf, 0, sizeof(rbuf)); 15955682Smarkm free(classes); 16055682Smarkm} 16155682Smarkm#endif 162