ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/tools/mkpasswd.c
Revision: 10208
Committed: Mon Jul 18 05:42:11 2022 UTC (20 months, 4 weeks ago) by michael
Content type: text/x-csrc
File size: 8361 byte(s)
Log Message:
- mkpasswd.c: make sure plaintext isn't NULL when passing it to crypt()

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

Properties

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