]>
Commit | Line | Data |
---|---|---|
7e1b7485 RS |
1 | /* ==================================================================== |
2 | * Copyright (c) 2000-2015 The OpenSSL Project. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in | |
13 | * the documentation and/or other materials provided with the | |
14 | * distribution. | |
15 | * | |
16 | * 3. All advertising materials mentioning features or use of this | |
17 | * software must display the following acknowledgment: | |
18 | * "This product includes software developed by the OpenSSL Project | |
19 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
20 | * | |
21 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
22 | * endorse or promote products derived from this software without | |
23 | * prior written permission. For written permission, please contact | |
24 | * licensing@OpenSSL.org. | |
25 | * | |
26 | * 5. Products derived from this software may not be called "OpenSSL" | |
27 | * nor may "OpenSSL" appear in their names without prior written | |
28 | * permission of the OpenSSL Project. | |
29 | * | |
30 | * 6. Redistributions of any form whatsoever must retain the following | |
31 | * acknowledgment: | |
32 | * "This product includes software developed by the OpenSSL Project | |
33 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
34 | * | |
35 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
36 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
37 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
38 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
39 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
40 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
41 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
42 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
44 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
45 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
46 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
47 | * ==================================================================== | |
48 | */ | |
bb325c7d | 49 | |
cf1b7d96 | 50 | #if defined OPENSSL_NO_MD5 || defined CHARSET_EBCDIC |
1f4643a2 | 51 | # define NO_MD5CRYPT_1 |
3ebf0be1 BM |
52 | #endif |
53 | ||
cf1b7d96 | 54 | #if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1) |
bb325c7d | 55 | |
0f113f3e MC |
56 | # include <string.h> |
57 | ||
58 | # include "apps.h" | |
59 | ||
60 | # include <openssl/bio.h> | |
61 | # include <openssl/err.h> | |
62 | # include <openssl/evp.h> | |
63 | # include <openssl/rand.h> | |
64 | # ifndef OPENSSL_NO_DES | |
65 | # include <openssl/des.h> | |
66 | # endif | |
67 | # ifndef NO_MD5CRYPT_1 | |
68 | # include <openssl/md5.h> | |
69 | # endif | |
70 | ||
0f113f3e MC |
71 | static unsigned const char cov_2char[64] = { |
72 | /* from crypto/des/fcrypt.c */ | |
73 | 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, | |
74 | 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, | |
75 | 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, | |
76 | 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, | |
77 | 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, | |
78 | 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, | |
79 | 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, | |
80 | 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A | |
bb325c7d BM |
81 | }; |
82 | ||
e6e7b5f3 | 83 | static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, |
0f113f3e MC |
84 | char *passwd, BIO *out, int quiet, int table, |
85 | int reverse, size_t pw_maxlen, int usecrypt, int use1, | |
86 | int useapr1); | |
e6e7b5f3 | 87 | |
7e1b7485 RS |
88 | typedef enum OPTION_choice { |
89 | OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, | |
90 | OPT_IN, | |
91 | OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1, | |
92 | OPT_1, OPT_CRYPT, OPT_SALT, OPT_STDIN | |
93 | } OPTION_CHOICE; | |
94 | ||
95 | OPTIONS passwd_options[] = { | |
96 | {"help", OPT_HELP, '-', "Display this summary"}, | |
97 | {"in", OPT_IN, '<', "Pead passwords from file"}, | |
98 | {"noverify", OPT_NOVERIFY, '-', | |
99 | "Never verify when reading password from terminal"}, | |
100 | {"quiet", OPT_QUIET, '-', "No warnings"}, | |
101 | {"table", OPT_TABLE, '-', "Format output as table"}, | |
102 | {"reverse", OPT_REVERSE, '-', "Switch table columns"}, | |
9c3bcfa0 RS |
103 | {"salt", OPT_SALT, 's', "Use provided salt"}, |
104 | {"stdin", OPT_STDIN, '-', "Read passwords from stdin"}, | |
7e1b7485 RS |
105 | # ifndef NO_MD5CRYPT_1 |
106 | {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"}, | |
107 | {"1", OPT_1, '-', "MD5-based password algorithm"}, | |
108 | # endif | |
109 | # ifndef OPENSSL_NO_DES | |
110 | {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"}, | |
111 | # endif | |
7e1b7485 RS |
112 | {NULL} |
113 | }; | |
07fb39c3 | 114 | |
7e1b7485 | 115 | int passwd_main(int argc, char **argv) |
0f113f3e | 116 | { |
7e1b7485 RS |
117 | BIO *in = NULL; |
118 | char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL; | |
119 | char *salt_malloc = NULL, *passwd_malloc = NULL, *prog; | |
120 | OPTION_CHOICE o; | |
121 | int in_stdin = 0, in_noverify = 0, pw_source_defined = 0; | |
0f113f3e | 122 | int passed_salt = 0, quiet = 0, table = 0, reverse = 0; |
7e1b7485 RS |
123 | int ret = 1, usecrypt = 0, use1 = 0, useapr1 = 0; |
124 | size_t passwd_malloc_size = 0, pw_maxlen = 256; | |
125 | ||
126 | prog = opt_init(argc, argv, passwd_options); | |
127 | while ((o = opt_next()) != OPT_EOF) { | |
128 | switch (o) { | |
129 | case OPT_EOF: | |
130 | case OPT_ERR: | |
131 | opthelp: | |
132 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); | |
133 | goto end; | |
134 | case OPT_HELP: | |
135 | opt_help(passwd_options); | |
136 | ret = 0; | |
137 | goto end; | |
138 | case OPT_IN: | |
139 | if (pw_source_defined) | |
140 | goto opthelp; | |
141 | infile = opt_arg(); | |
142 | pw_source_defined = 1; | |
143 | break; | |
144 | case OPT_NOVERIFY: | |
0f113f3e | 145 | in_noverify = 1; |
7e1b7485 RS |
146 | break; |
147 | case OPT_QUIET: | |
0f113f3e | 148 | quiet = 1; |
7e1b7485 RS |
149 | break; |
150 | case OPT_TABLE: | |
0f113f3e | 151 | table = 1; |
7e1b7485 RS |
152 | break; |
153 | case OPT_REVERSE: | |
0f113f3e | 154 | reverse = 1; |
7e1b7485 RS |
155 | break; |
156 | case OPT_1: | |
157 | use1 = 1; | |
158 | break; | |
159 | case OPT_APR1: | |
160 | useapr1 = 1; | |
161 | break; | |
162 | case OPT_CRYPT: | |
163 | usecrypt = 1; | |
164 | break; | |
165 | case OPT_SALT: | |
166 | passed_salt = 1; | |
167 | salt = opt_arg(); | |
168 | break; | |
169 | case OPT_STDIN: | |
170 | if (pw_source_defined) | |
171 | goto opthelp; | |
172 | in_stdin = 1; | |
173 | break; | |
174 | } | |
175 | } | |
176 | argc = opt_num_rest(); | |
177 | argv = opt_rest(); | |
178 | ||
179 | if (*argv) { | |
180 | if (pw_source_defined) | |
181 | goto opthelp; | |
182 | pw_source_defined = 1; | |
183 | passwds = argv; | |
0f113f3e MC |
184 | } |
185 | ||
7e1b7485 RS |
186 | if (!usecrypt && !use1 && !useapr1) { |
187 | /* use default */ | |
0f113f3e | 188 | usecrypt = 1; |
7e1b7485 RS |
189 | } |
190 | if (usecrypt + use1 + useapr1 > 1) { | |
191 | /* conflict */ | |
192 | goto opthelp; | |
193 | } | |
0f113f3e | 194 | |
0f113f3e MC |
195 | # ifdef OPENSSL_NO_DES |
196 | if (usecrypt) | |
7e1b7485 | 197 | goto opthelp; |
0f113f3e MC |
198 | # endif |
199 | # ifdef NO_MD5CRYPT_1 | |
200 | if (use1 || useapr1) | |
7e1b7485 | 201 | goto opthelp; |
0f113f3e MC |
202 | # endif |
203 | ||
7e1b7485 RS |
204 | if (infile && in_stdin) { |
205 | BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog); | |
206 | goto end; | |
0f113f3e MC |
207 | } |
208 | ||
bdd58d98 | 209 | in = bio_open_default(infile, 'r', FORMAT_TEXT); |
7e1b7485 RS |
210 | if (in == NULL) |
211 | goto end; | |
0f113f3e MC |
212 | |
213 | if (usecrypt) | |
214 | pw_maxlen = 8; | |
215 | else if (use1 || useapr1) | |
216 | pw_maxlen = 256; /* arbitrary limit, should be enough for most | |
217 | * passwords */ | |
218 | ||
219 | if (passwds == NULL) { | |
220 | /* no passwords on the command line */ | |
221 | ||
222 | passwd_malloc_size = pw_maxlen + 2; | |
68dc6824 RS |
223 | /* longer than necessary so that we can warn about truncation */ |
224 | passwd = passwd_malloc = | |
225 | app_malloc(passwd_malloc_size, "password buffer"); | |
0f113f3e MC |
226 | } |
227 | ||
228 | if ((in == NULL) && (passwds == NULL)) { | |
229 | /* build a null-terminated list */ | |
230 | static char *passwds_static[2] = { NULL, NULL }; | |
231 | ||
232 | passwds = passwds_static; | |
233 | if (in == NULL) | |
234 | if (EVP_read_pw_string | |
235 | (passwd_malloc, passwd_malloc_size, "Password: ", | |
236 | !(passed_salt || in_noverify)) != 0) | |
7e1b7485 | 237 | goto end; |
0f113f3e MC |
238 | passwds[0] = passwd_malloc; |
239 | } | |
240 | ||
241 | if (in == NULL) { | |
242 | assert(passwds != NULL); | |
243 | assert(*passwds != NULL); | |
244 | ||
245 | do { /* loop over list of passwords */ | |
246 | passwd = *passwds++; | |
7e1b7485 | 247 | if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out, |
0f113f3e MC |
248 | quiet, table, reverse, pw_maxlen, usecrypt, use1, |
249 | useapr1)) | |
7e1b7485 | 250 | goto end; |
0f113f3e MC |
251 | } |
252 | while (*passwds != NULL); | |
253 | } else | |
254 | /* in != NULL */ | |
255 | { | |
256 | int done; | |
257 | ||
258 | assert(passwd != NULL); | |
259 | do { | |
260 | int r = BIO_gets(in, passwd, pw_maxlen + 1); | |
261 | if (r > 0) { | |
262 | char *c = (strchr(passwd, '\n')); | |
263 | if (c != NULL) | |
264 | *c = 0; /* truncate at newline */ | |
265 | else { | |
266 | /* ignore rest of line */ | |
267 | char trash[BUFSIZ]; | |
268 | do | |
269 | r = BIO_gets(in, trash, sizeof trash); | |
270 | while ((r > 0) && (!strchr(trash, '\n'))); | |
271 | } | |
272 | ||
7e1b7485 RS |
273 | if (!do_passwd |
274 | (passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet, | |
275 | table, reverse, pw_maxlen, usecrypt, use1, useapr1)) | |
276 | goto end; | |
0f113f3e MC |
277 | } |
278 | done = (r <= 0); | |
279 | } | |
280 | while (!done); | |
281 | } | |
282 | ret = 0; | |
283 | ||
7e1b7485 | 284 | end: |
0f113f3e | 285 | ERR_print_errors(bio_err); |
b548a1f1 RS |
286 | OPENSSL_free(salt_malloc); |
287 | OPENSSL_free(passwd_malloc); | |
ca3a82c3 | 288 | BIO_free(in); |
7e1b7485 | 289 | return (ret); |
0f113f3e MC |
290 | } |
291 | ||
292 | # ifndef NO_MD5CRYPT_1 | |
293 | /* | |
294 | * MD5-based password algorithm (should probably be available as a library | |
295 | * function; then the static buffer would not be acceptable). For magic | |
296 | * string "1", this should be compatible to the MD5-based BSD password | |
297 | * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based | |
298 | * Apache password algorithm. (Apparently, the Apache password algorithm is | |
299 | * identical except that the 'magic' string was changed -- the laziest | |
300 | * application of the NIH principle I've ever encountered.) | |
1f4643a2 BM |
301 | */ |
302 | static char *md5crypt(const char *passwd, const char *magic, const char *salt) | |
0f113f3e MC |
303 | { |
304 | /* "$apr1$..salt..$.......md5hash..........\0" */ | |
305 | static char out_buf[6 + 9 + 24 + 2]; | |
306 | unsigned char buf[MD5_DIGEST_LENGTH]; | |
307 | char *salt_out; | |
308 | int n; | |
309 | unsigned int i; | |
6e59a892 | 310 | EVP_MD_CTX *md, *md2; |
0f113f3e MC |
311 | size_t passwd_len, salt_len; |
312 | ||
313 | passwd_len = strlen(passwd); | |
314 | out_buf[0] = '$'; | |
315 | out_buf[1] = 0; | |
316 | assert(strlen(magic) <= 4); /* "1" or "apr1" */ | |
7644a9ae RS |
317 | OPENSSL_strlcat(out_buf, magic, sizeof out_buf); |
318 | OPENSSL_strlcat(out_buf, "$", sizeof out_buf); | |
319 | OPENSSL_strlcat(out_buf, salt, sizeof out_buf); | |
0f113f3e MC |
320 | assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */ |
321 | salt_out = out_buf + 2 + strlen(magic); | |
322 | salt_len = strlen(salt_out); | |
323 | assert(salt_len <= 8); | |
324 | ||
bfb0641f | 325 | md = EVP_MD_CTX_new(); |
6e59a892 RL |
326 | if (md == NULL) |
327 | return NULL; | |
328 | EVP_DigestInit_ex(md, EVP_md5(), NULL); | |
329 | EVP_DigestUpdate(md, passwd, passwd_len); | |
330 | EVP_DigestUpdate(md, "$", 1); | |
331 | EVP_DigestUpdate(md, magic, strlen(magic)); | |
332 | EVP_DigestUpdate(md, "$", 1); | |
333 | EVP_DigestUpdate(md, salt_out, salt_len); | |
334 | ||
bfb0641f | 335 | md2 = EVP_MD_CTX_new(); |
6e59a892 RL |
336 | if (md2 == NULL) |
337 | return NULL; | |
338 | EVP_DigestInit_ex(md2, EVP_md5(), NULL); | |
339 | EVP_DigestUpdate(md2, passwd, passwd_len); | |
340 | EVP_DigestUpdate(md2, salt_out, salt_len); | |
341 | EVP_DigestUpdate(md2, passwd, passwd_len); | |
342 | EVP_DigestFinal_ex(md2, buf, NULL); | |
0f113f3e MC |
343 | |
344 | for (i = passwd_len; i > sizeof buf; i -= sizeof buf) | |
6e59a892 RL |
345 | EVP_DigestUpdate(md, buf, sizeof buf); |
346 | EVP_DigestUpdate(md, buf, i); | |
0f113f3e MC |
347 | |
348 | n = passwd_len; | |
349 | while (n) { | |
6e59a892 | 350 | EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1); |
0f113f3e MC |
351 | n >>= 1; |
352 | } | |
6e59a892 | 353 | EVP_DigestFinal_ex(md, buf, NULL); |
0f113f3e MC |
354 | |
355 | for (i = 0; i < 1000; i++) { | |
6e59a892 RL |
356 | EVP_DigestInit_ex(md2, EVP_md5(), NULL); |
357 | EVP_DigestUpdate(md2, (i & 1) ? (unsigned const char *)passwd : buf, | |
0f113f3e MC |
358 | (i & 1) ? passwd_len : sizeof buf); |
359 | if (i % 3) | |
6e59a892 | 360 | EVP_DigestUpdate(md2, salt_out, salt_len); |
0f113f3e | 361 | if (i % 7) |
6e59a892 RL |
362 | EVP_DigestUpdate(md2, passwd, passwd_len); |
363 | EVP_DigestUpdate(md2, (i & 1) ? buf : (unsigned const char *)passwd, | |
0f113f3e | 364 | (i & 1) ? sizeof buf : passwd_len); |
6e59a892 | 365 | EVP_DigestFinal_ex(md2, buf, NULL); |
0f113f3e | 366 | } |
bfb0641f RL |
367 | EVP_MD_CTX_free(md2); |
368 | EVP_MD_CTX_free(md); | |
0f113f3e MC |
369 | |
370 | { | |
371 | /* transform buf into output string */ | |
372 | ||
373 | unsigned char buf_perm[sizeof buf]; | |
374 | int dest, source; | |
375 | char *output; | |
376 | ||
377 | /* silly output permutation */ | |
378 | for (dest = 0, source = 0; dest < 14; | |
379 | dest++, source = (source + 6) % 17) | |
380 | buf_perm[dest] = buf[source]; | |
381 | buf_perm[14] = buf[5]; | |
382 | buf_perm[15] = buf[11]; | |
383 | # ifndef PEDANTIC /* Unfortunately, this generates a "no | |
384 | * effect" warning */ | |
385 | assert(16 == sizeof buf_perm); | |
386 | # endif | |
387 | ||
388 | output = salt_out + salt_len; | |
389 | assert(output == out_buf + strlen(out_buf)); | |
390 | ||
391 | *output++ = '$'; | |
392 | ||
393 | for (i = 0; i < 15; i += 3) { | |
394 | *output++ = cov_2char[buf_perm[i + 2] & 0x3f]; | |
395 | *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) | | |
396 | (buf_perm[i + 2] >> 6)]; | |
397 | *output++ = cov_2char[((buf_perm[i] & 3) << 4) | | |
398 | (buf_perm[i + 1] >> 4)]; | |
399 | *output++ = cov_2char[buf_perm[i] >> 2]; | |
400 | } | |
401 | assert(i == 15); | |
402 | *output++ = cov_2char[buf_perm[i] & 0x3f]; | |
403 | *output++ = cov_2char[buf_perm[i] >> 6]; | |
404 | *output = 0; | |
405 | assert(strlen(out_buf) < sizeof(out_buf)); | |
406 | } | |
0f113f3e MC |
407 | |
408 | return out_buf; | |
409 | } | |
410 | # endif | |
e6e7b5f3 BM |
411 | |
412 | static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, | |
0f113f3e MC |
413 | char *passwd, BIO *out, int quiet, int table, |
414 | int reverse, size_t pw_maxlen, int usecrypt, int use1, | |
415 | int useapr1) | |
416 | { | |
417 | char *hash = NULL; | |
418 | ||
419 | assert(salt_p != NULL); | |
420 | assert(salt_malloc_p != NULL); | |
421 | ||
422 | /* first make sure we have a salt */ | |
423 | if (!passed_salt) { | |
424 | # ifndef OPENSSL_NO_DES | |
425 | if (usecrypt) { | |
426 | if (*salt_malloc_p == NULL) { | |
68dc6824 | 427 | *salt_p = *salt_malloc_p = app_malloc(3, "salt buffer"); |
0f113f3e | 428 | } |
266483d2 | 429 | if (RAND_bytes((unsigned char *)*salt_p, 2) <= 0) |
7e1b7485 | 430 | goto end; |
0f113f3e MC |
431 | (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */ |
432 | (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */ | |
433 | (*salt_p)[2] = 0; | |
434 | # ifdef CHARSET_EBCDIC | |
435 | ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert back | |
436 | * to ASCII */ | |
437 | # endif | |
438 | } | |
439 | # endif /* !OPENSSL_NO_DES */ | |
440 | ||
441 | # ifndef NO_MD5CRYPT_1 | |
442 | if (use1 || useapr1) { | |
443 | int i; | |
444 | ||
445 | if (*salt_malloc_p == NULL) { | |
68dc6824 | 446 | *salt_p = *salt_malloc_p = app_malloc(9, "salt buffer"); |
0f113f3e | 447 | } |
266483d2 | 448 | if (RAND_bytes((unsigned char *)*salt_p, 8) <= 0) |
7e1b7485 | 449 | goto end; |
0f113f3e MC |
450 | |
451 | for (i = 0; i < 8; i++) | |
452 | (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */ | |
453 | (*salt_p)[8] = 0; | |
454 | } | |
455 | # endif /* !NO_MD5CRYPT_1 */ | |
456 | } | |
457 | ||
458 | assert(*salt_p != NULL); | |
459 | ||
460 | /* truncate password if necessary */ | |
461 | if ((strlen(passwd) > pw_maxlen)) { | |
462 | if (!quiet) | |
463 | /* | |
464 | * XXX: really we should know how to print a size_t, not cast it | |
465 | */ | |
466 | BIO_printf(bio_err, | |
467 | "Warning: truncating password to %u characters\n", | |
468 | (unsigned)pw_maxlen); | |
469 | passwd[pw_maxlen] = 0; | |
470 | } | |
471 | assert(strlen(passwd) <= pw_maxlen); | |
472 | ||
473 | /* now compute password hash */ | |
474 | # ifndef OPENSSL_NO_DES | |
475 | if (usecrypt) | |
476 | hash = DES_crypt(passwd, *salt_p); | |
477 | # endif | |
478 | # ifndef NO_MD5CRYPT_1 | |
479 | if (use1 || useapr1) | |
480 | hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p); | |
481 | # endif | |
482 | assert(hash != NULL); | |
483 | ||
484 | if (table && !reverse) | |
485 | BIO_printf(out, "%s\t%s\n", passwd, hash); | |
486 | else if (table && reverse) | |
487 | BIO_printf(out, "%s\t%s\n", hash, passwd); | |
488 | else | |
489 | BIO_printf(out, "%s\n", hash); | |
0f113f3e | 490 | return 0; |
7e1b7485 RS |
491 | |
492 | end: | |
493 | return 1; | |
0f113f3e | 494 | } |
3ebf0be1 | 495 | #else |
e6e7b5f3 | 496 | |
7e1b7485 | 497 | int passwd_main(int argc, char **argv) |
0f113f3e | 498 | { |
7768e116 RS |
499 | BIO_printf(bio_err, "Program not available.\n"); |
500 | return (1); | |
0f113f3e | 501 | } |
3ebf0be1 | 502 | #endif |