~ubuntu-branches/ubuntu/trusty/charybdis/trusty-proposed

« back to all changes in this revision

Viewing changes to tools/mkpasswd.c

  • Committer: Package Import Robot
  • Author(s): Antoine Beaupré
  • Date: 2011-11-10 23:07:37 UTC
  • Revision ID: package-import@ubuntu.com-20111110230737-kqo6qsglp5oh02hr
Tags: upstream-3.3.0
Import upstream version 3.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: mkpasswd.c 26439 2009-02-01 15:27:24Z jilles $
 
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
#include "ratbox_lib.h"
 
21
#ifndef __MINGW32__
 
22
#include <pwd.h>
 
23
#endif
 
24
 
 
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
 
35
 
 
36
 
 
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);
 
51
 
 
52
static void full_usage(void);
 
53
static void brief_usage(void);
 
54
 
 
55
static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
56
       /* 0 .. 63, ascii - 64 */
 
57
 
 
58
extern char *optarg;
 
59
 
 
60
 
 
61
#ifdef __MINGW32__
 
62
#include <conio.h>
 
63
#ifdef PASS_MAX
 
64
#undef PASS_MAX
 
65
#endif
 
66
#define PASS_MAX 256
 
67
static char getpassbuf[PASS_MAX + 1];
 
68
 
 
69
static char *
 
70
getpass(const char *prompt)
 
71
{
 
72
        int c;
 
73
        int i = 0;
 
74
 
 
75
        memset(getpassbuf, sizeof(getpassbuf), 0);
 
76
        fputs(prompt, stderr);
 
77
        for(;;)
 
78
        {
 
79
                c = _getch();
 
80
                if(c == '\r')
 
81
                {
 
82
                        getpassbuf[i] = '\0';
 
83
                        break;
 
84
                }
 
85
                else if(i < PASS_MAX)
 
86
                {
 
87
                        getpassbuf[i++] = c;
 
88
                }
 
89
        }
 
90
        fputs("\r\n", stderr);
 
91
 
 
92
        return getpassbuf;
 
93
}
 
94
#endif
 
95
 
 
96
 
 
97
int
 
98
main(int argc, char *argv[])
 
99
{
 
100
        char *plaintext = NULL;
 
101
        int c;
 
102
        char *saltpara = NULL;
 
103
        char *salt;
 
104
        int flag = 0;
 
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
 
109
                                 ** parameter.
 
110
                                 */
 
111
 
 
112
        while((c = getopt(argc, argv, "xymdber:h?l:s:p:")) != -1)
 
113
        {
 
114
                switch (c)
 
115
                {
 
116
                case 'm':
 
117
                        flag |= FLAG_MD5;
 
118
                        break;
 
119
                case 'd':
 
120
                        flag |= FLAG_DES;
 
121
                        break;
 
122
                case 'b':
 
123
                        flag |= FLAG_BLOWFISH;
 
124
                        rounds = 4;
 
125
                        break;
 
126
                case 'e':
 
127
                        flag |= FLAG_EXT;
 
128
                        rounds = 25;
 
129
                        break;
 
130
                case 'l':
 
131
                        flag |= FLAG_LENGTH;
 
132
                        length = atoi(optarg);
 
133
                        break;
 
134
                case 'r':
 
135
                        flag |= FLAG_ROUNDS;
 
136
                        rounds = atoi(optarg);
 
137
                        break;
 
138
                case 's':
 
139
                        flag |= FLAG_SALT;
 
140
                        saltpara = optarg;
 
141
                        break;
 
142
                case 'p':
 
143
                        flag |= FLAG_PASS;
 
144
                        plaintext = optarg;
 
145
                        break;
 
146
                case 'x':
 
147
                        flag |= FLAG_SHA256;
 
148
                        break;
 
149
                case 'y':
 
150
                        flag |= FLAG_SHA512;
 
151
                        break;
 
152
                case 'h':
 
153
                        full_usage();
 
154
                        /* NOT REACHED */
 
155
                        break;
 
156
                case '?':
 
157
                        brief_usage();
 
158
                        /* NOT REACHED */
 
159
                        break;
 
160
                default:
 
161
                        printf("Invalid Option: -%c\n", c);
 
162
                        break;
 
163
                }
 
164
        }
 
165
 
 
166
        if(flag & FLAG_BLOWFISH)
 
167
        {
 
168
                if(length == 0)
 
169
                        length = 22;
 
170
                if(flag & FLAG_SALT)
 
171
                        salt = make_bf_salt_para(rounds, saltpara);
 
172
                else
 
173
                        salt = make_bf_salt(rounds, length);
 
174
        }
 
175
        else if(flag & FLAG_SHA256)
 
176
        {
 
177
                if(length == 0)
 
178
                        length = 16;
 
179
                if(flag & FLAG_SALT)
 
180
                        salt = make_sha256_salt_para(saltpara);
 
181
                else
 
182
                        salt = make_sha256_salt(length);
 
183
        }
 
184
        else if(flag & FLAG_SHA512)
 
185
        {
 
186
                if(length == 0)
 
187
                        length = 16;
 
188
                if(flag & FLAG_SALT)
 
189
                        salt = make_sha512_salt_para(saltpara);
 
190
                else
 
191
                        salt = make_sha512_salt(length);
 
192
        }
 
193
        else if(flag & FLAG_EXT)
 
194
        {
 
195
                /* XXX - rounds needs to be done */
 
196
                if(flag & FLAG_SALT)
 
197
                {
 
198
                        if((strlen(saltpara) == 4))
 
199
                        {
 
200
                                salt = make_ext_salt_para(rounds, saltpara);
 
201
                        }
 
202
                        else
 
203
                        {
 
204
                                printf("Invalid salt, please enter 4 alphanumeric characters\n");
 
205
                                exit(1);
 
206
                        }
 
207
                }
 
208
                else
 
209
                {
 
210
                        salt = make_ext_salt(rounds);
 
211
                }
 
212
        }
 
213
        else if (flag & FLAG_DES)
 
214
        {
 
215
                if(flag & FLAG_SALT)
 
216
                {
 
217
                        if((strlen(saltpara) == 2))
 
218
                        {
 
219
                                salt = saltpara;
 
220
                        }
 
221
                        else
 
222
                        {
 
223
                                printf("Invalid salt, please enter 2 alphanumeric characters\n");
 
224
                                exit(1);
 
225
                        }
 
226
                }
 
227
                else
 
228
                {
 
229
                        salt = make_des_salt();
 
230
                }
 
231
        }
 
232
        else
 
233
        {
 
234
                if(length == 0)
 
235
                        length = 8;
 
236
                if(flag & FLAG_SALT)
 
237
                        salt = make_md5_salt_para(saltpara);
 
238
                else
 
239
                        salt = make_md5_salt(length);
 
240
        }
 
241
 
 
242
        if(flag & FLAG_PASS)
 
243
        {
 
244
                if(!plaintext)
 
245
                        printf("Please enter a valid password\n");
 
246
        }
 
247
        else
 
248
        {
 
249
                plaintext = getpass("plaintext: ");
 
250
        }
 
251
 
 
252
        printf("%s\n", rb_crypt(plaintext, salt));
 
253
        return 0;
 
254
}
 
