]> jfr.im git - solanum.git/blame - tools/mkpasswd.c
Revert "Accept expired certificates"
[solanum.git] / tools / mkpasswd.c
CommitLineData
212380e3 1/* simple password generator by Nelson Minar (minar@reed.edu)
8522eb3b
EM
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 */
212380e3
AC
12#include <stdio.h>
13#include <string.h>
14#include <stdlib.h>
15#include <time.h>
16#include <unistd.h>
17#include <fcntl.h>
fe037171 18#include "rb_lib.h"
f1d07f6b 19#include <pwd.h>
212380e3 20
f1d07f6b 21#define FLAG_MD5 0x00000001
8522eb3b
EM
22#define FLAG_SALT 0x00000002
23#define FLAG_PASS 0x00000004
24#define FLAG_LENGTH 0x00000008
25#define FLAG_BLOWFISH 0x00000010
26#define FLAG_ROUNDS 0x00000020
27#define FLAG_SHA256 0x00000040
28#define FLAG_SHA512 0x00000080
29
30
212380e3
AC
31static char *make_md5_salt(int);
32static char *make_md5_salt_para(char *);
f1d07f6b
JT
33static char *make_sha256_salt(int);
34static char *make_sha256_salt_para(char *);
35static char *make_sha512_salt(int);
36static char *make_sha512_salt_para(char *);
212380e3
AC
37static char *make_bf_salt(int, int);
38static char *make_bf_salt_para(int, char *);
212380e3
AC
39static char *generate_random_salt(char *, int);
40static char *generate_poor_salt(char *, int);
41
2cad5415
AJ
42static void full_usage(void) __attribute__((noreturn));
43static void brief_usage(void) __attribute__((noreturn));
212380e3 44
f1d07f6b 45static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
212380e3
AC
46 /* 0 .. 63, ascii - 64 */
47
f1d07f6b
JT
48int
49main(int argc, char *argv[])
212380e3 50{
f1d07f6b
JT
51 char *plaintext = NULL;
52 int c;
53 char *saltpara = NULL;
54 char *salt;
6002ccec 55 char *hashed, *hashed2;
f1d07f6b
JT
56 int flag = 0;
57 int length = 0; /* Not Set */
8522eb3b
EM
58 int rounds = 0; /* Not set, since blowfish needs 4 by default, a side effect
59 * of this being the encryption type parameter must be
60 * specified before the rounds parameter.
f1d07f6b
JT
61 */
62
8522eb3b 63 while((c = getopt(argc, argv, "xymbr:h?l:s:p:")) != -1)
f1d07f6b
JT
64 {
65 switch (c)
66 {
67 case 'm':
68 flag |= FLAG_MD5;
69 break;
f1d07f6b
JT
70 case 'b':
71 flag |= FLAG_BLOWFISH;
72 rounds = 4;
73 break;
f1d07f6b
JT
74 case 'l':
75 flag |= FLAG_LENGTH;
76 length = atoi(optarg);
77 break;
78 case 'r':
79 flag |= FLAG_ROUNDS;
80 rounds = atoi(optarg);
81 break;
82 case 's':
83 flag |= FLAG_SALT;
84 saltpara = optarg;
85 break;
86 case 'p':
87 flag |= FLAG_PASS;
88 plaintext = optarg;
89 break;
90 case 'x':
91 flag |= FLAG_SHA256;
92 break;
93 case 'y':
94 flag |= FLAG_SHA512;
95 break;
96 case 'h':
97 full_usage();
98 /* NOT REACHED */
99 break;
100 case '?':
101 brief_usage();
102 /* NOT REACHED */
103 break;
104 default:
105 printf("Invalid Option: -%c\n", c);
106 break;
107 }
108 }
109
7600b65f
EM
110 if(flag & FLAG_MD5)
111 {
112 if(length == 0)
113 length = 8;
114 if(flag & FLAG_SALT)
115 salt = make_md5_salt_para(saltpara);
116 else
117 salt = make_md5_salt(length);
118 }
119 else if(flag & FLAG_BLOWFISH)
f1d07f6b
JT
120 {
121 if(length == 0)
122 length = 22;
123 if(flag & FLAG_SALT)
124 salt = make_bf_salt_para(rounds, saltpara);
125 else
126 salt = make_bf_salt(rounds, length);
127 }
128 else if(flag & FLAG_SHA256)
129 {
130 if(length == 0)
131 length = 16;
132 if(flag & FLAG_SALT)
133 salt = make_sha256_salt_para(saltpara);
134 else
135 salt = make_sha256_salt(length);
136 }
920cb1dc
AC
137 else
138 {
139 if(length == 0)
7600b65f 140 length = 16;
920cb1dc 141 if(flag & FLAG_SALT)
7600b65f 142 salt = make_sha512_salt_para(saltpara);
920cb1dc 143 else
7600b65f 144 salt = make_sha512_salt(length);
920cb1dc 145 }
f1d07f6b
JT
146
147 if(flag & FLAG_PASS)
148 {
149 if(!plaintext)
011e38be
AI
150 {
151 fprintf(stderr, "Please enter a valid password\n");
152 return 1;
153 }
154
155 hashed = rb_crypt(plaintext, salt);
f1d07f6b
JT
156 }
157 else
158 {
6002ccec
AJ
159 plaintext = getpass("plaintext: ");
160 hashed = rb_crypt(plaintext, salt);
161 if (!hashed)
162 {
163 fprintf(stderr, "rb_crypt() failed\n");
164 return 1;
165 }
166 hashed = strdup(hashed);
167
011e38be 168 plaintext = getpass("again: ");
6002ccec
AJ
169 hashed2 = rb_crypt(plaintext, salt);
170 if (!hashed2)
171 {
172 fprintf(stderr, "rb_crypt() failed\n");
173 return 1;
174 }
011e38be 175
6002ccec 176 if (strcmp(hashed, hashed2) != 0)
011e38be
AI
177 {
178 fprintf(stderr, "Passwords do not match\n");
179 return 1;
180 }
f1d07f6b
JT
181 }
182
011e38be 183 printf("%s\n", hashed);
f1d07f6b 184 return 0;
212380e3
AC
185}
186
f1d07f6b
JT
187char *
188make_md5_salt_para(char *saltpara)
212380e3 189{
f1d07f6b
JT
190 static char salt[21];
191 if(saltpara && (strlen(saltpara) <= 16))
192 {
193 /* sprintf used because of portability requirements, the length
194 ** is checked above, so it should not be too much of a concern
195 */
196 sprintf(salt, "$1$%s$", saltpara);
197 return salt;
198 }
199 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
200 exit(1);
201
202 /* NOT REACHED */
203 return NULL;
212380e3
AC
204}
205
f1d07f6b
JT
206char *
207make_md5_salt(int length)
212380e3 208{
f1d07f6b
JT
209 static char salt[21];
210 if(length > 16)
211 {
212 printf("MD5 salt length too long\n");
213 exit(0);
214 }
215 salt[0] = '$';
216 salt[1] = '1';
217 salt[2] = '$';
218 generate_random_salt(&salt[3], length);
219 salt[length + 3] = '$';
220 salt[length + 4] = '\0';
221 return salt;
212380e3
AC
222}
223
f1d07f6b
JT
224char *
225make_sha256_salt_para(char *saltpara)
212380e3 226{
f1d07f6b
JT
227 static char salt[21];
228 if(saltpara && (strlen(saltpara) <= 16))
229 {
230 /* sprintf used because of portability requirements, the length
231 ** is checked above, so it should not be too much of a concern
232 */
233 sprintf(salt, "$5$%s$", saltpara);
234 return salt;
235 }
236 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
237 exit(1);
238
239 /* NOT REACHED */
240 return NULL;
212380e3
AC
241}
242
f1d07f6b
JT
243char *
244make_sha512_salt_para(char *saltpara)
212380e3 245{
f1d07f6b
JT
246 static char salt[21];
247 if(saltpara && (strlen(saltpara) <= 16))
248 {
249 /* sprintf used because of portability requirements, the length
250 ** is checked above, so it should not be too much of a concern
251 */
252 sprintf(salt, "$6$%s$", saltpara);
253 return salt;
254 }
255 printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
256 exit(1);
257
258 /* NOT REACHED */
259 return NULL;
212380e3
AC
260}
261
f1d07f6b
JT
262
263char *
264make_sha256_salt(int length)
212380e3 265{
f1d07f6b
JT
266 static char salt[21];
267 if(length > 16)
268 {
269 printf("SHA256 salt length too long\n");
270 exit(0);
271 }
272 salt[0] = '$';
273 salt[1] = '5';
274 salt[2] = '$';
275 generate_random_salt(&salt[3], length);
276 salt[length + 3] = '$';
277 salt[length + 4] = '\0';
278 return salt;
279}
280
281char *
282make_sha512_salt(int length)
283{
284 static char salt[21];
285 if(length > 16)
286 {
287 printf("SHA512 salt length too long\n");
288 exit(0);
289 }
290 salt[0] = '$';
291 salt[1] = '6';
292 salt[2] = '$';
293 generate_random_salt(&salt[3], length);
294 salt[length + 3] = '$';
295 salt[length + 4] = '\0';
296 return salt;
297}
298
299char *
300make_bf_salt_para(int rounds, char *saltpara)
301{
302 static char salt[31];
303 char tbuf[3];
304 if(saltpara && (strlen(saltpara) <= 22))
305 {
306 /* sprintf used because of portability requirements, the length
307 ** is checked above, so it should not be too much of a concern
308 */
309 sprintf(tbuf, "%02d", rounds);
310 sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
311 return salt;
312 }
313 printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
314 exit(1);
315
316 /* NOT REACHED */
317 return NULL;
318}
319
320char *
321make_bf_salt(int rounds, int length)
322{
323 static char salt[31];
324 char tbuf[3];
325 if(length > 22)
326 {
69b2e745 327 printf("Blowfish salt length too long\n");
f1d07f6b
JT
328 exit(0);
329 }
330 sprintf(tbuf, "%02d", rounds);
331 sprintf(salt, "$2a$%s$", tbuf);
332 generate_random_salt(&salt[7], length);
333 salt[length + 7] = '$';
334 salt[length + 8] = '\0';
335 return salt;
336}
337
338char *
339generate_poor_salt(char *salt, int length)
340{
341 int i;
342 srand(time(NULL));
343 for(i = 0; i < length; i++)
344 {
345 salt[i] = saltChars[rand() % 64];
346 }
347 return (salt);
348}
349
350char *
351generate_random_salt(char *salt, int length)
352{
353 char *buf;
354 int fd, i;
355 if((fd = open("/dev/random", O_RDONLY)) < 0)
356 {
357 return (generate_poor_salt(salt, length));
358 }
359 buf = calloc(1, length);
360 if(read(fd, buf, length) != length)
361 {
362 free(buf);
363 return (generate_poor_salt(salt, length));
364 }
365
366 for(i = 0; i < length; i++)
367 {
368 salt[i] = saltChars[abs(buf[i]) % 64];
369 }
370 free(buf);
371 return (salt);
212380e3
AC
372}
373
f1d07f6b
JT
374void
375full_usage()
212380e3 376{
8522eb3b 377 printf("mkpasswd [-m|-b|-x|-y] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
f1d07f6b
JT
378 printf("-x Generate a SHA256 password\n");
379 printf("-y Generate a SHA512 password\n");
380 printf("-m Generate an MD5 password\n");
69b2e745 381 printf("-b Generate a Blowfish password\n");
69b2e745 382 printf("-l Specify a length for a random MD5 or Blowfish salt\n");
8522eb3b
EM
383 printf("-r Specify a number of rounds for a Blowfish password\n");
384 printf(" Default 4, no more than 6 recommended\n");
385 printf("-s Specify a salt, up to 16 for MD5, SHA256, and SHA512\n");
386 printf(" up to 22 for Blowfish\n");
f1d07f6b
JT
387 printf("-p Specify a plaintext password to use\n");
388 printf("Example: mkpasswd -m -s 3dr -p test\n");
389 exit(0);
212380e3
AC
390}
391
f1d07f6b
JT
392void
393brief_usage()
212380e3 394{
f1d07f6b 395 printf("mkpasswd - password hash generator\n");
8522eb3b
EM
396 printf(" SHA512: mkpasswd [-y] [-l saltlength] [-s salt] [-p plaintext]\n");
397 printf(" SHA256: mkpasswd -x [-l saltlength] [-s salt] [-p plaintext]\n");
398 printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n");
399 printf("Blowfish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n");
400 printf(" [-p plaintext]\n");
f1d07f6b
JT
401 printf("Use -h for full usage\n");
402 exit(0);
212380e3 403}