ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/tools/mkpasswd.c
Revision: 30
Committed: Sun Oct 2 20:03:27 2005 UTC (18 years, 5 months ago) by adx
Content type: text/x-csrc
Original Path: ircd-hybrid/tools/mkpasswd.c
File size: 8946 byte(s)
Log Message:
- imported sources
- can be moved later according to the directory/branching scheme,
  but we need the svn up

File Contents

# Content
1 /* simple password generator by Nelson Minar (minar@reed.edu)
2 ** copyright 1991, all rights reserved.
3 ** You can use this code as long as my name stays with it.
4 **
5 ** md5 patch by W. Campbell <wcampbel@botbay.net>
6 ** Modernization, getopt, etc for the Hybrid IRCD team
7 ** by W. Campbell
8 **
9 ** /dev/random for salt generation added by
10 ** Aaron Sethman <androsyn@ratbox.org>
11 **
12 ** $Id: mkpasswd.c,v 7.18 2005/04/24 12:43:09 michael Exp $
13 */
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <time.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20
21 #define FLAG_MD5 0x00000001
22 #define FLAG_DES 0x00000002
23 #define FLAG_SALT 0x00000004
24 #define FLAG_PASS 0x00000008
25 #define FLAG_LENGTH 0x00000010
26 #define FLAG_BLOWFISH 0x00000020
27 #define FLAG_ROUNDS 0x00000040
28 #define FLAG_EXT 0x00000080
29 #define FLAG_RAW 0x00000100
30
31 extern char *crypt();
32
33 static char *make_des_salt(void);
34 static char *make_ext_salt(int);
35 static char *make_ext_salt_para(int, char *);
36 static char *make_md5_salt(int);
37 static char *make_md5_salt_para(char *);
38 static char *make_bf_salt(int, int);
39 static char *make_bf_salt_para(int, char *);
40 static char *int_to_base64(int);
41 static char *generate_random_salt(char *, int);
42 static char *generate_poor_salt(char *, int);
43 static void full_usage(void);
44 static void brief_usage(void);
45
46 static const char saltChars[] =
47 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
48 /* 0 .. 63, ascii - 64 */
49
50 int main(int argc, char *argv[])
51 {
52 const char *plaintext = NULL;
53 int c;
54 char *saltpara = NULL;
55 char *salt;
56 int flag = 0;
57 int length = 0; /* Not Set */
58 int rounds = 0; /* Not set, since extended DES needs 25 and blowfish needs
59 ** 4 by default, a side effect of this being the encryption
60 ** type parameter must be specified before the rounds
61 ** parameter.
62 */
63
64 while ((c = getopt(argc, argv, "mdber:h?l:s:p:R:")) != -1)
65 {
66 switch(c)
67 {
68 case 'm':
69 flag |= FLAG_MD5;
70 break;
71 case 'd':
72 flag |= FLAG_DES;
73 break;
74 case 'b':
75 flag |= FLAG_BLOWFISH;
76 rounds = 4;
77 break;
78 case 'e':
79 flag |= FLAG_EXT;
80 rounds = 25;
81 break;
82 case 'l':
83 flag |= FLAG_LENGTH;
84 length = atoi(optarg);
85 break;
86 case 'r':
87 flag |= FLAG_ROUNDS;
88 rounds = atoi(optarg);
89 break;
90 case 's':
91 flag |= FLAG_SALT;
92 saltpara = optarg;
93 break;
94 case 'p':
95 flag |= FLAG_PASS;
96 plaintext = optarg;
97 break;
98 case 'R':
99 flag |= FLAG_RAW;
100 saltpara = optarg;
101 break;
102 case 'h':
103 full_usage();
104 /* NOT REACHED */
105 break;
106 case '?':
107 brief_usage();
108 /* NOT REACHED */
109 break;
110 default:
111 printf("Invalid Option: -%c\n", c);
112 break;
113 }
114 }
115
116 if (flag & FLAG_MD5)
117 {
118 if (length == 0)
119 length = 8;
120 if (flag & FLAG_SALT)
121 salt = make_md5_salt_para(saltpara);
122 else
123 salt = make_md5_salt(length);
124 }
125 else if (flag & FLAG_BLOWFISH)
126 {
127 if (length == 0)
128 length = 22;
129 if (flag & FLAG_SALT)
130 salt = make_bf_salt_para(rounds, saltpara);
131 else
132 salt = make_bf_salt(rounds, length);
133 }
134 else if (flag & FLAG_EXT)
135 {
136 /* XXX - rounds needs to be done */
137 if (flag & FLAG_SALT)
138 {
139 if ((strlen(saltpara) == 4))
140 {
141 salt = make_ext_salt_para(rounds, saltpara);
142 }
143 else
144 {
145 printf("Invalid salt, please enter 4 alphanumeric characters\n");
146 exit(1);
147 }
148 }
149 else
150 {
151 salt = make_ext_salt(rounds);
152 }
153 }
154 else if (flag & FLAG_RAW)
155 {
156 salt = saltpara;
157 }
158 else /* Default to DES */
159 {
160 if (flag & FLAG_SALT)
161 {
162 if ((strlen(saltpara) == 2))
163 {
164 salt = saltpara;
165 }
166 else
167 {
168 printf("Invalid salt, please enter 2 alphanumeric characters\n");
169 exit(1);
170 }
171 }
172 else
173 {
174 salt = make_des_salt();
175 }
176 }
177
178 if (flag & FLAG_PASS)
179 {
180 if (!plaintext)
181 printf("Please enter a valid password\n");
182 }
183 else
184 {
185 plaintext = getpass("plaintext: ");
186 }
187
188 printf("%s\n", crypt(plaintext, salt));
189 return 0;
190 }
191
192 static char *make_des_salt(void)
193 {
194 static char salt[3];
195 generate_random_salt(salt, 2);
196 salt[2] = '\0';
197 return salt;
198 }
199
200 static char *int_to_base64(int value)
201 {
202 static char buf[5];
203 int i;
204
205 for (i = 0; i < 4; i++)
206 {
207 buf[i] = saltChars[value & 63];
208 value >>= 6; /* Right shifting 6 places is the same as dividing by 64 */
209 }
210
211 buf[i] = '\0'; /* not REALLY needed as it's static, and thus initialized
212 ** to \0.
213 */
214 return buf;
215 }
216
217 static char *make_ext_salt(int rounds)
218 {
219 static char salt[10];
220
221 sprintf(salt, "_%s", int_to_base64(rounds));
222 generate_random_salt(&salt[5], 4);
223 salt[9] = '\0';
224 return salt;
225 }
226
227 static char *make_ext_salt_para(int rounds, char *saltpara)
228 {
229 static char salt[10];
230
231 sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara);
232 return salt;
233 }
234
235 static char *make_md5_salt_para(char *saltpara)
236 {
237 static char salt[21];
238 if (saltpara && (strlen(saltpara) <= 16))
239 {
240 /* sprintf used because of portability requirements, the length
241 ** is checked above, so it should not be too much of a concern
242 */
243 sprintf(salt, "$1$%s$", saltpara);
244 return salt;
245 }
246 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
247 exit(1);
248
249 /* NOT REACHED */
250 return NULL;
251 }
252
253 static char *make_md5_salt(int length)
254 {
255 static char salt[21];
256 if (length > 16)
257 {
258 printf("MD5 salt length too long\n");
259 exit(0);
260 }
261 salt[0] = '$';
262 salt[1] = '1';
263 salt[2] = '$';
264 generate_random_salt(&salt[3], length);
265 salt[length+3] = '$';
266 salt[length+4] = '\0';
267 return salt;
268 }
269
270 static char *make_bf_salt_para(int rounds, char *saltpara)
271 {
272 static char salt[31];
273 char tbuf[3];
274 if (saltpara && (strlen(saltpara) <= 22))
275 {
276 /* sprintf used because of portability requirements, the length
277 ** is checked above, so it should not be too much of a concern
278 */
279 sprintf(tbuf, "%02d", rounds);
280 sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
281 return salt;
282 }
283 printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
284 exit(1);
285
286 /* NOT REACHED */
287 return NULL;
288 }
289
290 static char *make_bf_salt(int rounds, int length)
291 {
292 static char salt[31];
293 char tbuf[3];
294 if (length > 22)
295 {
296 printf("BlowFish salt length too long\n");
297 exit(0);
298 }
299 sprintf(tbuf, "%02d", rounds);
300 sprintf(salt, "$2a$%s$", tbuf);
301 generate_random_salt(&salt[7], length);
302 salt[length+7] = '$';
303 salt[length+8] = '\0';
304 return salt;
305 }
306
307 static char *generate_poor_salt(char *salt, int length)
308 {
309 int i;
310 srandom(time(NULL));
311 for(i = 0; i < length; i++)
312 {
313 salt[i] = saltChars[random() % 64];
314 }
315 return(salt);
316 }
317
318 static char *generate_random_salt(char *salt, int length)
319 {
320 char *buf;
321 int fd, i;
322 if((fd = open("/dev/random", O_RDONLY)) < 0)
323 {
324 return(generate_poor_salt(salt, length));
325 }
326 buf = calloc(1, length);
327 if(read(fd, buf, length) != length)
328 {
329 free(buf);
330 return(generate_poor_salt(salt, length));
331 }
332
333 for(i = 0; i < length; i++)
334 {
335 salt[i] = saltChars[abs(buf[i]) % 64];
336 }
337 free(buf);
338 return(salt);
339 }
340
341 static void full_usage(void)
342 {
343 printf("mkpasswd [-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
344 printf(" [-R rawsalt]\n");
345 printf("-m Generate an MD5 password\n");
346 printf("-d Generate a DES password\n");
347 printf("-b Generate a BlowFish password\n");
348 printf("-e Generate an Extended DES password\n");
349 printf("-l Specify a length for a random MD5 or BlowFish salt\n");
350 printf("-r Specify a number of rounds for a BlowFish or Extended DES password\n");
351 printf(" BlowFish: default 4, no more than 6 recommended\n");
352 printf(" Extended DES: default 25\n");
353 printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for MD5,\n");
354 printf(" up to 22 for BlowFish, and 4 for Extended DES\n");
355 printf("-R Specify a raw salt passed directly to crypt()\n");
356 printf("-p Specify a plaintext password to use\n");
357 printf("Example: mkpasswd -m -s 3dr -p test\n");
358 exit(0);
359 }
360
361 static void brief_usage(void)
362 {
363 printf("mkpasswd - password hash generator\n");
364 printf("Standard DES: mkpasswd [-d] [-s salt] [-p plaintext]\n");
365 printf("Extended DES: mkpasswd -e [-r rounds] [-s salt] [-p plaintext]\n");
366 printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n");
367 printf(" BlowFish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n");
368 printf(" [-p plaintext]\n");
369 printf(" Raw: mkpasswd -R <rawsalt> [-p plaintext]\n");
370 printf("Use -h for full usage\n");
371 exit(0);
372 }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"