ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/tools/mkpasswd.c
Revision: 3126
Committed: Sun Mar 9 20:10:33 2014 UTC (10 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/tools/mkpasswd.c
File size: 11144 byte(s)
Log Message:
- mkpasswd.c: mkpasswd now defaults to MD5 instead of DES

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 michael 3073 const char *saltpara = NULL;
64     const char *salt = NULL;
65 adx 30 int c;
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 michael 3126 if (flag & FLAG_DES)
133 adx 30 {
134     if (flag & FLAG_SALT)
135 michael 3126 {
136     if ((strlen(saltpara) == 2))
137     salt = saltpara;
138     else
139     {
140     printf("Invalid salt, please enter 2 alphanumeric characters\n");
141     exit(1);
142     }
143     }
144 adx 30 else
145 michael 3126 salt = make_des_salt();
146 adx 30 }
147 michael 952 else if (flag & FLAG_SHA256)
148     {
149     if (length == 0)
150     length = 16;
151     if (flag & FLAG_SALT)
152     salt = make_sha256_salt_para(saltpara);
153     else
154     salt = make_sha256_salt(length);
155     }
156     else if (flag & FLAG_SHA512)
157     {
158     if (length == 0)
159     length = 16;
160     if (flag & FLAG_SALT)
161     salt = make_sha512_salt_para(saltpara);
162     else
163     salt = make_sha512_salt(length);
164     }
165 adx 30 else if (flag & FLAG_BLOWFISH)
166     {
167     if (length == 0)
168     length = 22;
169     if (flag & FLAG_SALT)
170     salt = make_bf_salt_para(rounds, saltpara);
171     else
172     salt = make_bf_salt(rounds, length);
173     }
174     else if (flag & FLAG_EXT)
175     {
176     /* XXX - rounds needs to be done */
177     if (flag & FLAG_SALT)
178     {
179     if ((strlen(saltpara) == 4))
180     {
181     salt = make_ext_salt_para(rounds, saltpara);
182     }
183     else
184     {
185     printf("Invalid salt, please enter 4 alphanumeric characters\n");
186     exit(1);
187     }
188     }
189     else
190     {
191     salt = make_ext_salt(rounds);
192     }
193     }
194     else if (flag & FLAG_RAW)
195     {
196     salt = saltpara;
197     }
198 michael 3126 else /* Default to MD5 */
199 adx 30 {
200 michael 3126 if (length == 0)
201     length = 8;
202 adx 30 if (flag & FLAG_SALT)
203 michael 3126 salt = make_md5_salt_para(saltpara);
204 adx 30 else
205 michael 3126 salt = make_md5_salt(length);
206 adx 30 }
207    
208     if (flag & FLAG_PASS)
209     {
210     if (!plaintext)
211     printf("Please enter a valid password\n");
212     }
213     else
214     plaintext = getpass("plaintext: ");
215    
216     printf("%s\n", crypt(plaintext, salt));
217     return 0;
218     }
219    
220 michael 952 static char *
221     make_des_salt(void)
222 adx 30 {
223     static char salt[3];
224 michael 952
225 adx 30 generate_random_salt(salt, 2);
226     salt[2] = '\0';
227     return salt;
228     }
229    
230 michael 952 static char *
231     int_to_base64(int value)
232 adx 30 {
233     static char buf[5];
234     int i;
235    
236     for (i = 0; i < 4; i++)
237     {
238     buf[i] = saltChars[value & 63];
239     value >>= 6; /* Right shifting 6 places is the same as dividing by 64 */
240     }
241    
242     buf[i] = '\0'; /* not REALLY needed as it's static, and thus initialized
243     ** to \0.
244     */
245     return buf;
246     }
247    
248 michael 952 static char *
249     make_ext_salt(int rounds)
250 adx 30 {
251     static char salt[10];
252    
253 michael 2265 snprintf(salt, sizeof(salt), "_%s", int_to_base64(rounds));
254    
255 adx 30 generate_random_salt(&salt[5], 4);
256     salt[9] = '\0';
257 michael 952
258 adx 30 return salt;
259     }
260    
261 michael 952 static char *
262 michael 1578 make_ext_salt_para(int rounds, const char *saltpara)
263 adx 30 {
264     static char salt[10];
265    
266 michael 2222 snprintf(salt, sizeof(salt), "_%s%s", int_to_base64(rounds), saltpara);
267 adx 30 return salt;
268     }
269    
270 michael 952 static char *
271 michael 1578 make_sha256_salt_para(const char *saltpara)
272 adx 30 {
273     static char salt[21];
274 michael 952
275 adx 30 if (saltpara && (strlen(saltpara) <= 16))
276     {
277 michael 2222 snprintf(salt, sizeof(salt), "$5$%s$", saltpara);
278 michael 952 return salt;
279     }
280    
281     printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
282     exit(1);
283    
284     /* NOT REACHED */
285     return NULL;
286     }
287    
288     static char *
289     make_sha256_salt(int length)
290     {
291     static char salt[21];
292    
293     if (length > 16)
294     {
295 michael 3125 printf("SHA-256 salt length too long\n");
296 michael 952 exit(0);
297     }
298    
299     salt[0] = '$';
300     salt[1] = '5';
301     salt[2] = '$';
302 michael 1578
303 michael 952 generate_random_salt(&salt[3], length);
304 michael 1578
305 michael 952 salt[length + 3] = '$';
306     salt[length + 4] = '\0';
307    
308     return salt;
309     }
310    
311     static char *
312 michael 1578 make_sha512_salt_para(const char *saltpara)
313 michael 952 {
314     static char salt[21];
315    
316     if (saltpara && (strlen(saltpara) <= 16))
317     {
318 michael 2222 snprintf(salt, sizeof(salt), "$6$%s$", saltpara);
319 michael 952 return salt;
320     }
321    
322     printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
323     exit(1);
324    
325     /* NOT REACHED */
326     return NULL;
327     }
328    
329     static char *
330     make_sha512_salt(int length)
331     {
332     static char salt[21];
333    
334     if (length > 16)
335     {
336 michael 3125 printf("SHA-512 salt length too long\n");
337 michael 952 exit(0);
338     }
339    
340     salt[0] = '$';
341     salt[1] = '6';
342     salt[2] = '$';
343 michael 1578
344 michael 952 generate_random_salt(&salt[3], length);
345 michael 1578
346 michael 952 salt[length + 3] = '$';
347     salt[length + 4] = '\0';
348    
349     return salt;
350     }
351    
352     static char *
353 michael 1578 make_md5_salt_para(const char *saltpara)
354 michael 952 {
355     static char salt[21];
356    
357     if (saltpara && (strlen(saltpara) <= 16))
358     {
359 michael 2222 snprintf(salt, sizeof(salt), "$1$%s$", saltpara);
360 adx 30 return salt;
361     }
362 michael 952
363 adx 30 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
364     exit(1);
365    
366     /* NOT REACHED */
367     return NULL;
368     }
369    
370 michael 952 static char *
371     make_md5_salt(int length)
372 adx 30 {
373     static char salt[21];
374 michael 952
375 adx 30 if (length > 16)
376     {
377     printf("MD5 salt length too long\n");
378     exit(0);
379     }
380 michael 952
381 adx 30 salt[0] = '$';
382     salt[1] = '1';
383     salt[2] = '$';
384 michael 1578
385 adx 30 generate_random_salt(&salt[3], length);
386 michael 952
387 michael 1578 salt[length + 3] = '$';
388     salt[length + 4] = '\0';
389    
390 adx 30 return salt;
391     }
392    
393 michael 952 static char *
394 michael 1578 make_bf_salt_para(int rounds, const char *saltpara)
395 adx 30 {
396     static char salt[31];
397     char tbuf[3];
398 michael 952
399 adx 30 if (saltpara && (strlen(saltpara) <= 22))
400     {
401 michael 2222 snprintf(tbuf, sizeof(tbuf), "%02d", rounds);
402     snprintf(salt, sizeof(salt), "$2a$%s$%s$", tbuf, saltpara);
403 adx 30 return salt;
404     }
405 michael 952
406 adx 30 printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
407     exit(1);
408    
409     /* NOT REACHED */
410     return NULL;
411     }
412    
413 michael 952 static char *
414     make_bf_salt(int rounds, int length)
415 adx 30 {
416     static char salt[31];
417     char tbuf[3];
418 michael 952
419 adx 30 if (length > 22)
420     {
421     printf("BlowFish salt length too long\n");
422     exit(0);
423     }
424 michael 952
425 michael 2222 snprintf(tbuf, sizeof(tbuf), "%02d", rounds);
426     snprintf(salt, sizeof(salt), "$2a$%s$", tbuf);
427 michael 1578
428 adx 30 generate_random_salt(&salt[7], length);
429 michael 952
430 michael 1578 salt[length + 7] = '$';
431     salt[length + 8] = '\0';
432    
433 adx 30 return salt;
434     }
435    
436 michael 952 static char *
437     generate_poor_salt(char *salt, int length)
438 adx 30 {
439     int i;
440 michael 952
441 adx 30 srandom(time(NULL));
442 michael 952
443     for (i = 0; i < length; i++)
444 adx 30 salt[i] = saltChars[random() % 64];
445 michael 952
446     return salt;
447 adx 30 }
448    
449 michael 952 static char *
450     generate_random_salt(char *salt, int length)
451 adx 30 {
452     char *buf;
453     int fd, i;
454 michael 952
455     if ((fd = open("/dev/random", O_RDONLY)) < 0)
456     return generate_poor_salt(salt, length);
457    
458 adx 30 buf = calloc(1, length);
459 michael 952
460     if (read(fd, buf, length) != length)
461 adx 30 {
462 michael 1578 close(fd);
463 adx 30 free(buf);
464 michael 1578
465 michael 952 return generate_poor_salt(salt, length);
466 adx 30 }
467 michael 952
468     for (i = 0; i < length; i++)
469 adx 30 salt[i] = saltChars[abs(buf[i]) % 64];
470 michael 952
471 michael 1578 close(fd);
472 adx 30 free(buf);
473 michael 952
474     return salt;
475 adx 30 }
476    
477 michael 952 static void
478     full_usage(void)
479 adx 30 {
480 michael 952 printf("mkpasswd [-5|-6|-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
481 adx 30 printf(" [-R rawsalt]\n");
482 michael 1272 printf("-5 Generate a SHA-256 password\n");
483     printf("-6 Generate a SHA-512 password\n");
484 adx 30 printf("-m Generate an MD5 password\n");
485     printf("-d Generate a DES password\n");
486     printf("-b Generate a BlowFish password\n");
487     printf("-e Generate an Extended DES password\n");
488     printf("-l Specify a length for a random MD5 or BlowFish salt\n");
489     printf("-r Specify a number of rounds for a BlowFish or Extended DES password\n");
490     printf(" BlowFish: default 4, no more than 6 recommended\n");
491     printf(" Extended DES: default 25\n");
492 michael 952 printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for SHA/MD5,\n");
493 adx 30 printf(" up to 22 for BlowFish, and 4 for Extended DES\n");
494     printf("-R Specify a raw salt passed directly to crypt()\n");
495     printf("-p Specify a plaintext password to use\n");
496     printf("Example: mkpasswd -m -s 3dr -p test\n");
497     exit(0);
498     }
499    
500 michael 952 static void
501     brief_usage(void)
502 adx 30 {
503     printf("mkpasswd - password hash generator\n");
504     printf("Standard DES: mkpasswd [-d] [-s salt] [-p plaintext]\n");
505     printf("Extended DES: mkpasswd -e [-r rounds] [-s salt] [-p plaintext]\n");
506 michael 1272 printf(" SHA-256: mkpasswd -5 [-l saltlength] [-s salt] [-p plaintext]\n");
507     printf(" SHA-512: mkpasswd -6 [-l saltlength] [-s salt] [-p plaintext]\n");
508 adx 30 printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n");
509     printf(" BlowFish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n");
510     printf(" [-p plaintext]\n");
511     printf(" Raw: mkpasswd -R <rawsalt> [-p plaintext]\n");
512     printf("Use -h for full usage\n");
513     exit(0);
514     }

Properties

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