ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/tools/mkpasswd.c
Revision: 6571
Committed: Sun Oct 18 16:58:34 2015 UTC (10 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 11599 byte(s)
Log Message:
- Fixed broken bcrypt on (Open)BSD in conjunction with the -s and -l switches

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

Properties

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