255
 
 
256
static char *
 
257
make_des_salt()
 
258
{
 
259
        static char salt[3];
 
260
        generate_random_salt(salt, 2);
 
261
        salt[2] = '\0';
 
262
        return salt;
 
263
}
 
264
 
 
265
char *
 
266
int_to_base64(int value)
 
267
{
 
268
        static char buf[5];
 
269
        int i;
 
270
 
 
271
        for(i = 0; i < 4; i++)
 
272
        {
 
273
                buf[i] = saltChars[value & 63];
 
274
                value >>= 6;    /* Right shifting 6 places is the same as dividing by 64 */
 
275
        }
 
276
 
 
277
        buf[i] = '\0';          /* not REALLY needed as it's static, and thus initialized
 
278
                                 ** to \0.
 
279
                                 */
 
280
        return buf;
 
281
}
 
282
 
 
283
char *
 
284
make_ext_salt(int rounds)
 
285
{
 
286
        static char salt[10];
 
287
 
 
288
        sprintf(salt, "_%s", int_to_base64(rounds));
 
289
        generate_random_salt(&salt[5], 4);
 
290
        salt[9] = '\0';
 
291
        return salt;
 
292
}
 
293
 
 
294
char *
 
295
make_ext_salt_para(int rounds, char *saltpara)
 
296
{
 
297
        static char salt[10];
 
298
 
 
299
        sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara);
 
300
        return salt;
 
301
}
 
302
 
 
303
char *
 
304
make_md5_salt_para(char *saltpara)
 
305
{
 
306
        static char salt[21];
 
307
        if(saltpara && (strlen(saltpara) <= 16))
 
308
        {
 
309
                /* sprintf used because of portability requirements, the length
 
310
                 ** is checked above, so it should not be too much of a concern
 
311
                 */
 
312
                sprintf(salt, "$1$%s$", saltpara);
 
313
                return salt;
 
314
        }
 
315
        printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
 
316
        exit(1);
 
317
 
 
318
        /* NOT REACHED */
 
319
        return NULL;
 
320
}
 
321
 
 
322
char *
 
323
make_md5_salt(int length)
 
324
{
 
325
        static char salt[21];
 
326
        if(length > 16)
 
327
        {
 
328
                printf("MD5 salt length too long\n");
 
329
                exit(0);
 
330
        }
 
331
        salt[0] = '$';
 
332
        salt[1] = '1';
 
333
        salt[2] = '$';
 
334
        generate_random_salt(&salt[3], length);
 
335
        salt[length + 3] = '$';
 
336
        salt[length + 4] = '\0';
 
337
        return salt;
 
338
}
 
339
 
 
340
char *
 
341
make_sha256_salt_para(char *saltpara)
 
