/[svn]/ircd-hybrid/branches/8.2.x/tools/mkpasswd.c
ViewVC logotype

Annotation of /ircd-hybrid/branches/8.2.x/tools/mkpasswd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10208 - (hide annotations)
Mon Jul 18 05:42:11 2022 UTC (8 months ago) by michael
File MIME type: text/x-chdr
File size: 8361 byte(s)
- mkpasswd.c: make sure plaintext isn't NULL when passing it to crypt()

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     ** Modernization, getopt, etc for the Hybrid IRCD team
6     ** by W. Campbell
7 michael 5874 **
8     ** /dev/random for salt generation added by
9 adx 30 ** Aaron Sethman <androsyn@ratbox.org>
10     **
11 knight 31 ** $Id$
12 adx 30 */
13 michael 1578
14 adx 30 #include <stdio.h>
15     #include <string.h>
16     #include <stdlib.h>
17     #include <time.h>
18 michael 9957 #define _XOPEN_SOURCE
19 adx 30 #include <unistd.h>
20     #include <fcntl.h>
21    
22 michael 6583 enum
23     {
24 michael 8436 FLAG_SHA256 = 1 << 0,
25     FLAG_SHA512 = 1 << 1,
26     FLAG_BLOWFISH = 1 << 2,
27     FLAG_RAW = 1 << 3,
28     FLAG_SALT = 1 << 4,
29     FLAG_LENGTH = 1 << 5,
30     FLAG_ROUNDS = 1 << 6,
31     FLAG_PASS = 1 << 7,
32 michael 6583 };
33 adx 30
34 michael 6244 static const char *make_sha256_salt(unsigned int);
35     static const char *make_sha256_salt_para(const char *);
36     static const char *make_sha512_salt(unsigned int);
37     static const char *make_sha512_salt_para(const char *);
38 michael 6583 static const char *make_blowfish_salt(unsigned int, unsigned int);
39     static const char *make_blowfish_salt_para(unsigned int, const char *);
40 michael 6244 static const char *generate_random_salt(char *, unsigned int);
41     static const char *generate_poor_salt(char *, unsigned int);
42 adx 30 static void full_usage(void);
43     static void brief_usage(void);
44    
45     static const char saltChars[] =
46 michael 6583 "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
47 adx 30 /* 0 .. 63, ascii - 64 */
48    
49 michael 952 int
50     main(int argc, char *argv[])
51 adx 30 {
52     const char *plaintext = NULL;
53 michael 3073 const char *saltpara = NULL;
54     const char *salt = NULL;
55 michael 6241 const char *ret = NULL;
56 michael 6583 unsigned int flag = 0;
57 adx 30 int length = 0; /* Not Set */
58     int rounds = 0; /* Not set, since extended DES needs 25 and blowfish needs
59     ** 4 by default, a side effect of this being the encryption
60     ** type parameter must be specified before the rounds
61     ** parameter.
62     */
63    
64 michael 6589 for (int c = 0; (c = getopt(argc, argv, "56br:h?l:s:p:R:")) != -1; )
65 adx 30 {
66 michael 952 switch (c)
67 adx 30 {
68 michael 952 case '5':
69     flag |= FLAG_SHA256;
70     break;
71     case '6':
72     flag |= FLAG_SHA512;
73     break;
74 adx 30 case 'b':
75     flag |= FLAG_BLOWFISH;
76     rounds = 4;
77     break;
78     case 'l':
79     flag |= FLAG_LENGTH;
80 michael 6243 if ((length = atoi(optarg)) < 0)
81     length = 0;
82 adx 30 break;
83     case 'r':
84     flag |= FLAG_ROUNDS;
85 michael 6243 if ((rounds = atoi(optarg)) < 0)
86     rounds = 0;
87 adx 30 break;
88     case 's':
89     flag |= FLAG_SALT;
90     saltpara = optarg;
91     break;
92     case 'p':
93     flag |= FLAG_PASS;
94     plaintext = optarg;
95     break;
96     case 'R':
97     flag |= FLAG_RAW;
98     saltpara = optarg;
99     break;
100     case 'h':
101     full_usage();
102     /* NOT REACHED */
103     break;
104     case '?':
105     brief_usage();
106     /* NOT REACHED */
107     break;
108     default:
109     printf("Invalid Option: -%c\n", c);
110     break;
111     }
112     }
113    
114 michael 6583 if (flag & FLAG_SHA256)
115 adx 30 {
116 michael 952 if (length == 0)
117     length = 16;
118 michael 6589
119 michael 952 if (flag & FLAG_SALT)
120     salt = make_sha256_salt_para(saltpara);
121     else
122     salt = make_sha256_salt(length);
123     }
124     else if (flag & FLAG_SHA512)
125     {
126     if (length == 0)
127     length = 16;
128 michael 6589
129 michael 952 if (flag & FLAG_SALT)
130     salt = make_sha512_salt_para(saltpara);
131     else
132     salt = make_sha512_salt(length);
133     }
134 adx 30 else if (flag & FLAG_BLOWFISH)
135     {
136     if (length == 0)
137     length = 22;
138 michael 6589
139 adx 30 if (flag & FLAG_SALT)
140 michael 6583 salt = make_blowfish_salt_para(rounds, saltpara);
141 adx 30 else
142 michael 6583 salt = make_blowfish_salt(rounds, length);
143 adx 30 }
144     else if (flag & FLAG_RAW)
145     salt = saltpara;
146 michael 6589 else
147 adx 30 {
148 michael 6589 printf("No hashing algorithm specified\n");
149     exit(EXIT_FAILURE);
150 adx 30 }
151    
152     if (flag & FLAG_PASS)
153     {
154 michael 10208 if (plaintext == NULL)
155     {
156 adx 30 printf("Please enter a valid password\n");
157 michael 10208 exit(EXIT_FAILURE);
158     }
159 adx 30 }
160 michael 10208 else if ((plaintext = getpass("plaintext: ")) == NULL)
161     {
162     printf("getpass() failed\n");
163     exit(EXIT_FAILURE);
164     }
165 adx 30
166 michael 6241 if ((ret = crypt(plaintext, salt)))
167     printf("%s\n", ret);
168     else
169     printf("crypt() failed: invalid or unsupported setting\n");
170    
171 adx 30 return 0;
172     }
173    
174 michael 6244 static const char *
175 michael 1578 make_sha256_salt_para(const char *saltpara)
176 adx 30 {
177     static char salt[21];
178 michael 952
179 michael 6244 if (saltpara && strlen(saltpara) <= 16)
180 adx 30 {
181 michael 2222 snprintf(salt, sizeof(salt), "$5$%s$", saltpara);
182 michael 952 return salt;
183     }
184    
185 michael 6244 printf("Invalid salt, please use up to 16 random alphanumeric characters\n");
186 michael 6588 exit(EXIT_FAILURE);
187 michael 952
188     /* NOT REACHED */
189     return NULL;
190     }
191    
192 michael 6244 static const char *
193     make_sha256_salt(unsigned int length)
194 michael 952 {
195     static char salt[21];
196    
197     if (length > 16)
198     {
199 michael 3125 printf("SHA-256 salt length too long\n");
200 michael 6588 exit(EXIT_FAILURE);
201 michael 952 }
202    
203     salt[0] = '$';
204     salt[1] = '5';
205     salt[2] = '$';
206 michael 1578
207 michael 952 generate_random_salt(&salt[3], length);
208 michael 1578
209 michael 952 salt[length + 3] = '$';
210     salt[length + 4] = '\0';
211    
212     return salt;
213     }
214    
215 michael 6244 static const char *
216 michael 1578 make_sha512_salt_para(const char *saltpara)
217 michael 952 {
218     static char salt[21];
219    
220 michael 6244 if (saltpara && strlen(saltpara) <= 16)
221 michael 952 {
222 michael 2222 snprintf(salt, sizeof(salt), "$6$%s$", saltpara);
223 michael 952 return salt;
224     }
225    
226 michael 6244 printf("Invalid salt, please use up to 16 random alphanumeric characters\n");
227 michael 6588 exit(EXIT_FAILURE);
228 michael 952
229     /* NOT REACHED */
230     return NULL;
231     }
232    
233 michael 6244 static const char *
234     make_sha512_salt(unsigned int length)
235 michael 952 {
236     static char salt[21];
237    
238     if (length > 16)
239     {
240 michael 3125 printf("SHA-512 salt length too long\n");
241 michael 6588 exit(EXIT_FAILURE);
242 michael 952 }
243    
244     salt[0] = '$';
245     salt[1] = '6';
246     salt[2] = '$';
247 michael 1578
248 michael 952 generate_random_salt(&salt[3], length);
249 michael 1578
250 michael 952 salt[length + 3] = '$';
251     salt[length + 4] = '\0';
252    
253     return salt;
254     }
255    
256 michael 6244 static const char *
257 michael 6583 make_blowfish_salt_para(unsigned int rounds, const char *saltpara)
258 adx 30 {
259     static char salt[31];
260     char tbuf[3];
261 michael 952
262 michael 6572 if (saltpara && strlen(saltpara) >= 22)
263 adx 30 {
264 michael 6244 snprintf(tbuf, sizeof(tbuf), "%02u", rounds);
265 michael 2222 snprintf(salt, sizeof(salt), "$2a$%s$%s$", tbuf, saltpara);
266 adx 30 return salt;
267     }
268 michael 952
269 michael 6572 printf("Invalid salt, please use at least 22 random alphanumeric characters\n");
270 michael 6588 exit(EXIT_FAILURE);
271 adx 30
272     /* NOT REACHED */
273     return NULL;
274     }
275    
276 michael 6244 static const char *
277 michael 6583 make_blowfish_salt(unsigned int rounds, unsigned int length)
278 adx 30 {
279     static char salt[31];
280     char tbuf[3];
281 michael 952
282 michael 6572 if (length < 22)
283 adx 30 {
284 michael 6572 printf("Blowfish salt length too short\n");
285 michael 6588 exit(EXIT_FAILURE);
286 adx 30 }
287 michael 952
288 michael 6244 snprintf(tbuf, sizeof(tbuf), "%02u", rounds);
289 michael 2222 snprintf(salt, sizeof(salt), "$2a$%s$", tbuf);
290 michael 1578
291 adx 30 generate_random_salt(&salt[7], length);
292 michael 952
293 michael 1578 salt[length + 7] = '$';
294     salt[length + 8] = '\0';
295    
296 adx 30 return salt;
297     }
298    
299 michael 6244 static const char *
300     generate_poor_salt(char *salt, unsigned int length)
301 adx 30 {
302     srandom(time(NULL));
303 michael 952
304 michael 6244 for (unsigned int i = 0; i < length; ++i)
305 adx 30 salt[i] = saltChars[random() % 64];
306 michael 952
307     return salt;
308 adx 30 }
309    
310 michael 6244 static const char *
311     generate_random_salt(char *salt, unsigned int length)
312 adx 30 {
313     char *buf;
314 michael 6244 int fd;
315 michael 952
316     if ((fd = open("/dev/random", O_RDONLY)) < 0)
317     return generate_poor_salt(salt, length);
318    
319 adx 30 buf = calloc(1, length);
320 michael 952
321 michael 7329 if (read(fd, buf, length) != (ssize_t)length)
322 adx 30 {
323 michael 1578 close(fd);
324 adx 30 free(buf);
325 michael 1578
326 michael 952 return generate_poor_salt(salt, length);
327 adx 30 }
328 michael 952
329 michael 6244 for (unsigned int i = 0; i < length; ++i)
330 adx 30 salt[i] = saltChars[abs(buf[i]) % 64];
331 michael 952
332 michael 1578 close(fd);
333 adx 30 free(buf);
334 michael 952
335     return salt;
336 adx 30 }
337    
338 michael 952 static void
339     full_usage(void)
340 adx 30 {
341 michael 6589 printf("mkpasswd [-5|-6|-b] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
342 adx 30 printf(" [-R rawsalt]\n");
343 michael 1272 printf("-5 Generate a SHA-256 password\n");
344     printf("-6 Generate a SHA-512 password\n");
345 michael 6583 printf("-b Generate a Blowfish password\n");
346 michael 6589 printf("-l Specify a length for a random SHA-256/SHA-512 or Blowfish salt\n");
347 michael 6583 printf("-r Specify a number of rounds for a Blowfish password;\n");
348     printf(" default is 4, no more than 6 recommended\n");
349 michael 6589 printf("-s Specify a salt, up to 16 alphanumeric characters for SHA-256/SHA-512,\n");
350 michael 6583 printf(" and at least 22 for Blowfish\n");
351 adx 30 printf("-R Specify a raw salt passed directly to crypt()\n");
352     printf("-p Specify a plaintext password to use\n");
353 michael 6583 printf("Example: mkpasswd -6 -s 3dr -p test\n");
354 michael 6588 exit(EXIT_SUCCESS);
355 adx 30 }
356    
357 michael 952 static void
358     brief_usage(void)
359 adx 30 {
360     printf("mkpasswd - password hash generator\n");
361 michael 6583 printf(" SHA-256: mkpasswd -5 [-l saltlength] [-s salt] [-p plaintext]\n");
362     printf(" SHA-512: mkpasswd -6 [-l saltlength] [-s salt] [-p plaintext]\n");
363 michael 6589 printf("Blowfish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt] [-p plaintext]\n");
364 michael 6583 printf(" Raw: mkpasswd -R <rawsalt> [-p plaintext]\n");
365 adx 30 printf("Use -h for full usage\n");
366 michael 6588 exit(EXIT_SUCCESS);
367 adx 30 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.30