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.
5
** md5 patch by W. Campbell <wcampbel@botbay.net>
6
** Modernization, getopt, etc for the Hybrid IRCD team
9
** /dev/random for salt generation added by
10
** Aaron Sethman <androsyn@ratbox.org>
12
** $Id: mkpasswd.c 26439 2009-02-01 15:27:24Z jilles $
20
#include "ratbox_lib.h"
25
#define FLAG_MD5 0x00000001
26
#define FLAG_DES 0x00000002
27
#define FLAG_SALT 0x00000004
28
#define FLAG_PASS 0x00000008
29
#define FLAG_LENGTH 0x00000010
30
#define FLAG_BLOWFISH 0x00000020
31
#define FLAG_ROUNDS 0x00000040
32
#define FLAG_EXT 0x00000080
33
#define FLAG_SHA256 0x00000100
34
#define FLAG_SHA512 0x00000200
37
static char *make_des_salt(void);
38
static char *make_ext_salt(int);
39
static char *make_ext_salt_para(int, char *);
40
static char *make_md5_salt(int);
41
static char *make_md5_salt_para(char *);
42
static char *make_sha256_salt(int);
43
static char *make_sha256_salt_para(char *);
44
static char *make_sha512_salt(int);
45
static char *make_sha512_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);
52
static void full_usage(void);
53
static void brief_usage(void);
55
static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
56
/* 0 .. 63, ascii - 64 */
67
static char getpassbuf[PASS_MAX + 1];
70
getpass(const char *prompt)
75
memset(getpassbuf, sizeof(getpassbuf), 0);
76
fputs(prompt, stderr);
90
fputs("\r\n", stderr);
98
main(int argc, char *argv[])
100
char *plaintext = NULL;
102
char *saltpara = NULL;
105
int length = 0; /* Not Set */
106
int rounds = 0; /* Not set, since extended DES needs 25 and blowfish needs
107
** 4 by default, a side effect of this being the encryption
108
** type parameter must be specified before the rounds
112
while((c = getopt(argc, argv, "xymdber:h?l:s:p:")) != -1)
123
flag |= FLAG_BLOWFISH;
132
length = atoi(optarg);
136
rounds = atoi(optarg);
161
printf("Invalid Option: -%c\n", c);
166
if(flag & FLAG_BLOWFISH)
171
salt = make_bf_salt_para(rounds, saltpara);
173
salt = make_bf_salt(rounds, length);
175
else if(flag & FLAG_SHA256)
180
salt = make_sha256_salt_para(saltpara);
182
salt = make_sha256_salt(length);
184
else if(flag & FLAG_SHA512)
189
salt = make_sha512_salt_para(saltpara);
191
salt = make_sha512_salt(length);
193
else if(flag & FLAG_EXT)
195
/* XXX - rounds needs to be done */
198
if((strlen(saltpara) == 4))
200
salt = make_ext_salt_para(rounds, saltpara);
204
printf("Invalid salt, please enter 4 alphanumeric characters\n");
210
salt = make_ext_salt(rounds);
213
else if (flag & FLAG_DES)
217
if((strlen(saltpara) == 2))
223
printf("Invalid salt, please enter 2 alphanumeric characters\n");
229
salt = make_des_salt();
237
salt = make_md5_salt_para(saltpara);
239
salt = make_md5_salt(length);
245
printf("Please enter a valid password\n");
249
plaintext = getpass("plaintext: ");
252
printf("%s\n", rb_crypt(plaintext, salt));
260
generate_random_salt(salt, 2);
266
int_to_base64(int value)
271
for(i = 0; i < 4; i++)
273
buf[i] = saltChars[value & 63];
274
value >>= 6; /* Right shifting 6 places is the same as dividing by 64 */
277
buf[i] = '\0'; /* not REALLY needed as it's static, and thus initialized
284
make_ext_salt(int rounds)
286
static char salt[10];
288
sprintf(salt, "_%s", int_to_base64(rounds));
289
generate_random_salt(&salt[5], 4);
295
make_ext_salt_para(int rounds, char *saltpara)
297
static char salt[10];
299
sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara);
304
make_md5_salt_para(char *saltpara)
306
static char salt[21];
307
if(saltpara && (strlen(saltpara) <= 16))
309
/* sprintf used because of portability requirements, the length
310
** is checked above, so it should not be too much of a concern
312
sprintf(salt, "$1$%s$", saltpara);
315
printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
323
make_md5_salt(int length)
325
static char salt[21];
328
printf("MD5 salt length too long\n");
334
generate_random_salt(&salt[3], length);
335
salt[length + 3] = '$';
336
salt[length + 4] = '\0';
341
make_sha256_salt_para(char *saltpara)
343
static char salt[21];
344
if(saltpara && (strlen(saltpara) <= 16))
346
/* sprintf used because of portability requirements, the length
347
** is checked above, so it should not be too much of a concern
349
sprintf(salt, "$5$%s$", saltpara);
352
printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
360
make_sha512_salt_para(char *saltpara)
362
static char salt[21];
363
if(saltpara && (strlen(saltpara) <= 16))
365
/* sprintf used because of portability requirements, the length
366
** is checked above, so it should not be too much of a concern
368
sprintf(salt, "$6$%s$", saltpara);
371
printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
380
make_sha256_salt(int length)
382
static char salt[21];
385
printf("SHA256 salt length too long\n");
391
generate_random_salt(&salt[3], length);
392
salt[length + 3] = '$';
393
salt[length + 4] = '\0';
398
make_sha512_salt(int length)
400
static char salt[21];
403
printf("SHA512 salt length too long\n");
409
generate_random_salt(&salt[3], length);
410
salt[length + 3] = '$';
411
salt[length + 4] = '\0';
416
make_bf_salt_para(int rounds, char *saltpara)
418
static char salt[31];
420
if(saltpara && (strlen(saltpara) <= 22))
422
/* sprintf used because of portability requirements, the length
423
** is checked above, so it should not be too much of a concern
425
sprintf(tbuf, "%02d", rounds);
426
sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
429
printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
437
make_bf_salt(int rounds, int length)
439
static char salt[31];
443
printf("BlowFish salt length too long\n");
446
sprintf(tbuf, "%02d", rounds);
447
sprintf(salt, "$2a$%s$", tbuf);
448
generate_random_salt(&salt[7], length);
449
salt[length + 7] = '$';
450
salt[length + 8] = '\0';
455
generate_poor_salt(char *salt, int length)
459
for(i = 0; i < length; i++)
461
salt[i] = saltChars[rand() % 64];
467
generate_random_salt(char *salt, int length)
471
if((fd = open("/dev/random", O_RDONLY)) < 0)
473
return (generate_poor_salt(salt, length));
475
buf = calloc(1, length);
476
if(read(fd, buf, length) != length)
479
return (generate_poor_salt(salt, length));
482
for(i = 0; i < length; i++)
484
salt[i] = saltChars[abs(buf[i]) % 64];
493
printf("mkpasswd [-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
494
printf("-x Generate a SHA256 password\n");
495
printf("-y Generate a SHA512 password\n");
496
printf("-m Generate an MD5 password\n");
497
printf("-d Generate a DES password\n");
498
printf("-b Generate a BlowFish password\n");
499
printf("-e Generate an Extended DES password\n");
500
printf("-l Specify a length for a random MD5 or BlowFish salt\n");
501
printf("-r Specify a number of rounds for a BlowFish or Extended DES password\n");
502
printf(" BlowFish: default 4, no more than 6 recommended\n");
503
printf(" Extended DES: default 25\n");
504
printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for MD5,\n");
505
printf(" up to 22 for BlowFish, and 4 for Extended DES\n");
506
printf("-p Specify a plaintext password to use\n");
507
printf("Example: mkpasswd -m -s 3dr -p test\n");
514
printf("mkpasswd - password hash generator\n");
515
printf("Standard DES: mkpasswd [-d] [-s salt] [-p plaintext]\n");
516
printf("Extended DES: mkpasswd -e [-r rounds] [-s salt] [-p plaintext]\n");
517
printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n");
518
printf(" BlowFish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n");
519
printf(" [-p plaintext]\n");
520
printf("Use -h for full usage\n");