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
9280297Sjkim# include <assert.h>
10280297Sjkim# include <string.h>
1159191Skris
12280297Sjkim# include "apps.h"
1359191Skris
14280297Sjkim# include <openssl/bio.h>
15280297Sjkim# include <openssl/err.h>
16280297Sjkim# include <openssl/evp.h>
17280297Sjkim# include <openssl/rand.h>
18280297Sjkim# ifndef OPENSSL_NO_DES
19280297Sjkim#  include <openssl/des.h>
20280297Sjkim# endif
21280297Sjkim# ifndef NO_MD5CRYPT_1
22280297Sjkim#  include <openssl/md5.h>
23280297Sjkim# endif
2459191Skris
25280297Sjkim# undef PROG
26280297Sjkim# define PROG passwd_main
2759191Skris
28280297Sjkimstatic unsigned const char cov_2char[64] = {
29280297Sjkim    /* from crypto/des/fcrypt.c */
30280297Sjkim    0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
31280297Sjkim    0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
32280297Sjkim    0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
33280297Sjkim    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
34280297Sjkim    0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
35280297Sjkim    0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
36280297Sjkim    0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
37280297Sjkim    0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
3859191Skris};
3959191Skris
4059191Skrisstatic int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
41280297Sjkim                     char *passwd, BIO *out, int quiet, int table,
42280297Sjkim                     int reverse, size_t pw_maxlen, int usecrypt, int use1,
43280297Sjkim                     int useapr1);
4459191Skris
45280297Sjkim/*-
46280297Sjkim * -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)
61280297Sjkim{
62280297Sjkim    int ret = 1;
63280297Sjkim    char *infile = NULL;
64280297Sjkim    int in_stdin = 0;
65280297Sjkim    int in_noverify = 0;
66280297Sjkim    char *salt = NULL, *passwd = NULL, **passwds = NULL;
67280297Sjkim    char *salt_malloc = NULL, *passwd_malloc = NULL;
68280297Sjkim    size_t passwd_malloc_size = 0;
69280297Sjkim    int pw_source_defined = 0;
70280297Sjkim    BIO *in = NULL, *out = NULL;
71280297Sjkim    int i, badopt, opt_done;
72280297Sjkim    int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
73280297Sjkim    int usecrypt = 0, use1 = 0, useapr1 = 0;
74280297Sjkim    size_t pw_maxlen = 0;
7559191Skris
76280297Sjkim    apps_startup();
7759191Skris
78280297Sjkim    if (bio_err == NULL)
79280297Sjkim        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
80280297Sjkim            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
81109998Smarkm
82280297Sjkim    if (!load_config(bio_err, NULL))
83280297Sjkim        goto err;
84280297Sjkim    out = BIO_new(BIO_s_file());
85280297Sjkim    if (out == NULL)
86280297Sjkim        goto err;
87280297Sjkim    BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
88280297Sjkim# ifdef OPENSSL_SYS_VMS
89280297Sjkim    {
90280297Sjkim        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
91280297Sjkim        out = BIO_push(tmpbio, out);
92280297Sjkim    }
93280297Sjkim# endif
9459191Skris
95280297Sjkim    badopt = 0, opt_done = 0;
96280297Sjkim    i = 0;
97280297Sjkim    while (!badopt && !opt_done && argv[++i] != NULL) {
98280297Sjkim        if (strcmp(argv[i], "-crypt") == 0)
99280297Sjkim            usecrypt = 1;
100280297Sjkim        else if (strcmp(argv[i], "-1") == 0)
101280297Sjkim            use1 = 1;
102280297Sjkim        else if (strcmp(argv[i], "-apr1") == 0)
103280297Sjkim            useapr1 = 1;
104280297Sjkim        else if (strcmp(argv[i], "-salt") == 0) {
105280297Sjkim            if ((argv[i + 1] != NULL) && (salt == NULL)) {
106280297Sjkim                passed_salt = 1;
107280297Sjkim                salt = argv[++i];
108280297Sjkim            } else
109280297Sjkim                badopt = 1;
110280297Sjkim        } else if (strcmp(argv[i], "-in") == 0) {
111280297Sjkim            if ((argv[i + 1] != NULL) && !pw_source_defined) {
112280297Sjkim                pw_source_defined = 1;
113280297Sjkim                infile = argv[++i];
114280297Sjkim            } else
115280297Sjkim                badopt = 1;
116280297Sjkim        } else if (strcmp(argv[i], "-stdin") == 0) {
117280297Sjkim            if (!pw_source_defined) {
118280297Sjkim                pw_source_defined = 1;
119280297Sjkim                in_stdin = 1;
120280297Sjkim            } else
121280297Sjkim                badopt = 1;
122280297Sjkim        } else if (strcmp(argv[i], "-noverify") == 0)
123280297Sjkim            in_noverify = 1;
124280297Sjkim        else if (strcmp(argv[i], "-quiet") == 0)
125280297Sjkim            quiet = 1;
126280297Sjkim        else if (strcmp(argv[i], "-table") == 0)
127280297Sjkim            table = 1;
128280297Sjkim        else if (strcmp(argv[i], "-reverse") == 0)
129280297Sjkim            reverse = 1;
130280297Sjkim        else if (argv[i][0] == '-')
131280297Sjkim            badopt = 1;
132280297Sjkim        else if (!pw_source_defined)
133280297Sjkim            /* non-option arguments, use as passwords */
134280297Sjkim        {
135280297Sjkim            pw_source_defined = 1;
136280297Sjkim            passwds = &argv[i];
137280297Sjkim            opt_done = 1;
138280297Sjkim        } else
139280297Sjkim            badopt = 1;
140280297Sjkim    }
14159191Skris
142280297Sjkim    if (!usecrypt && !use1 && !useapr1) /* use default */
143280297Sjkim        usecrypt = 1;
144280297Sjkim    if (usecrypt + use1 + useapr1 > 1) /* conflict */
145280297Sjkim        badopt = 1;
14659191Skris
147280297Sjkim    /* reject unsupported algorithms */
148280297Sjkim# ifdef OPENSSL_NO_DES
149280297Sjkim    if (usecrypt)
150280297Sjkim        badopt = 1;
151280297Sjkim# endif
152280297Sjkim# ifdef NO_MD5CRYPT_1
153280297Sjkim    if (use1 || useapr1)
154280297Sjkim        badopt = 1;
155280297Sjkim# endif
15659191Skris
157280297Sjkim    if (badopt) {
158280297Sjkim        BIO_printf(bio_err, "Usage: passwd [options] [passwords]\n");
159280297Sjkim        BIO_printf(bio_err, "where options are\n");
160280297Sjkim# ifndef OPENSSL_NO_DES
161280297Sjkim        BIO_printf(bio_err,
162280297Sjkim                   "-crypt             standard Unix password algorithm (default)\n");
163280297Sjkim# endif
164280297Sjkim# ifndef NO_MD5CRYPT_1
165280297Sjkim        BIO_printf(bio_err,
166280297Sjkim                   "-1                 MD5-based password algorithm\n");
167280297Sjkim        BIO_printf(bio_err,
168280297Sjkim                   "-apr1              MD5-based password algorithm, Apache variant\n");
169280297Sjkim# endif
170280297Sjkim        BIO_printf(bio_err, "-salt string       use provided salt\n");
171280297Sjkim        BIO_printf(bio_err, "-in file           read passwords from file\n");
172280297Sjkim        BIO_printf(bio_err, "-stdin             read passwords from stdin\n");
173280297Sjkim        BIO_printf(bio_err,
174280297Sjkim                   "-noverify          never verify when reading password from terminal\n");
175280297Sjkim        BIO_printf(bio_err, "-quiet             no warnings\n");
176280297Sjkim        BIO_printf(bio_err, "-table             format output as table\n");
177280297Sjkim        BIO_printf(bio_err, "-reverse           switch table columns\n");
17859191Skris
179280297Sjkim        goto err;
180280297Sjkim    }
18159191Skris
182280297Sjkim    if ((infile != NULL) || in_stdin) {
183280297Sjkim        in = BIO_new(BIO_s_file());
184280297Sjkim        if (in == NULL)
185280297Sjkim            goto err;
186280297Sjkim        if (infile != NULL) {
187280297Sjkim            assert(in_stdin == 0);
188280297Sjkim            if (BIO_read_filename(in, infile) <= 0)
189280297Sjkim                goto err;
190280297Sjkim        } else {
191280297Sjkim            assert(in_stdin);
192280297Sjkim            BIO_set_fp(in, stdin, BIO_NOCLOSE);
193280297Sjkim        }
194280297Sjkim    }
19568651Skris
196280297Sjkim    if (usecrypt)
197280297Sjkim        pw_maxlen = 8;
198280297Sjkim    else if (use1 || useapr1)
199280297Sjkim        pw_maxlen = 256;        /* arbitrary limit, should be enough for most
200280297Sjkim                                 * passwords */
20159191Skris
202280297Sjkim    if (passwds == NULL) {
203280297Sjkim        /* no passwords on the command line */
20459191Skris
205280297Sjkim        passwd_malloc_size = pw_maxlen + 2;
206280297Sjkim        /*
207280297Sjkim         * longer than necessary so that we can warn about truncation
208280297Sjkim         */
209280297Sjkim        passwd = passwd_malloc = OPENSSL_malloc(passwd_malloc_size);
210280297Sjkim        if (passwd_malloc == NULL)
211280297Sjkim            goto err;
212280297Sjkim    }
21359191Skris
214280297Sjkim    if ((in == NULL) && (passwds == NULL)) {
215280297Sjkim        /* build a null-terminated list */
216280297Sjkim        static char *passwds_static[2] = { NULL, NULL };
21759191Skris
218280297Sjkim        passwds = passwds_static;
219280297Sjkim        if (in == NULL)
220280297Sjkim            if (EVP_read_pw_string
221280297Sjkim                (passwd_malloc, passwd_malloc_size, "Password: ",
222280297Sjkim                 !(passed_salt || in_noverify)) != 0)
223280297Sjkim                goto err;
224280297Sjkim        passwds[0] = passwd_malloc;
225280297Sjkim    }
22659191Skris
227280297Sjkim    if (in == NULL) {
228280297Sjkim        assert(passwds != NULL);
229280297Sjkim        assert(*passwds != NULL);
23059191Skris
231280297Sjkim        do {                    /* loop over list of passwords */
232280297Sjkim            passwd = *passwds++;
233280297Sjkim            if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
234280297Sjkim                           quiet, table, reverse, pw_maxlen, usecrypt, use1,
235280297Sjkim                           useapr1))
236280297Sjkim                goto err;
237280297Sjkim        }
238280297Sjkim        while (*passwds != NULL);
239280297Sjkim    } else
240280297Sjkim        /* in != NULL */
241280297Sjkim    {
242280297Sjkim        int done;
243280297Sjkim
244280297Sjkim        assert(passwd != NULL);
245280297Sjkim        do {
246280297Sjkim            int r = BIO_gets(in, passwd, pw_maxlen + 1);
247280297Sjkim            if (r > 0) {
248280297Sjkim                char *c = (strchr(passwd, '\n'));
249280297Sjkim                if (c != NULL)
250280297Sjkim                    *c = 0;     /* truncate at newline */
251280297Sjkim                else {
252280297Sjkim                    /* ignore rest of line */
253280297Sjkim                    char trash[BUFSIZ];
254280297Sjkim                    do
255331638Sjkim                        r = BIO_gets(in, trash, sizeof(trash));
256280297Sjkim                    while ((r > 0) && (!strchr(trash, '\n')));
257280297Sjkim                }
258280297Sjkim
259280297Sjkim                if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
260280297Sjkim                               quiet, table, reverse, pw_maxlen, usecrypt,
261280297Sjkim                               use1, useapr1))
262280297Sjkim                    goto err;
263280297Sjkim            }
264280297Sjkim            done = (r <= 0);
265280297Sjkim        }
266280297Sjkim        while (!done);
267280297Sjkim    }
268280297Sjkim    ret = 0;
269280297Sjkim
270280297Sjkim err:
271280297Sjkim    ERR_print_errors(bio_err);
272280297Sjkim    if (salt_malloc)
273280297Sjkim        OPENSSL_free(salt_malloc);
274280297Sjkim    if (passwd_malloc)
275280297Sjkim        OPENSSL_free(passwd_malloc);
276280297Sjkim    if (in)
277280297Sjkim        BIO_free(in);
278280297Sjkim    if (out)
279280297Sjkim        BIO_free_all(out);
280280297Sjkim    apps_shutdown();
281280297Sjkim    OPENSSL_EXIT(ret);
282280297Sjkim}
283280297Sjkim
284280297Sjkim# ifndef NO_MD5CRYPT_1
285280297Sjkim/*
286280297Sjkim * MD5-based password algorithm (should probably be available as a library
287280297Sjkim * function; then the static buffer would not be acceptable). For magic
288280297Sjkim * string "1", this should be compatible to the MD5-based BSD password
289280297Sjkim * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
290280297Sjkim * Apache password algorithm. (Apparently, the Apache password algorithm is
291280297Sjkim * identical except that the 'magic' string was changed -- the laziest
292280297Sjkim * application of the NIH principle I've ever encountered.)
29368651Skris */
29468651Skrisstatic char *md5crypt(const char *passwd, const char *magic, const char *salt)
295280297Sjkim{
296280297Sjkim    /* "$apr1$..salt..$.......md5hash..........\0" */
297280297Sjkim    static char out_buf[6 + 9 + 24 + 2];
298280297Sjkim    unsigned char buf[MD5_DIGEST_LENGTH];
299280297Sjkim    char *salt_out;
300280297Sjkim    int n;
301280297Sjkim    unsigned int i;
302280297Sjkim    EVP_MD_CTX md, md2;
303280297Sjkim    size_t passwd_len, salt_len;
30459191Skris
305280297Sjkim    passwd_len = strlen(passwd);
306280297Sjkim    out_buf[0] = '$';
307280297Sjkim    out_buf[1] = 0;
308280297Sjkim    assert(strlen(magic) <= 4); /* "1" or "apr1" */
309337982Sjkim    BUF_strlcat(out_buf, magic, sizeof(out_buf));
310337982Sjkim    BUF_strlcat(out_buf, "$", sizeof(out_buf));
311337982Sjkim    BUF_strlcat(out_buf, salt, sizeof(out_buf));
312280297Sjkim    assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */
313280297Sjkim    salt_out = out_buf + 2 + strlen(magic);
314280297Sjkim    salt_len = strlen(salt_out);
315280297Sjkim    assert(salt_len <= 8);
31659191Skris
317280297Sjkim    EVP_MD_CTX_init(&md);
318280297Sjkim    EVP_DigestInit_ex(&md, EVP_md5(), NULL);
319280297Sjkim    EVP_DigestUpdate(&md, passwd, passwd_len);
320280297Sjkim    EVP_DigestUpdate(&md, "$", 1);
321280297Sjkim    EVP_DigestUpdate(&md, magic, strlen(magic));
322280297Sjkim    EVP_DigestUpdate(&md, "$", 1);
323280297Sjkim    EVP_DigestUpdate(&md, salt_out, salt_len);
32459191Skris
325280297Sjkim    EVP_MD_CTX_init(&md2);
326280297Sjkim    EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
327280297Sjkim    EVP_DigestUpdate(&md2, passwd, passwd_len);
328280297Sjkim    EVP_DigestUpdate(&md2, salt_out, salt_len);
329280297Sjkim    EVP_DigestUpdate(&md2, passwd, passwd_len);
330280297Sjkim    EVP_DigestFinal_ex(&md2, buf, NULL);
33159191Skris
332331638Sjkim    for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf))
333331638Sjkim        EVP_DigestUpdate(&md, buf, sizeof(buf));
334280297Sjkim    EVP_DigestUpdate(&md, buf, i);
33559191Skris
336280297Sjkim    n = passwd_len;
337280297Sjkim    while (n) {
338280297Sjkim        EVP_DigestUpdate(&md, (n & 1) ? "\0" : passwd, 1);
339280297Sjkim        n >>= 1;
340280297Sjkim    }
341280297Sjkim    EVP_DigestFinal_ex(&md, buf, NULL);
34259191Skris
343280297Sjkim    for (i = 0; i < 1000; i++) {
344280297Sjkim        EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
345280297Sjkim        EVP_DigestUpdate(&md2, (i & 1) ? (unsigned const char *)passwd : buf,
346331638Sjkim                         (i & 1) ? passwd_len : sizeof(buf));
347280297Sjkim        if (i % 3)
348280297Sjkim            EVP_DigestUpdate(&md2, salt_out, salt_len);
349280297Sjkim        if (i % 7)
350280297Sjkim            EVP_DigestUpdate(&md2, passwd, passwd_len);
351280297Sjkim        EVP_DigestUpdate(&md2, (i & 1) ? buf : (unsigned const char *)passwd,
352331638Sjkim                         (i & 1) ? sizeof(buf) : passwd_len);
353280297Sjkim        EVP_DigestFinal_ex(&md2, buf, NULL);
354280297Sjkim    }
355280297Sjkim    EVP_MD_CTX_cleanup(&md2);
35659191Skris
357280297Sjkim    {
358280297Sjkim        /* transform buf into output string */
35959191Skris
360331638Sjkim        unsigned char buf_perm[sizeof(buf)];
361280297Sjkim        int dest, source;
362280297Sjkim        char *output;
363280297Sjkim
364280297Sjkim        /* silly output permutation */
365280297Sjkim        for (dest = 0, source = 0; dest < 14;
366280297Sjkim             dest++, source = (source + 6) % 17)
367280297Sjkim            buf_perm[dest] = buf[source];
368280297Sjkim        buf_perm[14] = buf[5];
369280297Sjkim        buf_perm[15] = buf[11];
370280297Sjkim#  ifndef PEDANTIC              /* Unfortunately, this generates a "no
371280297Sjkim                                 * effect" warning */
372331638Sjkim        assert(16 == sizeof(buf_perm));
373280297Sjkim#  endif
374280297Sjkim
375280297Sjkim        output = salt_out + salt_len;
376280297Sjkim        assert(output == out_buf + strlen(out_buf));
377280297Sjkim
378280297Sjkim        *output++ = '$';
379280297Sjkim
380280297Sjkim        for (i = 0; i < 15; i += 3) {
381280297Sjkim            *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
382280297Sjkim            *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
383280297Sjkim                                  (buf_perm[i + 2] >> 6)];
384280297Sjkim            *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
385280297Sjkim                                  (buf_perm[i + 1] >> 4)];
386280297Sjkim            *output++ = cov_2char[buf_perm[i] >> 2];
387280297Sjkim        }
388280297Sjkim        assert(i == 15);
389280297Sjkim        *output++ = cov_2char[buf_perm[i] & 0x3f];
390280297Sjkim        *output++ = cov_2char[buf_perm[i] >> 6];
391280297Sjkim        *output = 0;
392280297Sjkim        assert(strlen(out_buf) < sizeof(out_buf));
393280297Sjkim    }
394280297Sjkim    EVP_MD_CTX_cleanup(&md);
395280297Sjkim
396280297Sjkim    return out_buf;
397280297Sjkim}
398280297Sjkim# endif
399280297Sjkim
40059191Skrisstatic int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
401280297Sjkim                     char *passwd, BIO *out, int quiet, int table,
402280297Sjkim                     int reverse, size_t pw_maxlen, int usecrypt, int use1,
403280297Sjkim                     int useapr1)
404280297Sjkim{
405280297Sjkim    char *hash = NULL;
40659191Skris
407280297Sjkim    assert(salt_p != NULL);
408280297Sjkim    assert(salt_malloc_p != NULL);
40959191Skris
410280297Sjkim    /* first make sure we have a salt */
411280297Sjkim    if (!passed_salt) {
412280297Sjkim# ifndef OPENSSL_NO_DES
413280297Sjkim        if (usecrypt) {
414280297Sjkim            if (*salt_malloc_p == NULL) {
415280297Sjkim                *salt_p = *salt_malloc_p = OPENSSL_malloc(3);
416280297Sjkim                if (*salt_malloc_p == NULL)
417280297Sjkim                    goto err;
418280297Sjkim            }
419306195Sjkim            if (RAND_bytes((unsigned char *)*salt_p, 2) <= 0)
420280297Sjkim                goto err;
421280297Sjkim            (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
422280297Sjkim            (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
423280297Sjkim            (*salt_p)[2] = 0;
424280297Sjkim#  ifdef CHARSET_EBCDIC
425280297Sjkim            ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert back
426280297Sjkim                                                * to ASCII */
427280297Sjkim#  endif
428280297Sjkim        }
429280297Sjkim# endif                         /* !OPENSSL_NO_DES */
43059191Skris
431280297Sjkim# ifndef NO_MD5CRYPT_1
432280297Sjkim        if (use1 || useapr1) {
433280297Sjkim            int i;
43459191Skris
435280297Sjkim            if (*salt_malloc_p == NULL) {
436280297Sjkim                *salt_p = *salt_malloc_p = OPENSSL_malloc(9);
437280297Sjkim                if (*salt_malloc_p == NULL)
438280297Sjkim                    goto err;
439280297Sjkim            }
440306195Sjkim            if (RAND_bytes((unsigned char *)*salt_p, 8) <= 0)
441280297Sjkim                goto err;
442280297Sjkim
443280297Sjkim            for (i = 0; i < 8; i++)
444280297Sjkim                (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
445280297Sjkim            (*salt_p)[8] = 0;
446280297Sjkim        }
447280297Sjkim# endif                         /* !NO_MD5CRYPT_1 */
448280297Sjkim    }
449280297Sjkim
450280297Sjkim    assert(*salt_p != NULL);
451280297Sjkim
452280297Sjkim    /* truncate password if necessary */
453280297Sjkim    if ((strlen(passwd) > pw_maxlen)) {
454280297Sjkim        if (!quiet)
455280297Sjkim            /*
456280297Sjkim             * XXX: really we should know how to print a size_t, not cast it
457280297Sjkim             */
458280297Sjkim            BIO_printf(bio_err,
459280297Sjkim                       "Warning: truncating password to %u characters\n",
460280297Sjkim                       (unsigned)pw_maxlen);
461280297Sjkim        passwd[pw_maxlen] = 0;
462280297Sjkim    }
463280297Sjkim    assert(strlen(passwd) <= pw_maxlen);
464280297Sjkim
465280297Sjkim    /* now compute password hash */
466280297Sjkim# ifndef OPENSSL_NO_DES
467280297Sjkim    if (usecrypt)
468280297Sjkim        hash = DES_crypt(passwd, *salt_p);
469280297Sjkim# endif
470280297Sjkim# ifndef NO_MD5CRYPT_1
471280297Sjkim    if (use1 || useapr1)
472280297Sjkim        hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p);
473280297Sjkim# endif
474280297Sjkim    assert(hash != NULL);
475280297Sjkim
476280297Sjkim    if (table && !reverse)
477280297Sjkim        BIO_printf(out, "%s\t%s\n", passwd, hash);
478280297Sjkim    else if (table && reverse)
479280297Sjkim        BIO_printf(out, "%s\t%s\n", hash, passwd);
480280297Sjkim    else
481280297Sjkim        BIO_printf(out, "%s\n", hash);
482280297Sjkim    return 1;
483280297Sjkim
484280297Sjkim err:
485280297Sjkim    return 0;
486280297Sjkim}
48759191Skris#else
48859191Skris
48959191Skrisint MAIN(int argc, char **argv)
490280297Sjkim{
491280297Sjkim    fputs("Program not available.\n", stderr)
492280297Sjkim        OPENSSL_EXIT(1);
493280297Sjkim}
49459191Skris#endif
495