ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/tools/mkpasswd.c
Revision: 9957
Committed: Sun May 23 15:13:15 2021 UTC (2 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 8240 byte(s)
Log Message:
- mkpasswd.c: define _XOPEN_SOURCE for glibc 2.27 and below

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)
155 printf("Please enter a valid password\n");
156 }
157 else
158 plaintext = getpass("plaintext: ");
159
160 if ((ret = crypt(plaintext, salt)))
161 printf("%s\n", ret);
162 else
163 printf("crypt() failed: invalid or unsupported setting\n");
164
165 return 0;
166 }
167
168 static const char *
169 make_sha256_salt_para(const char *saltpara)
170 {
171 static char salt[21];
172
173 if (saltpara && strlen(saltpara) <= 16)
174 {
175 snprintf(salt, sizeof(salt), "$5$%s$", saltpara);
176 return salt;
177 }
178
179 printf("Invalid salt, please use up to 16 random alphanumeric characters\n");
180 exit(EXIT_FAILURE);
181
182 /* NOT REACHED */
183 return NULL;
184 }
185
186 static const char *
187 make_sha256_salt(unsigned int length)
188 {
189 static char salt[21];
190
191 if (length > 16)
192 {
193 printf("SHA-256 salt length too long\n");
194 exit(EXIT_FAILURE);
195 }
196
197 salt[0] = '$';
198 salt[1] = '5';
199 salt[2] = '$';
200
201 generate_random_salt(&salt[3], length);
202
203 salt[length + 3] = '$';
204 salt[length + 4] = '\0';
205
206 return salt;
207 }
208
209 static const char *
210 make_sha512_salt_para(const char *saltpara)
211 {
212 static char salt[21];
213
214 if (saltpara && strlen(saltpara) <= 16)
215 {
216 snprintf(salt, sizeof(salt), "$6$%s$", saltpara);
217 return salt;
218 }
219
220 printf("Invalid salt, please use up to 16 random alphanumeric characters\n");
221 exit(EXIT_FAILURE);
222
223 /* NOT REACHED */
224 return NULL;
225 }
226
227 static const char *
228 make_sha512_salt(unsigned int length)
229 {
230 static char salt[21];
231
232 if (length > 16)
233 {
234 printf("SHA-512 salt length too long\n");
235 exit(EXIT_FAILURE);
236 }
237
238 salt[0] = '$';
239 salt[1] = '6';
240 salt[2] = '$';
241
242 generate_random_salt(&salt[3], length);
243
244 salt[length + 3] = '$';
245 salt[length + 4] = '\0';
246
247 return salt;
248 }
249
250 static const char *
251 make_blowfish_salt_para(unsigned int rounds, const char *saltpara)
252 {
253 static char salt[31];
254 char tbuf[3];
255
256 if (saltpara && strlen(saltpara) >= 22)
257 {
258 snprintf(tbuf, sizeof(tbuf), "%02u", rounds);
259 snprintf(salt, sizeof(salt), "$2a$%s$%s$", tbuf, saltpara);
260 return salt;
261 }
262
263 printf("Invalid salt, please use at least 22 random alphanumeric characters\n");
264 exit(EXIT_FAILURE);
265
266 /* NOT REACHED */
267 return NULL;
268 }
269
270 static const char *
271 make_blowfish_salt(unsigned int rounds, unsigned int length)
272 {
273 static char salt[31];
274 char tbuf[3];
275
276 if (length < 22)
277 {
278 printf("Blowfish salt length too short\n");
279 exit(EXIT_FAILURE);
280 }
281
282 snprintf(tbuf, sizeof(tbuf), "%02u", rounds);
283 snprintf(salt, sizeof(salt), "$2a$%s$", tbuf);
284
285 generate_random_salt(&salt[7], length);
286
287 salt[length + 7] = '$';
288 salt[length + 8] = '\0';
289
290 return salt;
291 }
292
293 static const char *
294 generate_poor_salt(char *salt, unsigned int length)
295 {
296 srandom(time(NULL));
297
298 for (unsigned int i = 0; i < length; ++i)
299 salt[i] = saltChars[random() % 64];
300
301 return salt;
302 }
303
304 static const char *
305 generate_random_salt(char *salt, unsigned int length)
306 {
307 char *buf;
308 int fd;
309
310 if ((fd = open("/dev/random", O_RDONLY)) < 0)
311 return generate_poor_salt(salt, length);
312
313 buf = calloc(1, length);
314
315 if (read(fd, buf, length) != (ssize_t)length)
316 {
317 close(fd);
318 free(buf);
319
320 return generate_poor_salt(salt, length);
321 }
322
323 for (unsigned int i = 0; i < length; ++i)
324 salt[i] = saltChars[abs(buf[i]) % 64];
325
326 close(fd);
327 free(buf);
328
329 return salt;
330 }
331
332 static void
333 full_usage(void)
334 {
335 printf("mkpasswd [-5|-6|-b] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
336 printf(" [-R rawsalt]\n");
337 printf("-5 Generate a SHA-256 password\n");
338 printf("-6 Generate a SHA-512 password\n");
339 printf("-b Generate a Blowfish password\n");
340 printf("-l Specify a length for a random SHA-256/SHA-512 or Blowfish salt\n");
341 printf("-r Specify a number of rounds for a Blowfish password;\n");
342 printf(" default is 4, no more than 6 recommended\n");
343 printf("-s Specify a salt, up to 16 alphanumeric characters for SHA-256/SHA-512,\n");
344 printf(" and at least 22 for Blowfish\n");
345 printf("-R Specify a raw salt passed directly to crypt()\n");
346 printf("-p Specify a plaintext password to use\n");
347 printf("Example: mkpasswd -6 -s 3dr -p test\n");
348 exit(EXIT_SUCCESS);
349 }
350
351 static void
352 brief_usage(void)
353 {
354 printf("mkpasswd - password hash generator\n");
355 printf(" SHA-256: mkpasswd -5 [-l saltlength] [-s salt] [-p plaintext]\n");
356 printf(" SHA-512: mkpasswd -6 [-l saltlength] [-s salt] [-p plaintext]\n");
357 printf("Blowfish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt] [-p plaintext]\n");
358 printf(" Raw: mkpasswd -R <rawsalt> [-p plaintext]\n");
359 printf("Use -h for full usage\n");
360 exit(EXIT_SUCCESS);
361 }

Properties

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