159191Skris/* apps/passwd.c */
259191Skris
3109998Smarkm#if defined OPENSSL_NO_MD5 || defined CHARSET_EBCDIC
468651Skris# define NO_MD5CRYPT_1
559191Skris#endif
659191Skris
7109998Smarkm#if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1)
859191Skris
9296465Sdelphij# include <assert.h>
10296465Sdelphij# include <string.h>
1159191Skris
12296465Sdelphij# include "apps.h"
1359191Skris
14296465Sdelphij# include <openssl/bio.h>
15296465Sdelphij# include <openssl/err.h>
16296465Sdelphij# include <openssl/evp.h>
17296465Sdelphij# include <openssl/rand.h>
18296465Sdelphij# ifndef OPENSSL_NO_DES
19296465Sdelphij#  include <openssl/des.h>
20296465Sdelphij# endif
21296465Sdelphij# ifndef NO_MD5CRYPT_1
22296465Sdelphij#  include <openssl/md5.h>
23296465Sdelphij# endif
2459191Skris
25296465Sdelphij# undef PROG
26296465Sdelphij# define PROG passwd_main
2759191Skris
28296465Sdelphijstatic unsigned const char cov_2char[64] = {
29296465Sdelphij    /* from crypto/des/fcrypt.c */
30296465Sdelphij    0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
31296465Sdelphij    0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
32296465Sdelphij    0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
33296465Sdelphij    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
34296465Sdelphij    0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
35296465Sdelphij    0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
36296465Sdelphij    0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
37296465Sdelphij    0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
3859191Skris};
3959191Skris
4059191Skrisstatic int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
41296465Sdelphij                     char *passwd, BIO *out, int quiet, int table,
42296465Sdelphij                     int reverse, size_t pw_maxlen, int usecrypt, int use1,
43296465Sdelphij                     int useapr1);
4459191Skris
45296465Sdelphij/*-
46296465Sdelphij * -crypt        - standard Unix password algorithm (default)
4768651Skris * -1            - MD5-based password algorithm
4868651Skris * -apr1         - MD5-based password algorithm, Apache variant
4959191Skris * -salt string  - salt
5059191Skris * -in file      - read passwords from file
5159191Skris * -stdin        - read passwords from stdin
52109998Smarkm * -noverify     - never verify when reading password from terminal
5359191Skris * -quiet        - no warnings
5459191Skris * -table        - format output as table
5559191Skris * -reverse      - switch table columns
5659191Skris */
5759191Skris
5859191Skrisint MAIN(int, char **);
5959191Skris
6059191Skrisint MAIN(int argc, char **argv)
61296465Sdelphij{
62296465Sdelphij    int ret = 1;
63296465Sdelphij    char *infile = NULL;
64296465Sdelphij    int in_stdin = 0;
65296465Sdelphij    int in_noverify = 0;
66296465Sdelphij    char *salt = NULL, *passwd = NULL, **passwds = NULL;
67296465Sdelphij    char *salt_malloc = NULL, *passwd_malloc = NULL;
68296465Sdelphij    size_t passwd_malloc_size = 0;
69296465Sdelphij    int pw_source_defined = 0;
70296465Sdelphij    BIO *in = NULL, *out = NULL;
71296465Sdelphij    int i, badopt, opt_done;
72296465Sdelphij    int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
73296465Sdelphij    int usecrypt = 0, use1 = 0, useapr1 = 0;
74296465Sdelphij    size_t pw_maxlen = 0;
7559191Skris
76296465Sdelphij    apps_startup();
7759191Skris
78296465Sdelphij    if (bio_err == NULL)
79296465Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
80296465Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
81109998Smarkm
82296465Sdelphij    if (!load_config(bio_err, NULL))
83296465Sdelphij        goto err;
84296465Sdelphij    out = BIO_new(BIO_s_file());
85296465Sdelphij    if (out == NULL)
86296465Sdelphij        goto err;
87296465Sdelphij    BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
88296465Sdelphij# ifdef OPENSSL_SYS_VMS
89296465Sdelphij    {
90296465Sdelphij        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
91296465Sdelphij        out = BIO_push(tmpbio, out);
92296465Sdelphij    }
93296465Sdelphij# endif
9459191Skris
95296465Sdelphij    badopt = 0, opt_done = 0;
96296465Sdelphij    i = 0;
97296465Sdelphij    while (!badopt && !opt_done && argv[++i] != NULL) {
98296465Sdelphij        if (strcmp(argv[i], "-crypt") == 0)
99296465Sdelphij            usecrypt = 1;
100296465Sdelphij        else if (strcmp(argv[i], "-1") == 0)
101296465Sdelphij            use1 = 1;
102296465Sdelphij        else if (strcmp(argv[i], "-apr1") == 0)
103296465Sdelphij            useapr1 = 1;
104296465Sdelphij        else if (strcmp(argv[i], "-salt") == 0) {
105296465Sdelphij            if ((argv[i + 1] != NULL) && (salt == NULL)) {
106296465Sdelphij                passed_salt = 1;
107296465Sdelphij                salt = argv[++i];
108296465Sdelphij            } else
109296465Sdelphij                badopt = 1;
110296465Sdelphij        } else if (strcmp(argv[i], "-in") == 0) {
111296465Sdelphij            if ((argv[i + 1] != NULL) && !pw_source_defined) {
112296465Sdelphij                pw_source_defined = 1;
113296465Sdelphij                infile = argv[++i];
114296465Sdelphij            } else
115296465Sdelphij                badopt = 1;
116296465Sdelphij        } else if (strcmp(argv[i], "-stdin") == 0) {
117296465Sdelphij            if (!pw_source_defined) {
118296465Sdelphij                pw_source_defined = 1;
119296465Sdelphij                in_stdin = 1;
120296465Sdelphij            } else
121296465Sdelphij                badopt = 1;
122296465Sdelphij        } else if (strcmp(argv[i], "-noverify") == 0)
123296465Sdelphij            in_noverify = 1;
124296465Sdelphij        else if (strcmp(argv[i], "-quiet") == 0)
125296465Sdelphij            quiet = 1;
126296465Sdelphij        else if (strcmp(argv[i], "-table") == 0)
127296465Sdelphij            table = 1;
128296465Sdelphij        else if (strcmp(argv[i], "-reverse") == 0)
129296465Sdelphij            reverse = 1;
130296465Sdelphij        else if (argv[i][0] == '-')
131296465Sdelphij            badopt = 1;
132296465Sdelphij        else if (!pw_source_defined)
133296465Sdelphij            /* non-option arguments, use as passwords */
134296465Sdelphij        {
135296465Sdelphij            pw_source_defined = 1;
136296465Sdelphij            passwds = &argv[i];
137296465Sdelphij            opt_done = 1;
138296465Sdelphij        } else
139296465Sdelphij            badopt = 1;
140296465Sdelphij    }
14159191Skris
142296465Sdelphij    if (!usecrypt && !use1 && !useapr1) /* use default */
143296465Sdelphij        usecrypt = 1;
144296465Sdelphij    if (usecrypt + use1 + useapr1 > 1) /* conflict */
145296465Sdelphij        badopt = 1;
14659191Skris
147296465Sdelphij    /* reject unsupported algorithms */
148296465Sdelphij# ifdef OPENSSL_NO_DES
149296465Sdelphij    if (usecrypt)
150296465Sdelphij        badopt = 1;
151296465Sdelphij# endif
152296465Sdelphij# ifdef NO_MD5CRYPT_1
153296465Sdelphij    if (use1 || useapr1)
154296465Sdelphij        badopt = 1;
155296465Sdelphij# endif
15659191Skris
157296465Sdelphij    if (badopt) {
158296465Sdelphij        BIO_printf(bio_err, "Usage: passwd [options] [passwords]\n");
159296465Sdelphij        BIO_printf(bio_err, "where options are\n");
160296465Sdelphij# ifndef OPENSSL_NO_DES
161296465Sdelphij        BIO_printf(bio_err,
162296465Sdelphij                   "-crypt             standard Unix password algorithm (default)\n");
163296465Sdelphij# endif
164296465Sdelphij# ifndef NO_MD5CRYPT_1
165296465Sdelphij        BIO_printf(bio_err,
166296465Sdelphij                   "-1                 MD5-based password algorithm\n");
167296465Sdelphij        BIO_printf(bio_err,
168296465Sdelphij                   "-apr1              MD5-based password algorithm, Apache variant\n");
169296465Sdelphij# endif
170296465Sdelphij        BIO_printf(bio_err, "-salt string       use provided salt\n");
171296465Sdelphij        BIO_printf(bio_err, "-in file           read passwords from file\n");
172296465Sdelphij        BIO_printf(bio_err, "-stdin             read passwords from stdin\n");
173296465Sdelphij        BIO_printf(bio_err,
174296465Sdelphij                   "-noverify          never verify when reading password from terminal\n");
175296465Sdelphij        BIO_printf(bio_err, "-quiet             no warnings\n");
176296465Sdelphij        BIO_printf(bio_err, "-table             format output as table\n");
177296465Sdelphij        BIO_printf(bio_err, "-reverse           switch table columns\n");
17859191Skris
179296465Sdelphij        goto err;
180296465Sdelphij    }
18159191Skris
182296465Sdelphij    if ((infile != NULL) || in_stdin) {
183296465Sdelphij        in = BIO_new(BIO_s_file());
184296465Sdelphij        if (in == NULL)
185296465Sdelphij            goto err;
186296465Sdelphij        if (infile != NULL) {
187296465Sdelphij            assert(in_stdin == 0);
188296465Sdelphij            if (BIO_read_filename(in, infile) <= 0)
189296465Sdelphij                goto err;
190296465Sdelphij        } else {
191296465Sdelphij            assert(in_stdin);
192296465Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE);
193296465Sdelphij        }
194296465Sdelphij    }
19568651Skris
196296465Sdelphij    if (usecrypt)
197296465Sdelphij        pw_maxlen = 8;
198296465Sdelphij    else if (use1 || useapr1)
199296465Sdelphij        pw_maxlen = 256;        /* arbitrary limit, should be enough for most
200296465Sdelphij                                 * passwords */
20159191Skris
202296465Sdelphij    if (passwds == NULL) {
203296465Sdelphij        /* no passwords on the command line */
20459191Skris
205296465Sdelphij        passwd_malloc_size = pw_maxlen + 2;
206296465Sdelphij        /*
207296465Sdelphij         * longer than necessary so that we can warn about truncation
208296465Sdelphij         */
209296465Sdelphij        passwd = passwd_malloc = OPENSSL_malloc(passwd_malloc_size);
210296465Sdelphij        if (passwd_malloc == NULL)
211296465Sdelphij            goto err;
212296465Sdelphij    }
21359191Skris
214296465Sdelphij    if ((in == NULL) && (passwds == NULL)) {
215296465Sdelphij        /* build a null-terminated list */
216296465Sdelphij        static char *passwds_static[2] = { NULL, NULL };
21759191Skris
218296465Sdelphij        passwds = passwds_static;
219296465Sdelphij        if (in == NULL)
220296465Sdelphij            if (EVP_read_pw_string
221296465Sdelphij                (passwd_malloc, passwd_malloc_size, "Password: ",
222296465Sdelphij                 !(passed_salt || in_noverify)) != 0)
223296465Sdelphij                goto err;
224296465Sdelphij        passwds[0] = passwd_malloc;
225296465Sdelphij    }
22659191Skris
227296465Sdelphij    if (in == NULL) {
228296465Sdelphij        assert(passwds != NULL);
229296465Sdelphij        assert(*passwds != NULL);
23059191Skris
231296465Sdelphij        do {                    /* loop over list of passwords */
232296465Sdelphij            passwd = *passwds++;
233296465Sdelphij            if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
234296465Sdelphij                           quiet, table, reverse, pw_maxlen, usecrypt, use1,
235296465Sdelphij                           useapr1))
236296465Sdelphij                goto err;
237296465Sdelphij        }
238296465Sdelphij        while (*passwds != NULL);
239296465Sdelphij    } else
240296465Sdelphij        /* in != NULL */
241296465Sdelphij    {
242296465Sdelphij        int done;
243296465Sdelphij
244296465Sdelphij        assert(passwd != NULL);
245296465Sdelphij        do {
246296465Sdelphij            int r = BIO_gets(in, passwd, pw_maxlen + 1);
247296465Sdelphij            if (r > 0) {
248296465Sdelphij                char *c = (strchr(passwd, '\n'));
249296465Sdelphij                if (c != NULL)
250296465Sdelphij                    *c = 0;     /* truncate at newline */
251296465Sdelphij                else {
252296465Sdelphij                    /* ignore rest of line */
253296465Sdelphij                    char trash[BUFSIZ];
254296465Sdelphij                    do
255296465Sdelphij                        r = BIO_gets(in, trash, sizeof trash);
256296465Sdelphij                    while ((r > 0) && (!strchr(trash, '\n')));
257296465Sdelphij                }
258296465Sdelphij
259296465Sdelphij                if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
260296465Sdelphij                               quiet, table, reverse, pw_maxlen, usecrypt,
261296465Sdelphij                               use1, useapr1))
262296465Sdelphij                    goto err;
263296465Sdelphij            }
264296465Sdelphij            done = (r <= 0);
265296465Sdelphij        }
266296465Sdelphij        while (!done);
267296465Sdelphij    }
268296465Sdelphij    ret = 0;
269296465Sdelphij
270296465Sdelphij err:
271296465Sdelphij    ERR_print_errors(bio_err);
272296465Sdelphij    if (salt_malloc)
273296465Sdelphij        OPENSSL_free(salt_malloc);
274296465Sdelphij    if (passwd_malloc)
275296465Sdelphij        OPENSSL_free(passwd_malloc);
276296465Sdelphij    if (in)
277296465Sdelphij        BIO_free(in);
278296465Sdelphij    if (out)
279296465Sdelphij        BIO_free_all(out);
280296465Sdelphij    apps_shutdown();
281296465Sdelphij    OPENSSL_EXIT(ret);
282296465Sdelphij}
283296465Sdelphij
284296465Sdelphij# ifndef NO_MD5CRYPT_1
285296465Sdelphij/*
286296465Sdelphij * MD5-based password algorithm (should probably be available as a library
287296465Sdelphij * function; then the static buffer would not be acceptable). For magic
288296465Sdelphij * string "1", this should be compatible to the MD5-based BSD password
289296465Sdelphij * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
290296465Sdelphij * Apache password algorithm. (Apparently, the Apache password algorithm is
291296465Sdelphij * identical except that the 'magic' string was changed -- the laziest
292296465Sdelphij * application of the NIH principle I've ever encountered.)
29368651Skris */
29468651Skrisstatic char *md5crypt(const char *passwd, const char *magic, const char *salt)
295296465Sdelphij{
296296465Sdelphij    /* "$apr1$..salt..$.......md5hash..........\0" */
297296465Sdelphij    static char out_buf[6 + 9 + 24 + 2];
298296465Sdelphij    unsigned char buf[MD5_DIGEST_LENGTH];
299296465Sdelphij    char *salt_out;
300296465Sdelphij    int n;
301296465Sdelphij    unsigned int i;
302296465Sdelphij    EVP_MD_CTX md, md2;
303296465Sdelphij    size_t passwd_len, salt_len;
30459191Skris
305296465Sdelphij    passwd_len = strlen(passwd);
306296465Sdelphij    out_buf[0] = '$';
307296465Sdelphij    out_buf[1] = 0;
308296465Sdelphij    assert(strlen(magic) <= 4); /* "1" or "apr1" */
309296465Sdelphij    strncat(out_buf, magic, 4);
310296465Sdelphij    strncat(out_buf, "$", 1);
311296465Sdelphij    strncat(out_buf, salt, 8);
312296465Sdelphij    assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */
313296465Sdelphij    salt_out = out_buf + 2 + strlen(magic);
314296465Sdelphij    salt_len = strlen(salt_out);
315296465Sdelphij    assert(salt_len <= 8);
31659191Skris
317296465Sdelphij    EVP_MD_CTX_init(&md);
318296465Sdelphij    EVP_DigestInit_ex(&md, EVP_md5(), NULL);
319296465Sdelphij    EVP_DigestUpdate(&md, passwd, passwd_len);
320296465Sdelphij    EVP_DigestUpdate(&md, "$", 1);
321296465Sdelphij    EVP_DigestUpdate(&md, magic, strlen(magic));
322296465Sdelphij    EVP_DigestUpdate(&md, "$", 1);
323296465Sdelphij    EVP_DigestUpdate(&md, salt_out, salt_len);
32459191Skris
325296465Sdelphij    EVP_MD_CTX_init(&md2);
326296465Sdelphij    EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
327296465Sdelphij    EVP_DigestUpdate(&md2, passwd, passwd_len);
328296465Sdelphij    EVP_DigestUpdate(&md2, salt_out, salt_len);
329296465Sdelphij    EVP_DigestUpdate(&md2, passwd, passwd_len);
330296465Sdelphij    EVP_DigestFinal_ex(&md2, buf, NULL);
33159191Skris
332296465Sdelphij    for (i = passwd_len; i > sizeof buf; i -= sizeof buf)
333296465Sdelphij        EVP_DigestUpdate(&md, buf, sizeof buf);
334296465Sdelphij    EVP_DigestUpdate(&md, buf, i);
33559191Skris
336296465Sdelphij    n = passwd_len;
337296465Sdelphij    while (n) {
338296465Sdelphij        EVP_DigestUpdate(&md, (n & 1) ? "\0" : passwd, 1);
339296465Sdelphij        n >>= 1;
340296465Sdelphij    }
341296465Sdelphij    EVP_DigestFinal_ex(&md, buf, NULL);
34259191Skris
343296465Sdelphij    for (i = 0; i < 1000; i++) {
344296465Sdelphij        EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
345296465Sdelphij        EVP_DigestUpdate(&md2, (i & 1) ? (unsigned const char *)passwd : buf,
346296465Sdelphij                         (i & 1) ? passwd_len : sizeof buf);
347296465Sdelphij        if (i % 3)
348296465Sdelphij            EVP_DigestUpdate(&md2, salt_out, salt_len);
349296465Sdelphij        if (i % 7)
350296465Sdelphij            EVP_DigestUpdate(&md2, passwd, passwd_len);
351296465Sdelphij        EVP_DigestUpdate(&md2, (i & 1) ? buf : (unsigned const char *)passwd,
352296465Sdelphij                         (i & 1) ? sizeof buf : passwd_len);
353296465Sdelphij        EVP_DigestFinal_ex(&md2, buf, NULL);
354296465Sdelphij    }
355296465Sdelphij    EVP_MD_CTX_cleanup(&md2);
35659191Skris
357296465Sdelphij    {
358296465Sdelphij        /* transform buf into output string */
35959191Skris
360296465Sdelphij        unsigned char buf_perm[sizeof buf];
361296465Sdelphij        int dest, source;
362296465Sdelphij        char *output;
363296465Sdelphij
364296465Sdelphij        /* silly output permutation */
365296465Sdelphij        for (dest = 0, source = 0; dest < 14;
366296465Sdelphij             dest++, source = (source + 6) % 17)
367296465Sdelphij            buf_perm[dest] = buf[source];
368296465Sdelphij        buf_perm[14] = buf[5];
369296465Sdelphij        buf_perm[15] = buf[11];
370296465Sdelphij#  ifndef PEDANTIC              /* Unfortunately, this generates a "no
371296465Sdelphij                                 * effect" warning */
372296465Sdelphij        assert(16 == sizeof buf_perm);
373296465Sdelphij#  endif
374296465Sdelphij
375296465Sdelphij        output = salt_out + salt_len;
376296465Sdelphij        assert(output == out_buf + strlen(out_buf));
377296465Sdelphij
378296465Sdelphij        *output++ = '$';
379296465Sdelphij
380296465Sdelphij        for (i = 0; i < 15; i += 3) {
381296465Sdelphij            *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
382296465Sdelphij            *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
383296465Sdelphij                                  (buf_perm[i + 2] >> 6)];
384296465Sdelphij            *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
385296465Sdelphij                                  (buf_perm[i + 1] >> 4)];
386296465Sdelphij            *output++ = cov_2char[buf_perm[i] >> 2];
387296465Sdelphij        }
388296465Sdelphij        assert(i == 15);
389296465Sdelphij        *output++ = cov_2char[buf_perm[i] & 0x3f];
390296465Sdelphij        *output++ = cov_2char[buf_perm[i] >> 6];
391296465Sdelphij        *output = 0;
392296465Sdelphij        assert(strlen(out_buf) < sizeof(out_buf));
393296465Sdelphij    }
394296465Sdelphij    EVP_MD_CTX_cleanup(&md);
395296465Sdelphij
396296465Sdelphij    return out_buf;
397296465Sdelphij}
398296465Sdelphij# endif
399296465Sdelphij
40059191Skrisstatic int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
401296465Sdelphij                     char *passwd, BIO *out, int quiet, int table,
402296465Sdelphij                     int reverse, size_t pw_maxlen, int usecrypt, int use1,
403296465Sdelphij                     int useapr1)
404296465Sdelphij{
405296465Sdelphij    char *hash = NULL;
40659191Skris
407296465Sdelphij    assert(salt_p != NULL);
408296465Sdelphij    assert(salt_malloc_p != NULL);
40959191Skris
410296465Sdelphij    /* first make sure we have a salt */
411296465Sdelphij    if (!passed_salt) {
412296465Sdelphij# ifndef OPENSSL_NO_DES
413296465Sdelphij        if (usecrypt) {
414296465Sdelphij            if (*salt_malloc_p == NULL) {
415296465Sdelphij                *salt_p = *salt_malloc_p = OPENSSL_malloc(3);
416296465Sdelphij                if (*salt_malloc_p == NULL)
417296465Sdelphij                    goto err;
418296465Sdelphij            }
419296465Sdelphij            if (RAND_pseudo_bytes((unsigned char *)*salt_p, 2) < 0)
420296465Sdelphij                goto err;
421296465Sdelphij            (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
422296465Sdelphij            (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
423296465Sdelphij            (*salt_p)[2] = 0;
424296465Sdelphij#  ifdef CHARSET_EBCDIC
425296465Sdelphij            ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert back
426296465Sdelphij                                                * to ASCII */
427296465Sdelphij#  endif
428296465Sdelphij        }
429296465Sdelphij# endif                         /* !OPENSSL_NO_DES */
43059191Skris
431296465Sdelphij# ifndef NO_MD5CRYPT_1
432296465Sdelphij        if (use1 || useapr1) {
433296465Sdelphij            int i;
43459191Skris
435296465Sdelphij            if (*salt_malloc_p == NULL) {
436296465Sdelphij                *salt_p = *salt_malloc_p = OPENSSL_malloc(9);
437296465Sdelphij                if (*salt_malloc_p == NULL)
438296465Sdelphij                    goto err;
439296465Sdelphij            }
440296465Sdelphij            if (RAND_pseudo_bytes((unsigned char *)*salt_p, 8) < 0)
441296465Sdelphij                goto err;
442296465Sdelphij
443296465Sdelphij            for (i = 0; i < 8; i++)
444296465Sdelphij                (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
445296465Sdelphij            (*salt_p)[8] = 0;
446296465Sdelphij        }
447296465Sdelphij# endif                         /* !NO_MD5CRYPT_1 */
448296465Sdelphij    }
449296465Sdelphij
450296465Sdelphij    assert(*salt_p != NULL);
451296465Sdelphij
452296465Sdelphij    /* truncate password if necessary */
453296465Sdelphij    if ((strlen(passwd) > pw_maxlen)) {
454296465Sdelphij        if (!quiet)
455296465Sdelphij            /*
456296465Sdelphij             * XXX: really we should know how to print a size_t, not cast it
457296465Sdelphij             */
458296465Sdelphij            BIO_printf(bio_err,
459296465Sdelphij                       "Warning: truncating password to %u characters\n",
460296465Sdelphij                       (unsigned)pw_maxlen);
461296465Sdelphij        passwd[pw_maxlen] = 0;
462296465Sdelphij    }
463296465Sdelphij    assert(strlen(passwd) <= pw_maxlen);
464296465Sdelphij
465296465Sdelphij    /* now compute password hash */
466296465Sdelphij# ifndef OPENSSL_NO_DES
467296465Sdelphij    if (usecrypt)
468296465Sdelphij        hash = DES_crypt(passwd, *salt_p);
469296465Sdelphij# endif
470296465Sdelphij# ifndef NO_MD5CRYPT_1
471296465Sdelphij    if (use1 || useapr1)
472296465Sdelphij        hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p);
473296465Sdelphij# endif
474296465Sdelphij    assert(hash != NULL);
475296465Sdelphij
476296465Sdelphij    if (table && !reverse)
477296465Sdelphij        BIO_printf(out, "%s\t%s\n", passwd, hash);
478296465Sdelphij    else if (table && reverse)
479296465Sdelphij        BIO_printf(out, "%s\t%s\n", hash, passwd);
480296465Sdelphij    else
481296465Sdelphij        BIO_printf(out, "%s\n", hash);
482296465Sdelphij    return 1;
483296465Sdelphij
484296465Sdelphij err:
485296465Sdelphij    return 0;
486296465Sdelphij}
48759191Skris#else
48859191Skris
48959191Skrisint MAIN(int argc, char **argv)
490296465Sdelphij{
491296465Sdelphij    fputs("Program not available.\n", stderr)
492296465Sdelphij        OPENSSL_EXIT(1);
493296465Sdelphij}
49459191Skris#endif
495