ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.0.x/tools/mkpasswd.c
Revision: 1593
Committed: Sat Oct 27 21:09:19 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 11615 byte(s)
Log Message:
- Create 8.0.x branch

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$
13 */
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <time.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21
22 #define FLAG_MD5 0x00000001
23 #define FLAG_DES 0x00000002
24 #define FLAG_SALT 0x00000004
25 #define FLAG_PASS 0x00000008
26 #define FLAG_LENGTH 0x00000010
27 #define FLAG_BLOWFISH 0x00000020
28 #define FLAG_ROUNDS 0x00000040
29 #define FLAG_EXT 0x00000080
30 #define FLAG_RAW 0x00000100
31 #define FLAG_SHA256 0x00000200
32 #define FLAG_SHA512 0x00000400
33
34
35 extern char *crypt();
36
37
38 static char *make_sha256_salt(int);
39 static char *make_sha256_salt_para(const char *);
40 static char *make_sha512_salt(int);
41 static char *make_sha512_salt_para(const char *);
42 static char *make_des_salt(void);
43 static char *make_ext_salt(int);
44 static char *make_ext_salt_para(int, const char *);
45 static char *make_md5_salt(int);
46 static char *make_md5_salt_para(const char *);
47 static char *make_bf_salt(int, int);
48 static char *make_bf_salt_para(int, const char *);
49 static char *int_to_base64(int);
50 static char *generate_random_salt(char *, int);
51 static char *generate_poor_salt(char *, int);
52 static void full_usage(void);
53 static void brief_usage(void);
54
55 static const char saltChars[] =
56 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
57 /* 0 .. 63, ascii - 64 */
58
59 int
60 main(int argc, char *argv[])
61 {
62 const char *plaintext = NULL;
63 int c;
64 char *saltpara = NULL;
65 char *salt;
66 int flag = 0;
67 int length = 0; /* Not Set */
68 int rounds = 0; /* Not set, since extended DES needs 25 and blowfish needs
69 ** 4 by default, a side effect of this being the encryption
70 ** type parameter must be specified before the rounds
71 ** parameter.
72 */
73
74 while ((c = getopt(argc, argv, "56mdber:h?l:s:p:R:")) != -1)
75 {
76 switch (c)
77 {
78 case '5':
79 flag |= FLAG_SHA256;
80 break;
81 case '6':
82 flag |= FLAG_SHA512;
83 break;
84 case 'm':
85 flag |= FLAG_MD5;
86 break;
87 case 'd':
88 flag |= FLAG_DES;
89 break;
90 case 'b':
91 flag |= FLAG_BLOWFISH;
92 rounds = 4;
93 break;
94 case 'e':
95 flag |= FLAG_EXT;
96 rounds = 25;
97 break;
98 case 'l':
99 flag |= FLAG_LENGTH;
100 length = atoi(optarg);
101 break;
102 case 'r':
103 flag |= FLAG_ROUNDS;
104 rounds = atoi(optarg);
105 break;
106 case 's':
107 flag |= FLAG_SALT;
108 saltpara = optarg;
109 break;
110 case 'p':
111 flag |= FLAG_PASS;
112 plaintext = optarg;
113 break;
114 case 'R':
115 flag |= FLAG_RAW;
116 saltpara = optarg;
117 break;
118 case 'h':
119 full_usage();
120 /* NOT REACHED */
121 break;
122 case '?':
123 brief_usage();
124 /* NOT REACHED */
125 break;
126 default:
127 printf("Invalid Option: -%c\n", c);
128 break;
129 }
130 }
131
132 if (flag & FLAG_MD5)
133 {
134 if (length == 0)
135 length = 8;
136 if (flag & FLAG_SALT)
137 salt = make_md5_salt_para(saltpara);
138 else
139 salt = make_md5_salt(length);
140 }
141 else if (flag & FLAG_SHA256)
142 {
143 if (length == 0)
144 length = 16;
145 if (flag & FLAG_SALT)
146 salt = make_sha256_salt_para(saltpara);
147 else
148 salt = make_sha256_salt(length);
149 }
150 else if (flag & FLAG_SHA512)
151 {
152 if (length == 0)
153 length = 16;
154 if (flag & FLAG_SALT)
155 salt = make_sha512_salt_para(saltpara);
156 else
157 salt = make_sha512_salt(length);
158 }
159 else if (flag & FLAG_BLOWFISH)
160 {
161 if (length == 0)
162 length = 22;
163 if (flag & FLAG_SALT)
164 salt = make_bf_salt_para(rounds, saltpara);
165 else
166 salt = make_bf_salt(rounds, length);
167 }
168 else if (flag & FLAG_EXT)
169 {
170 /* XXX - rounds needs to be done */
171 if (flag & FLAG_SALT)
172 {
173 if ((strlen(saltpara) == 4))
174 {
175 salt = make_ext_salt_para(rounds, saltpara);
176 }
177 else
178 {
179 printf("Invalid salt, please enter 4 alphanumeric characters\n");
180 exit(1);
181 }
182 }
183 else
184 {
185 salt = make_ext_salt(rounds);
186 }
187 }
188 else if (flag & FLAG_RAW)
189 {
190 salt = saltpara;
191 }
192 else /* Default to DES */
193 {
194 if (flag & FLAG_SALT)
195 {
196 if ((strlen(saltpara) == 2))
197 {
198 salt = saltpara;
199 }
200 else
201 {
202 printf("Invalid salt, please enter 2 alphanumeric characters\n");
203 exit(1);
204 }
205 }
206 else
207 {
208 salt = make_des_salt();
209 }
210 }
211
212 if (flag & FLAG_PASS)
213 {
214 if (!plaintext)
215 printf("Please enter a valid password\n");
216 }
217 else
218 plaintext = getpass("plaintext: ");
219
220 printf("%s\n", crypt(plaintext, salt));
221 return 0;
222 }
223
224 static char *
225 make_des_salt(void)
226 {
227 static char salt[3];
228
229 generate_random_salt(salt, 2);
230 salt[2] = '\0';
231 return salt;
232 }
233
234 static char *
235 int_to_base64(int value)
236 {
237 static char buf[5];
238 int i;
239
240 for (i = 0; i < 4; i++)
241 {
242 buf[i] = saltChars[value & 63];
243 value >>= 6; /* Right shifting 6 places is the same as dividing by 64 */
244 }
245
246 buf[i] = '\0'; /* not REALLY needed as it's static, and thus initialized
247 ** to \0.
248 */
249 return buf;
250 }
251
252 static char *
253 make_ext_salt(int rounds)
254 {
255 static char salt[10];
256
257 sprintf(salt, "_%s", int_to_base64(rounds));
258 generate_random_salt(&salt[5], 4);
259 salt[9] = '\0';
260
261 return salt;
262 }
263
264 static char *
265 make_ext_salt_para(int rounds, const char *saltpara)
266 {
267 static char salt[10];
268
269 sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara);
270 return salt;
271 }
272
273 static char *
274 make_sha256_salt_para(const char *saltpara)
275 {
276 static char salt[21];
277
278 if (saltpara && (strlen(saltpara) <= 16))
279 {
280 /*
281 * sprintf used because of portability requirements, the length
282 * is checked above, so it should not be too much of a concern
283 */
284 sprintf(salt, "$5$%s$", saltpara);
285 return salt;
286 }
287
288 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
289 exit(1);
290
291 /* NOT REACHED */
292 return NULL;
293 }
294
295 static char *
296 make_sha256_salt(int length)
297 {
298 static char salt[21];
299
300 if (length > 16)
301 {
302 printf("SHA256 salt length too long\n");
303 exit(0);
304 }
305
306 salt[0] = '$';
307 salt[1] = '5';
308 salt[2] = '$';
309
310 generate_random_salt(&salt[3], length);
311
312 salt[length + 3] = '$';
313 salt[length + 4] = '\0';
314
315 return salt;
316 }
317
318 static char *
319 make_sha512_salt_para(const char *saltpara)
320 {
321 static char salt[21];
322
323 if (saltpara && (strlen(saltpara) <= 16))
324 {
325 /*
326 * sprintf used because of portability requirements, the length
327 * is checked above, so it should not be too much of a concern
328 */
329 sprintf(salt, "$6$%s$", saltpara);
330 return salt;
331 }
332
333 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
334 exit(1);
335
336 /* NOT REACHED */
337 return NULL;
338 }
339
340 static char *
341 make_sha512_salt(int length)
342 {
343 static char salt[21];
344
345 if (length > 16)
346 {
347 printf("SHA512 salt length too long\n");
348 exit(0);
349 }
350
351 salt[0] = '$';
352 salt[1] = '6';
353 salt[2] = '$';
354
355 generate_random_salt(&salt[3], length);
356
357 salt[length + 3] = '$';
358 salt[length + 4] = '\0';
359
360 return salt;
361 }
362
363 static char *
364 make_md5_salt_para(const char *saltpara)
365 {
366 static char salt[21];
367
368 if (saltpara && (strlen(saltpara) <= 16))
369 {
370 /*
371 * sprintf used because of portability requirements, the length
372 * is checked above, so it should not be too much of a concern
373 */
374 sprintf(salt, "$1$%s$", saltpara);
375 return salt;
376 }
377
378 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
379 exit(1);
380
381 /* NOT REACHED */
382 return NULL;
383 }
384
385 static char *
386 make_md5_salt(int length)
387 {
388 static char salt[21];
389
390 if (length > 16)
391 {
392 printf("MD5 salt length too long\n");
393 exit(0);
394 }
395
396 salt[0] = '$';
397 salt[1] = '1';
398 salt[2] = '$';
399
400 generate_random_salt(&salt[3], length);
401
402 salt[length + 3] = '$';
403 salt[length + 4] = '\0';
404
405 return salt;
406 }
407
408 static char *
409 make_bf_salt_para(int rounds, const char *saltpara)
410 {
411 static char salt[31];
412 char tbuf[3];
413
414 if (saltpara && (strlen(saltpara) <= 22))
415 {
416 /*
417 * sprintf used because of portability requirements, the length
418 * is checked above, so it should not be too much of a concern
419 */
420 sprintf(tbuf, "%02d", rounds);
421 sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
422 return salt;
423 }
424
425 printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
426 exit(1);
427
428 /* NOT REACHED */
429 return NULL;
430 }
431
432 static char *
433 make_bf_salt(int rounds, int length)
434 {
435 static char salt[31];
436 char tbuf[3];
437
438 if (length > 22)
439 {
440 printf("BlowFish salt length too long\n");
441 exit(0);
442 }
443
444 sprintf(tbuf, "%02d", rounds);
445 sprintf(salt, "$2a$%s$", tbuf);
446
447 generate_random_salt(&salt[7], length);
448
449 salt[length + 7] = '$';
450 salt[length + 8] = '\0';
451
452 return salt;
453 }
454
455 static char *
456 generate_poor_salt(char *salt, int length)
457 {
458 int i;
459
460 srandom(time(NULL));
461
462 for (i = 0; i < length; i++)
463 salt[i] = saltChars[random() % 64];
464
465 return salt;
466 }
467
468 static char *
469 generate_random_salt(char *salt, int length)
470 {
471 char *buf;
472 int fd, i;
473
474 if ((fd = open("/dev/random", O_RDONLY)) < 0)
475 return generate_poor_salt(salt, length);
476
477 buf = calloc(1, length);
478
479 if (read(fd, buf, length) != length)
480 {
481 close(fd);
482 free(buf);
483
484 return generate_poor_salt(salt, length);
485 }
486
487 for (i = 0; i < length; i++)
488 salt[i] = saltChars[abs(buf[i]) % 64];
489
490 close(fd);
491 free(buf);
492
493 return salt;
494 }
495
496 static void
497 full_usage(void)
498 {
499 printf("mkpasswd [-5|-6|-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
500 printf(" [-R rawsalt]\n");
501 printf("-5 Generate a SHA-256 password\n");
502 printf("-6 Generate a SHA-512 password\n");
503 printf("-m Generate an MD5 password\n");
504 printf("-d Generate a DES password\n");
505 printf("-b Generate a BlowFish password\n");
506 printf("-e Generate an Extended DES password\n");
507 printf("-l Specify a length for a random MD5 or BlowFish salt\n");
508 printf("-r Specify a number of rounds for a BlowFish or Extended DES password\n");
509 printf(" BlowFish: default 4, no more than 6 recommended\n");
510 printf(" Extended DES: default 25\n");
511 printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for SHA/MD5,\n");
512 printf(" up to 22 for BlowFish, and 4 for Extended DES\n");
513 printf("-R Specify a raw salt passed directly to crypt()\n");
514 printf("-p Specify a plaintext password to use\n");
515 printf("Example: mkpasswd -m -s 3dr -p test\n");
516 exit(0);
517 }
518
519 static void
520 brief_usage(void)
521 {
522 printf("mkpasswd - password hash generator\n");
523 printf("Standard DES: mkpasswd [-d] [-s salt] [-p plaintext]\n");
524 printf("Extended DES: mkpasswd -e [-r rounds] [-s salt] [-p plaintext]\n");
525 printf(" SHA-256: mkpasswd -5 [-l saltlength] [-s salt] [-p plaintext]\n");
526 printf(" SHA-512: mkpasswd -6 [-l saltlength] [-s salt] [-p plaintext]\n");
527 printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n");
528 printf(" BlowFish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n");
529 printf(" [-p plaintext]\n");
530 printf(" Raw: mkpasswd -R <rawsalt> [-p plaintext]\n");
531 printf("Use -h for full usage\n");
532 exit(0);
533 }

Properties

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