1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * 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
36b528cefcSMark Murray /* This file defines some a function that generates a random password,
37b528cefcSMark Murray that can be used when creating a large amount of principals (such
38b528cefcSMark Murray as for a batch of students). Since this is a political matter, you
39b528cefcSMark Murray should think about how secure generated passwords has to be.
40b528cefcSMark Murray
41b528cefcSMark Murray Both methods defined here will give you at least 55 bits of
42b528cefcSMark Murray entropy.
43b528cefcSMark Murray */
44b528cefcSMark Murray
45b528cefcSMark Murray /* If you want OTP-style passwords, define OTP_STYLE */
46b528cefcSMark Murray
47b528cefcSMark Murray #ifdef OTP_STYLE
48b528cefcSMark Murray #include <otp.h>
49b528cefcSMark Murray #else
50b528cefcSMark Murray static void generate_password(char **pw, int num_classes, ...);
51b528cefcSMark Murray #endif
52b528cefcSMark Murray
53b528cefcSMark Murray void
random_password(char * pw,size_t len)54b528cefcSMark Murray random_password(char *pw, size_t len)
55b528cefcSMark Murray {
56b528cefcSMark Murray #ifdef OTP_STYLE
57b528cefcSMark Murray {
58adb0ddaeSAssar Westerlund OtpKey newkey;
59b528cefcSMark Murray
60adb0ddaeSAssar Westerlund krb5_generate_random_block(&newkey, sizeof(newkey));
61b528cefcSMark Murray otp_print_stddict (newkey, pw, len);
62b528cefcSMark Murray strlwr(pw);
63b528cefcSMark Murray }
64b528cefcSMark Murray #else
65b528cefcSMark Murray char *pass;
66b528cefcSMark Murray generate_password(&pass, 3,
67b528cefcSMark Murray "abcdefghijklmnopqrstuvwxyz", 7,
68b528cefcSMark Murray "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2,
69b528cefcSMark Murray "@$%&*()-+=:,/<>1234567890", 1);
70b528cefcSMark Murray strlcpy(pw, pass, len);
71b528cefcSMark Murray memset(pass, 0, strlen(pass));
72b528cefcSMark Murray free(pass);
73b528cefcSMark Murray #endif
74b528cefcSMark Murray }
75b528cefcSMark Murray
76b528cefcSMark Murray /* some helper functions */
77b528cefcSMark Murray
78b528cefcSMark Murray #ifndef OTP_STYLE
79b528cefcSMark Murray /* return a random value in range 0-127 */
80b528cefcSMark Murray static int
RND(unsigned char * key,int keylen,int * left)81adb0ddaeSAssar Westerlund RND(unsigned char *key, int keylen, int *left)
82b528cefcSMark Murray {
83b528cefcSMark Murray if(*left == 0){
84adb0ddaeSAssar Westerlund krb5_generate_random_block(key, keylen);
85adb0ddaeSAssar Westerlund *left = keylen;
86b528cefcSMark Murray }
87b528cefcSMark Murray (*left)--;
88b528cefcSMark Murray return ((unsigned char*)key)[*left];
89b528cefcSMark Murray }
90b528cefcSMark Murray
91b528cefcSMark Murray /* This a helper function that generates a random password with a
92b528cefcSMark Murray number of characters from a set of character classes.
93b528cefcSMark Murray
94b528cefcSMark Murray If there are n classes, and the size of each class is Pi, and the
95b528cefcSMark Murray number of characters from each class is Ni, the number of possible
96b528cefcSMark Murray passwords are (given that the character classes are disjoint):
97b528cefcSMark Murray
98b528cefcSMark Murray n n
99b528cefcSMark Murray ----- / ---- \
100b528cefcSMark Murray | | Ni | \ |
101b528cefcSMark Murray | | Pi | \ Ni| !
102b528cefcSMark Murray | | ---- * | / |
103b528cefcSMark Murray | | Ni! | /___ |
104b528cefcSMark Murray i=1 \ i=1 /
105b528cefcSMark Murray
106b528cefcSMark Murray Since it uses the RND function above, neither the size of each
107b528cefcSMark Murray class, nor the total length of the generated password should be
108b528cefcSMark Murray larger than 127 (without fixing RND).
109b528cefcSMark Murray
110b528cefcSMark Murray */
111b528cefcSMark Murray static void
generate_password(char ** pw,int num_classes,...)112b528cefcSMark Murray generate_password(char **pw, int num_classes, ...)
113b528cefcSMark Murray {
114b528cefcSMark Murray struct {
115b528cefcSMark Murray const char *str;
116b528cefcSMark Murray int len;
117b528cefcSMark Murray int freq;
118b528cefcSMark Murray } *classes;
119b528cefcSMark Murray va_list ap;
120b528cefcSMark Murray int len, i;
121adb0ddaeSAssar Westerlund unsigned char rbuf[8]; /* random buffer */
122b528cefcSMark Murray int rleft = 0;
123b528cefcSMark Murray
124c19800e8SDoug Rabson *pw = NULL;
125c19800e8SDoug Rabson
126b528cefcSMark Murray classes = malloc(num_classes * sizeof(*classes));
127c19800e8SDoug Rabson if(classes == NULL)
128c19800e8SDoug Rabson return;
129b528cefcSMark Murray va_start(ap, num_classes);
130b528cefcSMark Murray len = 0;
131b528cefcSMark Murray for(i = 0; i < num_classes; i++){
132b528cefcSMark Murray classes[i].str = va_arg(ap, const char*);
133b528cefcSMark Murray classes[i].len = strlen(classes[i].str);
134b528cefcSMark Murray classes[i].freq = va_arg(ap, int);
135b528cefcSMark Murray len += classes[i].freq;
136b528cefcSMark Murray }
137b528cefcSMark Murray va_end(ap);
138b528cefcSMark Murray *pw = malloc(len + 1);
139c19800e8SDoug Rabson if(*pw == NULL) {
140c19800e8SDoug Rabson free(classes);
141b528cefcSMark Murray return;
142c19800e8SDoug Rabson }
143b528cefcSMark Murray for(i = 0; i < len; i++) {
144b528cefcSMark Murray int j;
145adb0ddaeSAssar Westerlund int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i);
146b528cefcSMark Murray int t = 0;
147b528cefcSMark Murray for(j = 0; j < num_classes; j++) {
148b528cefcSMark Murray if(x < t + classes[j].freq) {
149adb0ddaeSAssar Westerlund (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft)
150adb0ddaeSAssar Westerlund % classes[j].len];
151b528cefcSMark Murray classes[j].freq--;
152b528cefcSMark Murray break;
153b528cefcSMark Murray }
154b528cefcSMark Murray t += classes[j].freq;
155b528cefcSMark Murray }
156b528cefcSMark Murray }
157b528cefcSMark Murray (*pw)[len] = '\0';
158b528cefcSMark Murray memset(rbuf, 0, sizeof(rbuf));
159b528cefcSMark Murray free(classes);
160b528cefcSMark Murray }
161b528cefcSMark Murray #endif
162