342
{
 
343
        static char salt[21];
 
344
        if(saltpara && (strlen(saltpara) <= 16))
 
345
        {
 
346
                /* sprintf used because of portability requirements, the length
 
347
                 ** is checked above, so it should not be too much of a concern
 
348
                 */
 
349
                sprintf(salt, "$5$%s$", saltpara);
 
350
                return salt;
 
351
        }
 
352
        printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
 
353
        exit(1);
 
354
 
 
355
        /* NOT REACHED */
 
356
        return NULL;
 
357
}
 
358
 
 
359
char *
 
360
make_sha512_salt_para(char *saltpara)
 
361
{
 
362
        static char salt[21];
 
363
        if(saltpara && (strlen(saltpara) <= 16))
 
364
        {
 
365
                /* sprintf used because of portability requirements, the length
 
366
                 ** is checked above, so it should not be too much of a concern
 
367
                 */
 
368
                sprintf(salt, "$6$%s$", saltpara);
 
369
                return salt;
 
370
        }
 
371
        printf("Invalid Salt, please use up to 16 random alphanumeric characters\n");
 
372
        exit(1);
 
373
 
 
374
        /* NOT REACHED */
 
375
        return NULL;
 
376
}
 
377
 
 
378
 
 
379
char *
 
380
make_sha256_salt(int length)
 
381
{
 
382
        static char salt[21];
 
383
        if(length > 16)
 
384
        {
 
385
                printf("SHA256 salt length too long\n");
 
386
                exit(0);
 
387
        }
 
388
        salt[0] = '$';
 
389
        salt[1] = '5';
 
390
        salt[2] = '$';
 
391
        generate_random_salt(&salt[3], length);
 
392
        salt[length + 3] = '$';
 
393
        salt[length + 4] = '\0';
 
394
        return salt;
 
395
}
 
396
 
 
397
char *
 
398
make_sha512_salt(int length)
 
399
{
 
400
        static char salt[21];
 
401
        if(length > 16)
 
402
        {
 
403
                printf("SHA512 salt length too long\n");
 
404
                exit(0);
 
405
        }
 
406
        salt[0] = '$';
 
407
        salt[1] = '6';
 
408
        salt[2] = '$';
 
409
        generate_random_salt(&salt[3], length);
 
410
        salt[length + 3] = '$';
 
411
        salt[length + 4] = '\0';
 
412
        return salt;
 
413
}
 
414
 
 
415
char *
 
416
make_bf_salt_para(int rounds, char *saltpara)
 
417
{
 
418
        static char salt[31];
 
419
        char tbuf[3];
 
420
        if(saltpara && (strlen(saltpara) <= 22))
 
421
        {
 
422
                /* sprintf used because of portability requirements, the length
 
423
                 ** is checked above, so it should not be too much of a concern
 
424
                 */
 
425
                sprintf(tbuf, "%02d", rounds);
 
426
                sprintf(salt, "$2a$%s$%s$", tbuf, saltpara);
 
427
                return salt;
 
428
        }
 
429
        printf("Invalid Salt, please use up to 22 random alphanumeric characters\n");
 
430
        exit(1);
 
431
 
 
432
        /* NOT REACHED */
 
433
        return NULL;
 
434
}
 
435
 
 
436
char *
 
437
make_bf_salt(int rounds, int length)
 
438
{
 
439
        static char salt[31];
 
440
        char tbuf[3];
 
441
        if(length > 22)
 
442
        {
 
443
                printf("BlowFish salt length too long\n");
 
444
                exit(0);
 
445
        }
 
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';
 
451
        return salt;
 
452
}
 
453
 
 
454
char *
 
455
generate_poor_salt(char *salt, int length)
 
456
{
 
457
        int i;
 
458
        srand(time(NULL));
 
459
        for(i = 0; i < length; i++)
 
460
        {
 
461
                salt[i] = saltChars[rand() % 64];
 
462
        }
 
463
        return (salt);
 
464
}
 
465
 
 
466
char *
 
467
generate_random_salt(char *salt, int length)
 
468
{
 
469
        char *buf;
 
470
        int fd, i;
 
471
        if((fd = open("/dev/random", O_RDONLY)) < 0)
 
472
        {
 
473
                return (generate_poor_salt(salt, length));
 
474
        }
 
475
        buf = calloc(1, length);
 
476
        if(read(fd, buf, length) != length)
 
477
        {
 
478
                free(buf);
 
479
                return (generate_poor_salt(salt, length));
 
480
        }
 
481
 
 
482
        for(i = 0; i < length; i++)
 
483
        {
 
484
                salt[i] = saltChars[abs(buf[i]) % 64];
 
485
        }
 
486
        free(buf);
 
487
        return (salt);
 
488
}
 
489
 
 
490
void
 
491
full_usage()
 
492
{
 
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");
 
508
        exit(0);
 
509
}
 
510
 
 
511
void
 
512
brief_usage()
 
513
{
 
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");
 
521
        exit(0);
 
522
}