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

Properties

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