1*e7718adaStb /* $OpenBSD: passwd.c,v 1.14 2023/03/06 14:32:06 tb Exp $ */
2dab3f910Sjsing
3dab3f910Sjsing #if defined OPENSSL_NO_MD5
4dab3f910Sjsing #define NO_MD5CRYPT_1
5dab3f910Sjsing #endif
6dab3f910Sjsing
7dab3f910Sjsing #if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1)
8dab3f910Sjsing
9dab3f910Sjsing #include <assert.h>
10dab3f910Sjsing #include <string.h>
11dab3f910Sjsing
12dab3f910Sjsing #include "apps.h"
13dab3f910Sjsing
14dab3f910Sjsing #include <openssl/bio.h>
15dab3f910Sjsing #include <openssl/err.h>
16dab3f910Sjsing #include <openssl/evp.h>
17dab3f910Sjsing
18dab3f910Sjsing #ifndef OPENSSL_NO_DES
19dab3f910Sjsing #include <openssl/des.h>
20dab3f910Sjsing #endif
21dab3f910Sjsing
22dab3f910Sjsing #ifndef NO_MD5CRYPT_1
23dab3f910Sjsing #include <openssl/md5.h>
24dab3f910Sjsing #endif
25dab3f910Sjsing
26dab3f910Sjsing static unsigned const char cov_2char[64] = {
27dab3f910Sjsing /* from crypto/des/fcrypt.c */
28dab3f910Sjsing 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
29dab3f910Sjsing 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
30dab3f910Sjsing 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
31dab3f910Sjsing 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
32dab3f910Sjsing 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
33dab3f910Sjsing 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
34dab3f910Sjsing 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
35dab3f910Sjsing 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
36dab3f910Sjsing };
37dab3f910Sjsing
38dab3f910Sjsing static int
39dab3f910Sjsing do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
40dab3f910Sjsing char *passwd, BIO * out, int quiet, int table, int reverse,
41dab3f910Sjsing size_t pw_maxlen, int usecrypt, int use1, int useapr1);
42dab3f910Sjsing
43b6995238Sjsing static struct {
44b6995238Sjsing char *infile;
45b6995238Sjsing int in_stdin;
46b6995238Sjsing int noverify;
47b6995238Sjsing int quiet;
48b6995238Sjsing int reverse;
49b6995238Sjsing char *salt;
50b6995238Sjsing int table;
51b6995238Sjsing int use1;
52b6995238Sjsing int useapr1;
53b6995238Sjsing int usecrypt;
54*e7718adaStb } cfg;
55b6995238Sjsing
56ea149709Sguenther static const struct option passwd_options[] = {
57b6995238Sjsing #ifndef NO_MD5CRYPT_1
58b6995238Sjsing {
59b6995238Sjsing .name = "1",
60b6995238Sjsing .desc = "Use MD5 based BSD password algorithm 1",
61b6995238Sjsing .type = OPTION_FLAG,
62*e7718adaStb .opt.flag = &cfg.use1,
63b6995238Sjsing },
64b6995238Sjsing {
65b6995238Sjsing .name = "apr1",
66b6995238Sjsing .desc = "Use apr1 algorithm (Apache variant of BSD algorithm)",
67b6995238Sjsing .type = OPTION_FLAG,
68*e7718adaStb .opt.flag = &cfg.useapr1,
69b6995238Sjsing },
70b6995238Sjsing #endif
71b6995238Sjsing #ifndef OPENSSL_NO_DES
72b6995238Sjsing {
73b6995238Sjsing .name = "crypt",
74b6995238Sjsing .desc = "Use crypt algorithm (default)",
75b6995238Sjsing .type = OPTION_FLAG,
76*e7718adaStb .opt.flag = &cfg.usecrypt,
77b6995238Sjsing },
78b6995238Sjsing #endif
79b6995238Sjsing {
80b6995238Sjsing .name = "in",
81b6995238Sjsing .argname = "file",
82b6995238Sjsing .desc = "Read passwords from specified file",
83b6995238Sjsing .type = OPTION_ARG,
84*e7718adaStb .opt.arg = &cfg.infile,
85b6995238Sjsing },
86b6995238Sjsing {
87b6995238Sjsing .name = "noverify",
88b6995238Sjsing .desc = "Do not verify password",
89b6995238Sjsing .type = OPTION_FLAG,
90*e7718adaStb .opt.flag = &cfg.noverify,
91b6995238Sjsing },
92b6995238Sjsing {
93b6995238Sjsing .name = "quiet",
94b6995238Sjsing .desc = "Do not output warnings",
95b6995238Sjsing .type = OPTION_FLAG,
96*e7718adaStb .opt.flag = &cfg.quiet,
97b6995238Sjsing },
98b6995238Sjsing {
99b6995238Sjsing .name = "reverse",
100b6995238Sjsing .desc = "Reverse table columns (requires -table)",
101b6995238Sjsing .type = OPTION_FLAG,
102*e7718adaStb .opt.flag = &cfg.reverse,
103b6995238Sjsing },
104b6995238Sjsing {
105b6995238Sjsing .name = "salt",
106b6995238Sjsing .argname = "string",
107b6995238Sjsing .desc = "Use specified salt",
108b6995238Sjsing .type = OPTION_ARG,
109*e7718adaStb .opt.arg = &cfg.salt,
110b6995238Sjsing },
111b6995238Sjsing {
112b6995238Sjsing .name = "stdin",
113b6995238Sjsing .desc = "Read passwords from stdin",
114b6995238Sjsing .type = OPTION_FLAG,
115*e7718adaStb .opt.flag = &cfg.in_stdin,
116b6995238Sjsing },
117b6995238Sjsing {
118b6995238Sjsing .name = "table",
119b6995238Sjsing .desc = "Output cleartext and hashed passwords (tab separated)",
120b6995238Sjsing .type = OPTION_FLAG,
121*e7718adaStb .opt.flag = &cfg.table,
122b6995238Sjsing },
123b6995238Sjsing { NULL },
124b6995238Sjsing };
125b6995238Sjsing
126b6995238Sjsing static void
passwd_usage(void)127b6995238Sjsing passwd_usage(void)
128b6995238Sjsing {
129b6995238Sjsing fprintf(stderr, "usage: passwd [-1 | -apr1 | -crypt] [-in file] "
130b6995238Sjsing "[-noverify] [-quiet]\n"
131b6995238Sjsing " [-reverse] [-salt string] [-stdin] [-table] [password]\n\n");
132b6995238Sjsing options_usage(passwd_options);
133b6995238Sjsing }
134dab3f910Sjsing
135dab3f910Sjsing int
passwd_main(int argc,char ** argv)136dab3f910Sjsing passwd_main(int argc, char **argv)
137dab3f910Sjsing {
138b6995238Sjsing char *passwd = NULL, **passwds = NULL;
139dab3f910Sjsing char *salt_malloc = NULL, *passwd_malloc = NULL;
140dab3f910Sjsing size_t passwd_malloc_size = 0;
141dab3f910Sjsing BIO *in = NULL, *out = NULL;
142b6995238Sjsing int badopt = 0;
143b6995238Sjsing int passed_salt = 0;
144dab3f910Sjsing size_t pw_maxlen = 0;
145b6995238Sjsing int argsused;
146b6995238Sjsing int ret = 1;
147dab3f910Sjsing
14851811eadSderaadt if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1499bc487adSdoug perror("pledge");
150e370f0eeSdoug exit(1);
151e370f0eeSdoug }
1529bc487adSdoug
153*e7718adaStb memset(&cfg, 0, sizeof(cfg));
154b6995238Sjsing
155b6995238Sjsing if (options_parse(argc, argv, passwd_options, NULL, &argsused) != 0) {
156b6995238Sjsing passwd_usage();
157dab3f910Sjsing goto err;
158dab3f910Sjsing }
159dab3f910Sjsing
160b6995238Sjsing if (argsused < argc)
161b6995238Sjsing passwds = &argv[argsused];
162*e7718adaStb if (cfg.salt != NULL)
163b6995238Sjsing passed_salt = 1;
164dab3f910Sjsing
165*e7718adaStb if (!cfg.usecrypt && !cfg.use1 &&
166*e7718adaStb !cfg.useapr1)
167*e7718adaStb cfg.usecrypt = 1; /* use default */
168*e7718adaStb if (cfg.usecrypt + cfg.use1 +
169*e7718adaStb cfg.useapr1 > 1)
170b6995238Sjsing badopt = 1; /* conflicting options */
171b6995238Sjsing
172b6995238Sjsing /* Reject unsupported algorithms */
173dab3f910Sjsing #ifdef OPENSSL_NO_DES
174*e7718adaStb if (cfg.usecrypt)
175dab3f910Sjsing badopt = 1;
176dab3f910Sjsing #endif
177dab3f910Sjsing #ifdef NO_MD5CRYPT_1
178*e7718adaStb if (cfg.use1 || cfg.useapr1)
179dab3f910Sjsing badopt = 1;
180dab3f910Sjsing #endif
181dab3f910Sjsing
182dab3f910Sjsing if (badopt) {
183b6995238Sjsing passwd_usage();
184dab3f910Sjsing goto err;
185dab3f910Sjsing }
186b6995238Sjsing
187b6995238Sjsing if ((out = BIO_new(BIO_s_file())) == NULL)
188dab3f910Sjsing goto err;
189b6995238Sjsing BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
190b6995238Sjsing
191*e7718adaStb if (cfg.infile != NULL || cfg.in_stdin) {
192b6995238Sjsing if ((in = BIO_new(BIO_s_file())) == NULL)
193b6995238Sjsing goto err;
194*e7718adaStb if (cfg.infile != NULL) {
195*e7718adaStb assert(cfg.in_stdin == 0);
196*e7718adaStb if (BIO_read_filename(in, cfg.infile) <= 0)
197dab3f910Sjsing goto err;
198dab3f910Sjsing } else {
199*e7718adaStb assert(cfg.in_stdin);
200dab3f910Sjsing BIO_set_fp(in, stdin, BIO_NOCLOSE);
201dab3f910Sjsing }
202dab3f910Sjsing }
203*e7718adaStb if (cfg.usecrypt)
204dab3f910Sjsing pw_maxlen = 8;
205*e7718adaStb else if (cfg.use1 || cfg.useapr1)
206dab3f910Sjsing pw_maxlen = 256;/* arbitrary limit, should be enough for most
207dab3f910Sjsing * passwords */
208dab3f910Sjsing
209dab3f910Sjsing if (passwds == NULL) {
210dab3f910Sjsing /* no passwords on the command line */
211dab3f910Sjsing
212dab3f910Sjsing passwd_malloc_size = pw_maxlen + 2;
213dab3f910Sjsing /* longer than necessary so that we can warn about truncation */
214dab3f910Sjsing passwd = passwd_malloc = malloc(passwd_malloc_size);
215dab3f910Sjsing if (passwd_malloc == NULL)
216dab3f910Sjsing goto err;
217dab3f910Sjsing }
218b6995238Sjsing if (in == NULL && passwds == NULL) {
219dab3f910Sjsing /* build a null-terminated list */
220dab3f910Sjsing static char *passwds_static[2] = {NULL, NULL};
221dab3f910Sjsing
222dab3f910Sjsing passwds = passwds_static;
223dab3f910Sjsing if (in == NULL)
224b6995238Sjsing if (EVP_read_pw_string(passwd_malloc,
225b6995238Sjsing passwd_malloc_size, "Password: ",
226*e7718adaStb !(passed_salt || cfg.noverify)) != 0)
227dab3f910Sjsing goto err;
228dab3f910Sjsing passwds[0] = passwd_malloc;
229dab3f910Sjsing }
230dab3f910Sjsing if (in == NULL) {
231dab3f910Sjsing assert(passwds != NULL);
232dab3f910Sjsing assert(*passwds != NULL);
233dab3f910Sjsing
234dab3f910Sjsing do { /* loop over list of passwords */
235dab3f910Sjsing passwd = *passwds++;
236*e7718adaStb if (!do_passwd(passed_salt, &cfg.salt,
237*e7718adaStb &salt_malloc, passwd, out, cfg.quiet,
238*e7718adaStb cfg.table, cfg.reverse,
239*e7718adaStb pw_maxlen, cfg.usecrypt,
240*e7718adaStb cfg.use1, cfg.useapr1))
241dab3f910Sjsing goto err;
242b6995238Sjsing } while (*passwds != NULL);
243b6995238Sjsing } else {
244dab3f910Sjsing int done;
245dab3f910Sjsing
246dab3f910Sjsing assert(passwd != NULL);
247dab3f910Sjsing do {
248dab3f910Sjsing int r = BIO_gets(in, passwd, pw_maxlen + 1);
249dab3f910Sjsing if (r > 0) {
250dab3f910Sjsing char *c = (strchr(passwd, '\n'));
251dab3f910Sjsing if (c != NULL)
252dab3f910Sjsing *c = 0; /* truncate at newline */
253dab3f910Sjsing else {
254dab3f910Sjsing /* ignore rest of line */
255dab3f910Sjsing char trash[BUFSIZ];
256dab3f910Sjsing do
257dab3f910Sjsing r = BIO_gets(in, trash, sizeof trash);
258dab3f910Sjsing while ((r > 0) && (!strchr(trash, '\n')));
259dab3f910Sjsing }
260dab3f910Sjsing
261*e7718adaStb if (!do_passwd(passed_salt, &cfg.salt,
262b6995238Sjsing &salt_malloc, passwd, out,
263*e7718adaStb cfg.quiet, cfg.table,
264*e7718adaStb cfg.reverse, pw_maxlen,
265*e7718adaStb cfg.usecrypt, cfg.use1,
266*e7718adaStb cfg.useapr1))
267dab3f910Sjsing goto err;
268dab3f910Sjsing }
269dab3f910Sjsing done = (r <= 0);
270b6995238Sjsing } while (!done);
271dab3f910Sjsing }
272dab3f910Sjsing ret = 0;
273dab3f910Sjsing
274dab3f910Sjsing err:
275dab3f910Sjsing ERR_print_errors(bio_err);
276b6995238Sjsing
277dab3f910Sjsing free(salt_malloc);
278dab3f910Sjsing free(passwd_malloc);
279b6995238Sjsing
280dab3f910Sjsing BIO_free(in);
281dab3f910Sjsing BIO_free_all(out);
282dab3f910Sjsing
283dab3f910Sjsing return (ret);
284dab3f910Sjsing }
285dab3f910Sjsing
286dab3f910Sjsing
287dab3f910Sjsing #ifndef NO_MD5CRYPT_1
288dab3f910Sjsing /* MD5-based password algorithm (should probably be available as a library
289dab3f910Sjsing * function; then the static buffer would not be acceptable).
290dab3f910Sjsing * For magic string "1", this should be compatible to the MD5-based BSD
291dab3f910Sjsing * password algorithm.
292dab3f910Sjsing * For 'magic' string "apr1", this is compatible to the MD5-based Apache
293dab3f910Sjsing * password algorithm.
294dab3f910Sjsing * (Apparently, the Apache password algorithm is identical except that the
295dab3f910Sjsing * 'magic' string was changed -- the laziest application of the NIH principle
296dab3f910Sjsing * I've ever encountered.)
297dab3f910Sjsing */
298dab3f910Sjsing static char *
md5crypt(const char * passwd,const char * magic,const char * salt)299dab3f910Sjsing md5crypt(const char *passwd, const char *magic, const char *salt)
300dab3f910Sjsing {
301dab3f910Sjsing static char out_buf[6 + 9 + 24 + 2]; /* "$apr1$..salt..$.......md5h
302dab3f910Sjsing * ash..........\0" */
303dab3f910Sjsing unsigned char buf[MD5_DIGEST_LENGTH];
304dab3f910Sjsing char *salt_out;
305dab3f910Sjsing int n;
306dab3f910Sjsing unsigned int i;
30770158555Stb EVP_MD_CTX *md = NULL, *md2 = NULL;
308dab3f910Sjsing size_t passwd_len, salt_len;
309dab3f910Sjsing
310dab3f910Sjsing passwd_len = strlen(passwd);
311dab3f910Sjsing out_buf[0] = '$';
312dab3f910Sjsing out_buf[1] = 0;
313dab3f910Sjsing assert(strlen(magic) <= 4); /* "1" or "apr1" */
314dab3f910Sjsing strlcat(out_buf, magic, sizeof(out_buf));
315dab3f910Sjsing strlcat(out_buf, "$", sizeof(out_buf));
316dab3f910Sjsing strlcat(out_buf, salt, sizeof(out_buf));
317dab3f910Sjsing assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */
318dab3f910Sjsing salt_out = out_buf + 2 + strlen(magic);
319dab3f910Sjsing salt_len = strlen(salt_out);
320dab3f910Sjsing assert(salt_len <= 8);
321dab3f910Sjsing
32270158555Stb if ((md = EVP_MD_CTX_new()) == NULL)
32370158555Stb goto err;
32470158555Stb if (!EVP_DigestInit_ex(md, EVP_md5(), NULL))
32570158555Stb goto err;
32670158555Stb if (!EVP_DigestUpdate(md, passwd, passwd_len))
32770158555Stb goto err;
32870158555Stb if (!EVP_DigestUpdate(md, "$", 1))
32970158555Stb goto err;
33070158555Stb if (!EVP_DigestUpdate(md, magic, strlen(magic)))
33170158555Stb goto err;
33270158555Stb if (!EVP_DigestUpdate(md, "$", 1))
33370158555Stb goto err;
33470158555Stb if (!EVP_DigestUpdate(md, salt_out, salt_len))
33570158555Stb goto err;
336dab3f910Sjsing
33770158555Stb if ((md2 = EVP_MD_CTX_new()) == NULL)
33870158555Stb goto err;
33970158555Stb if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
34070158555Stb goto err;
34170158555Stb if (!EVP_DigestUpdate(md2, passwd, passwd_len))
34270158555Stb goto err;
34370158555Stb if (!EVP_DigestUpdate(md2, salt_out, salt_len))
34470158555Stb goto err;
34570158555Stb if (!EVP_DigestUpdate(md2, passwd, passwd_len))
34670158555Stb goto err;
34770158555Stb if (!EVP_DigestFinal_ex(md2, buf, NULL))
34870158555Stb goto err;
349dab3f910Sjsing
35070158555Stb for (i = passwd_len; i > sizeof buf; i -= sizeof buf) {
35170158555Stb if (!EVP_DigestUpdate(md, buf, sizeof buf))
35270158555Stb goto err;
35370158555Stb }
35470158555Stb if (!EVP_DigestUpdate(md, buf, i))
35570158555Stb goto err;
356dab3f910Sjsing
357dab3f910Sjsing n = passwd_len;
358dab3f910Sjsing while (n) {
35970158555Stb if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1))
36070158555Stb goto err;
361dab3f910Sjsing n >>= 1;
362dab3f910Sjsing }
36370158555Stb if (!EVP_DigestFinal_ex(md, buf, NULL))
36470158555Stb goto err;
365dab3f910Sjsing
366dab3f910Sjsing for (i = 0; i < 1000; i++) {
36770158555Stb if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
36870158555Stb goto err;
36970158555Stb if (!EVP_DigestUpdate(md2,
37070158555Stb (i & 1) ? (unsigned const char *) passwd : buf,
37170158555Stb (i & 1) ? passwd_len : sizeof buf))
37270158555Stb goto err;
37370158555Stb if (i % 3) {
37470158555Stb if (!EVP_DigestUpdate(md2, salt_out, salt_len))
37570158555Stb goto err;
376dab3f910Sjsing }
37770158555Stb if (i % 7) {
37870158555Stb if (!EVP_DigestUpdate(md2, passwd, passwd_len))
37970158555Stb goto err;
38070158555Stb }
38170158555Stb if (!EVP_DigestUpdate(md2,
38270158555Stb (i & 1) ? buf : (unsigned const char *) passwd,
38370158555Stb (i & 1) ? sizeof buf : passwd_len))
38470158555Stb goto err;
38570158555Stb if (!EVP_DigestFinal_ex(md2, buf, NULL))
38670158555Stb goto err;
38770158555Stb }
38870158555Stb EVP_MD_CTX_free(md2);
38970158555Stb md2 = NULL;
390dab3f910Sjsing
391dab3f910Sjsing {
392dab3f910Sjsing /* transform buf into output string */
393dab3f910Sjsing
394dab3f910Sjsing unsigned char buf_perm[sizeof buf];
395dab3f910Sjsing int dest, source;
396dab3f910Sjsing char *output;
397dab3f910Sjsing
398dab3f910Sjsing /* silly output permutation */
399dab3f910Sjsing for (dest = 0, source = 0; dest < 14; dest++, source = (source + 6) % 17)
400dab3f910Sjsing buf_perm[dest] = buf[source];
401dab3f910Sjsing buf_perm[14] = buf[5];
402dab3f910Sjsing buf_perm[15] = buf[11];
403dab3f910Sjsing assert(16 == sizeof buf_perm);
404dab3f910Sjsing
405dab3f910Sjsing output = salt_out + salt_len;
406dab3f910Sjsing assert(output == out_buf + strlen(out_buf));
407dab3f910Sjsing
408dab3f910Sjsing *output++ = '$';
409dab3f910Sjsing
410dab3f910Sjsing for (i = 0; i < 15; i += 3) {
411dab3f910Sjsing *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
412dab3f910Sjsing *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
413dab3f910Sjsing (buf_perm[i + 2] >> 6)];
414dab3f910Sjsing *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
415dab3f910Sjsing (buf_perm[i + 1] >> 4)];
416dab3f910Sjsing *output++ = cov_2char[buf_perm[i] >> 2];
417dab3f910Sjsing }
418dab3f910Sjsing assert(i == 15);
419dab3f910Sjsing *output++ = cov_2char[buf_perm[i] & 0x3f];
420dab3f910Sjsing *output++ = cov_2char[buf_perm[i] >> 6];
421dab3f910Sjsing *output = 0;
422dab3f910Sjsing assert(strlen(out_buf) < sizeof(out_buf));
423dab3f910Sjsing }
42470158555Stb EVP_MD_CTX_free(md);
425dab3f910Sjsing
426dab3f910Sjsing return out_buf;
42770158555Stb err:
42870158555Stb EVP_MD_CTX_free(md);
42970158555Stb EVP_MD_CTX_free(md2);
43070158555Stb
43170158555Stb return NULL;
432dab3f910Sjsing }
433dab3f910Sjsing #endif
434dab3f910Sjsing
435dab3f910Sjsing
436dab3f910Sjsing static int
do_passwd(int passed_salt,char ** salt_p,char ** salt_malloc_p,char * passwd,BIO * out,int quiet,int table,int reverse,size_t pw_maxlen,int usecrypt,int use1,int useapr1)437dab3f910Sjsing do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
438dab3f910Sjsing char *passwd, BIO * out, int quiet, int table, int reverse,
439dab3f910Sjsing size_t pw_maxlen, int usecrypt, int use1, int useapr1)
440dab3f910Sjsing {
441dab3f910Sjsing char *hash = NULL;
442dab3f910Sjsing
443dab3f910Sjsing assert(salt_p != NULL);
444dab3f910Sjsing assert(salt_malloc_p != NULL);
445dab3f910Sjsing
446dab3f910Sjsing /* first make sure we have a salt */
447dab3f910Sjsing if (!passed_salt) {
448dab3f910Sjsing #ifndef OPENSSL_NO_DES
449dab3f910Sjsing if (usecrypt) {
450dab3f910Sjsing if (*salt_malloc_p == NULL) {
451dab3f910Sjsing *salt_p = *salt_malloc_p = malloc(3);
452dab3f910Sjsing if (*salt_malloc_p == NULL)
453dab3f910Sjsing goto err;
454dab3f910Sjsing }
455fd6ab616Sjsing arc4random_buf(*salt_p, 2);
456dab3f910Sjsing (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
457dab3f910Sjsing (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
458dab3f910Sjsing (*salt_p)[2] = 0;
459dab3f910Sjsing }
460dab3f910Sjsing #endif /* !OPENSSL_NO_DES */
461dab3f910Sjsing
462dab3f910Sjsing #ifndef NO_MD5CRYPT_1
463dab3f910Sjsing if (use1 || useapr1) {
464dab3f910Sjsing int i;
465dab3f910Sjsing
466dab3f910Sjsing if (*salt_malloc_p == NULL) {
467dab3f910Sjsing *salt_p = *salt_malloc_p = malloc(9);
468dab3f910Sjsing if (*salt_malloc_p == NULL)
469dab3f910Sjsing goto err;
470dab3f910Sjsing }
471fd6ab616Sjsing arc4random_buf(*salt_p, 8);
472dab3f910Sjsing
473dab3f910Sjsing for (i = 0; i < 8; i++)
474dab3f910Sjsing (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
475dab3f910Sjsing (*salt_p)[8] = 0;
476dab3f910Sjsing }
477dab3f910Sjsing #endif /* !NO_MD5CRYPT_1 */
478dab3f910Sjsing }
479dab3f910Sjsing assert(*salt_p != NULL);
480dab3f910Sjsing
481dab3f910Sjsing /* truncate password if necessary */
482dab3f910Sjsing if ((strlen(passwd) > pw_maxlen)) {
483dab3f910Sjsing if (!quiet)
484129f13dcStb BIO_printf(bio_err,
485129f13dcStb "Warning: truncating password to %zu characters\n",
486129f13dcStb pw_maxlen);
487dab3f910Sjsing passwd[pw_maxlen] = 0;
488dab3f910Sjsing }
489dab3f910Sjsing assert(strlen(passwd) <= pw_maxlen);
490dab3f910Sjsing
491dab3f910Sjsing /* now compute password hash */
492dab3f910Sjsing #ifndef OPENSSL_NO_DES
493dab3f910Sjsing if (usecrypt)
494dab3f910Sjsing hash = DES_crypt(passwd, *salt_p);
495dab3f910Sjsing #endif
496dab3f910Sjsing #ifndef NO_MD5CRYPT_1
497dab3f910Sjsing if (use1 || useapr1)
49870158555Stb if ((hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p)) == NULL)
49970158555Stb goto err;
500dab3f910Sjsing #endif
501dab3f910Sjsing assert(hash != NULL);
502dab3f910Sjsing
503dab3f910Sjsing if (table && !reverse)
504dab3f910Sjsing BIO_printf(out, "%s\t%s\n", passwd, hash);
505dab3f910Sjsing else if (table && reverse)
506dab3f910Sjsing BIO_printf(out, "%s\t%s\n", hash, passwd);
507dab3f910Sjsing else
508dab3f910Sjsing BIO_printf(out, "%s\n", hash);
509dab3f910Sjsing return 1;
510dab3f910Sjsing
511dab3f910Sjsing err:
51270158555Stb free(*salt_malloc_p);
51370158555Stb *salt_malloc_p = NULL;
514dab3f910Sjsing return 0;
515dab3f910Sjsing }
516dab3f910Sjsing #else
517dab3f910Sjsing
518dab3f910Sjsing int
passwd_main(int argc,char ** argv)519dab3f910Sjsing passwd_main(int argc, char **argv)
520dab3f910Sjsing {
521dab3f910Sjsing fputs("Program not available.\n", stderr)
522dab3f910Sjsing return (1);
523dab3f910Sjsing }
524dab3f910Sjsing #endif
525