ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/tools/mkpasswd.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 11615 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

File Contents

# User Rev Content
1 adx 30 /* 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 knight 31 ** $Id$
13 adx 30 */
14 michael 1578
15 adx 30 #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 michael 952 #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 adx 30 #define FLAG_BLOWFISH 0x00000020
28 michael 952 #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 adx 30
34 michael 952
35 adx 30 extern char *crypt();
36    
37 michael 952
38     static char *make_sha256_salt(int);
39 michael 1578 static char *make_sha256_salt_para(const char *);
40 michael 952 static char *make_sha512_salt(int);
41 michael 1578 static char *make_sha512_salt_para(const char *);
42 adx 30 static char *make_des_salt(void);
43     static char *make_ext_salt(int);
44 michael 1578 static char *make_ext_salt_para(int, const char *);
45 adx 30 static char *make_md5_salt(int);
46 michael 1578 static char *make_md5_salt_para(const char *);
47 adx 30 static char *make_bf_salt(int, int);
48 michael 1578 static char *make_bf_salt_para(int, const char *);
49 adx 30 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 michael 952 int
60     main(int argc, char *argv[])
61 adx 30 {
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 michael 952 while ((c = getopt(argc, argv, "56mdber:h?l:s:p:R:")) != -1)
75 adx 30 {
76 michael 952 switch (c)
77 adx 30 {
78 michael 952 case '5':
79     flag |= FLAG_SHA256;
80     break;
81     case '6':
82     flag |= FLAG_SHA512;
83     break;
84 adx 30 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 michael 952 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 adx 30 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 michael 952 static char *
225     make_des_salt(void)
226 adx 30 {
227     static char salt[3];
228 michael 952
229 adx 30 generate_random_salt(salt, 2);
230     salt[2] = '\0';
231     return salt;
232     }
233    
234 michael 952 static char *
235     int_to_base64(int value)
236 adx 30 {
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 michael 952 static char *
253     make_ext_salt(int rounds)
254 adx 30 {
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 michael 952
261 adx 30 return salt;
262     }
263    
264 michael 952 static char *
265 michael 1578 make_ext_salt_para(int rounds, const char *saltpara)
266 adx 30 {
267     static char salt[10];
268    
269     sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara);
270     return salt;
271     }
272    
273 michael 952 static char *
274 michael 1578 make_sha256_salt_para(const char *saltpara)
275 adx 30 {
276     static char salt[21];
277 michael 952
278 adx 30 if (saltpara && (strlen(saltpara) <= 16))
279     {
280 michael 1578 /*
281     * sprintf used because of portability requirements, the length
282     * is checked above, so it should not be too much of a concern
283 michael 952 */
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 michael 1578
310 michael 952 generate_random_salt(&salt[3], length);
311 michael 1578
312 michael 952 salt[length + 3] = '$';
313     salt[length + 4] = '\0';
314    
315     return salt;
316     }
317    
318     static char *
319 michael 1578 make_sha512_salt_para(const char *saltpara)
320 michael 952 {
321     static char salt[21];
322    
323     if (saltpara && (strlen(saltpara) <= 16))
324     {
325 michael 1578 /*
326     * sprintf used because of portability requirements, the length
327     * is checked above, so it should not be too much of a concern
328 michael 952 */
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 michael 1578
355 michael 952 generate_random_salt(&salt[3], length);
356 michael 1578
357 michael 952 salt[length + 3] = '$';
358     salt[length + 4] = '\0';
359    
360     return salt;
361     }
362    
363     static char *
364 michael 1578 make_md5_salt_para(const char *saltpara)
365 michael 952 {
366     static char salt[21];
367    
368     if (saltpara && (strlen(saltpara) <= 16))
369     {
370 michael 1578 /*
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 adx 30 sprintf(salt, "$1$%s$", saltpara);
375     return salt;
376     }
377 michael 952
378 adx 30 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 michael 952 static char *
386     make_md5_salt(int length)
387 adx 30 {
388     static char salt[21];
389 michael 952
390 adx 30 if (length > 16)
391     {
392     printf("MD5 salt length too long\n");
393     exit(0);
394     }
395 michael 952
396 adx 30 salt[0] = '$';
397     salt[1] = '1';
398     salt[2] = '$';
399 michael 1578
400 adx 30 generate_random_salt(&salt[3], length);
401 michael 952
402 michael 1578 salt[length + 3] = '$';
403     salt[length + 4] = '\0';
404    
405 adx 30 return salt;
406     }
407    
408 michael 952 static char *
409 michael 1578 make_bf_salt_para(int rounds, const char *saltpara)
410 adx 30 {
411     static char salt[31];
412     char tbuf[3];
413 michael 952
414 adx 30 if (saltpara && (strlen(saltpara) <= 22))
415     {
416 michael 1578 /*
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 adx 30 sprintf(tbuf, "%02d", rounds);
421     sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
422     return salt;
423     }
424 michael 952
425 adx 30 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 michael 952 static char *
433     make_bf_salt(int rounds, int length)
434 adx 30 {
435     static char salt[31];
436     char tbuf[3];
437 michael 952
438 adx 30 if (length > 22)
439     {
440     printf("BlowFish salt length too long\n");
441     exit(0);
442     }
443 michael 952
444 adx 30 sprintf(tbuf, "%02d", rounds);
445     sprintf(salt, "$2a$%s$", tbuf);
446 michael 1578
447 adx 30 generate_random_salt(&salt[7], length);
448 michael 952
449 michael 1578 salt[length + 7] = '$';
450     salt[length + 8] = '\0';
451    
452 adx 30 return salt;
453     }
454    
455 michael 952 static char *
456     generate_poor_salt(char *salt, int length)
457 adx 30 {
458     int i;
459 michael 952
460 adx 30 srandom(time(NULL));
461 michael 952
462     for (i = 0; i < length; i++)
463 adx 30 salt[i] = saltChars[random() % 64];
464 michael 952
465     return salt;
466 adx 30 }
467    
468 michael 952 static char *
469     generate_random_salt(char *salt, int length)
470 adx 30 {
471     char *buf;
472     int fd, i;
473 michael 952
474     if ((fd = open("/dev/random", O_RDONLY)) < 0)
475     return generate_poor_salt(salt, length);
476    
477 adx 30 buf = calloc(1, length);
478 michael 952
479     if (read(fd, buf, length) != length)
480 adx 30 {
481 michael 1578 close(fd);
482 adx 30 free(buf);
483 michael 1578
484 michael 952 return generate_poor_salt(salt, length);
485 adx 30 }
486 michael 952
487     for (i = 0; i < length; i++)
488 adx 30 salt[i] = saltChars[abs(buf[i]) % 64];
489 michael 952
490 michael 1578 close(fd);
491 adx 30 free(buf);
492 michael 952
493     return salt;
494 adx 30 }
495    
496 michael 952 static void
497     full_usage(void)
498 adx 30 {
499 michael 952 printf("mkpasswd [-5|-6|-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
500 adx 30 printf(" [-R rawsalt]\n");
501 michael 1272 printf("-5 Generate a SHA-256 password\n");
502     printf("-6 Generate a SHA-512 password\n");
503 adx 30 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 michael 952 printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for SHA/MD5,\n");
512 adx 30 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 michael 952 static void
520     brief_usage(void)
521 adx 30 {
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 michael 1272 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 adx 30 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