Blame apps/passwd.c

Packit Service 084de1
/*
Packit Service 084de1
 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
Packit Service 084de1
 *
Packit Service 084de1
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit Service 084de1
 * this file except in compliance with the License.  You can obtain a copy
Packit Service 084de1
 * in the file LICENSE in the source distribution or at
Packit Service 084de1
 * https://www.openssl.org/source/license.html
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
#include <string.h>
Packit Service 084de1
Packit Service 084de1
#include "apps.h"
Packit Service 084de1
#include "progs.h"
Packit Service 084de1
Packit Service 084de1
#include <openssl/bio.h>
Packit Service 084de1
#include <openssl/err.h>
Packit Service 084de1
#include <openssl/evp.h>
Packit Service 084de1
#include <openssl/rand.h>
Packit Service 084de1
#ifndef OPENSSL_NO_DES
Packit Service 084de1
# include <openssl/des.h>
Packit Service 084de1
#endif
Packit Service 084de1
#include <openssl/md5.h>
Packit Service 084de1
#include <openssl/sha.h>
Packit Service 084de1
Packit Service 084de1
static unsigned const char cov_2char[64] = {
Packit Service 084de1
    /* from crypto/des/fcrypt.c */
Packit Service 084de1
    0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
Packit Service 084de1
    0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
Packit Service 084de1
    0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
Packit Service 084de1
    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
Packit Service 084de1
    0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
Packit Service 084de1
    0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
Packit Service 084de1
    0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
Packit Service 084de1
    0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
static const char ascii_dollar[] = { 0x24, 0x00 };
Packit Service 084de1
Packit Service 084de1
typedef enum {
Packit Service 084de1
    passwd_unset = 0,
Packit Service 084de1
    passwd_crypt,
Packit Service 084de1
    passwd_md5,
Packit Service 084de1
    passwd_apr1,
Packit Service 084de1
    passwd_sha256,
Packit Service 084de1
    passwd_sha512,
Packit Service 084de1
    passwd_aixmd5
Packit Service 084de1
} passwd_modes;
Packit Service 084de1
Packit Service 084de1
static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
Packit Service 084de1
                     char *passwd, BIO *out, int quiet, int table,
Packit Service 084de1
                     int reverse, size_t pw_maxlen, passwd_modes mode);
Packit Service 084de1
Packit Service 084de1
typedef enum OPTION_choice {
Packit Service 084de1
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
Packit Service 084de1
    OPT_IN,
Packit Service 084de1
    OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
Packit Service 084de1
    OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
Packit Service 084de1
    OPT_R_ENUM
Packit Service 084de1
} OPTION_CHOICE;
Packit Service 084de1
Packit Service 084de1
const OPTIONS passwd_options[] = {
Packit Service 084de1
    {"help", OPT_HELP, '-', "Display this summary"},
Packit Service 084de1
    {"in", OPT_IN, '<', "Read passwords from file"},
Packit Service 084de1
    {"noverify", OPT_NOVERIFY, '-',
Packit Service 084de1
     "Never verify when reading password from terminal"},
Packit Service 084de1
    {"quiet", OPT_QUIET, '-', "No warnings"},
Packit Service 084de1
    {"table", OPT_TABLE, '-', "Format output as table"},
Packit Service 084de1
    {"reverse", OPT_REVERSE, '-', "Switch table columns"},
Packit Service 084de1
    {"salt", OPT_SALT, 's', "Use provided salt"},
Packit Service 084de1
    {"stdin", OPT_STDIN, '-', "Read passwords from stdin"},
Packit Service 084de1
    {"6", OPT_6, '-', "SHA512-based password algorithm"},
Packit Service 084de1
    {"5", OPT_5, '-', "SHA256-based password algorithm"},
Packit Service 084de1
    {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"},
Packit Service 084de1
    {"1", OPT_1, '-', "MD5-based password algorithm"},
Packit Service 084de1
    {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"},
Packit Service 084de1
#ifndef OPENSSL_NO_DES
Packit Service 084de1
    {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"},
Packit Service 084de1
#endif
Packit Service 084de1
    OPT_R_OPTIONS,
Packit Service 084de1
    {NULL}
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
int passwd_main(int argc, char **argv)
Packit Service 084de1
{
Packit Service 084de1
    BIO *in = NULL;
Packit Service 084de1
    char *infile = NULL, *salt = NULL, *passwd = NULL, **passwds = NULL;
Packit Service 084de1
    char *salt_malloc = NULL, *passwd_malloc = NULL, *prog;
Packit Service 084de1
    OPTION_CHOICE o;
Packit Service 084de1
    int in_stdin = 0, pw_source_defined = 0;
Packit Service 084de1
#ifndef OPENSSL_NO_UI_CONSOLE
Packit Service 084de1
    int in_noverify = 0;
Packit Service 084de1
#endif
Packit Service 084de1
    int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
Packit Service 084de1
    int ret = 1;
Packit Service 084de1
    passwd_modes mode = passwd_unset;
Packit Service 084de1
    size_t passwd_malloc_size = 0;
Packit Service 084de1
    size_t pw_maxlen = 256; /* arbitrary limit, should be enough for most
Packit Service 084de1
                             * passwords */
Packit Service 084de1
Packit Service 084de1
    prog = opt_init(argc, argv, passwd_options);
Packit Service 084de1
    while ((o = opt_next()) != OPT_EOF) {
Packit Service 084de1
        switch (o) {
Packit Service 084de1
        case OPT_EOF:
Packit Service 084de1
        case OPT_ERR:
Packit Service 084de1
 opthelp:
Packit Service 084de1
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
Packit Service 084de1
            goto end;
Packit Service 084de1
        case OPT_HELP:
Packit Service 084de1
            opt_help(passwd_options);
Packit Service 084de1
            ret = 0;
Packit Service 084de1
            goto end;
Packit Service 084de1
        case OPT_IN:
Packit Service 084de1
            if (pw_source_defined)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            infile = opt_arg();
Packit Service 084de1
            pw_source_defined = 1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_NOVERIFY:
Packit Service 084de1
#ifndef OPENSSL_NO_UI_CONSOLE
Packit Service 084de1
            in_noverify = 1;
Packit Service 084de1
#endif
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_QUIET:
Packit Service 084de1
            quiet = 1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_TABLE:
Packit Service 084de1
            table = 1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_REVERSE:
Packit Service 084de1
            reverse = 1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_1:
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_md5;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_5:
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_sha256;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_6:
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_sha512;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_APR1:
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_apr1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_AIXMD5:
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_aixmd5;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_CRYPT:
Packit Service 084de1
#ifndef OPENSSL_NO_DES
Packit Service 084de1
            if (mode != passwd_unset)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            mode = passwd_crypt;
Packit Service 084de1
#endif
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_SALT:
Packit Service 084de1
            passed_salt = 1;
Packit Service 084de1
            salt = opt_arg();
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_STDIN:
Packit Service 084de1
            if (pw_source_defined)
Packit Service 084de1
                goto opthelp;
Packit Service 084de1
            in_stdin = 1;
Packit Service 084de1
            pw_source_defined = 1;
Packit Service 084de1
            break;
Packit Service 084de1
        case OPT_R_CASES:
Packit Service 084de1
            if (!opt_rand(o))
Packit Service 084de1
                goto end;
Packit Service 084de1
            break;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    argc = opt_num_rest();
Packit Service 084de1
    argv = opt_rest();
Packit Service 084de1
Packit Service 084de1
    if (*argv != NULL) {
Packit Service 084de1
        if (pw_source_defined)
Packit Service 084de1
            goto opthelp;
Packit Service 084de1
        pw_source_defined = 1;
Packit Service 084de1
        passwds = argv;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (mode == passwd_unset) {
Packit Service 084de1
        /* use default */
Packit Service 084de1
        mode = passwd_crypt;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
#ifdef OPENSSL_NO_DES
Packit Service 084de1
    if (mode == passwd_crypt)
Packit Service 084de1
        goto opthelp;
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    if (infile != NULL && in_stdin) {
Packit Service 084de1
        BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog);
Packit Service 084de1
        goto end;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (infile != NULL || in_stdin) {
Packit Service 084de1
        /*
Packit Service 084de1
         * If in_stdin is true, we know that infile is NULL, and that
Packit Service 084de1
         * bio_open_default() will give us back an alias for stdin.
Packit Service 084de1
         */
Packit Service 084de1
        in = bio_open_default(infile, 'r', FORMAT_TEXT);
Packit Service 084de1
        if (in == NULL)
Packit Service 084de1
            goto end;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (mode == passwd_crypt)
Packit Service 084de1
        pw_maxlen = 8;
Packit Service 084de1
Packit Service 084de1
    if (passwds == NULL) {
Packit Service 084de1
        /* no passwords on the command line */
Packit Service 084de1
Packit Service 084de1
        passwd_malloc_size = pw_maxlen + 2;
Packit Service 084de1
        /* longer than necessary so that we can warn about truncation */
Packit Service 084de1
        passwd = passwd_malloc =
Packit Service 084de1
            app_malloc(passwd_malloc_size, "password buffer");
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if ((in == NULL) && (passwds == NULL)) {
Packit Service 084de1
        /*
Packit Service 084de1
         * we use the following method to make sure what
Packit Service 084de1
         * in the 'else' section is always compiled, to
Packit Service 084de1
         * avoid rot of not-frequently-used code.
Packit Service 084de1
         */
Packit Service 084de1
        if (1) {
Packit Service 084de1
#ifndef OPENSSL_NO_UI_CONSOLE
Packit Service 084de1
            /* build a null-terminated list */
Packit Service 084de1
            static char *passwds_static[2] = { NULL, NULL };
Packit Service 084de1
Packit Service 084de1
            passwds = passwds_static;
Packit Service 084de1
            if (in == NULL) {
Packit Service 084de1
                if (EVP_read_pw_string
Packit Service 084de1
                    (passwd_malloc, passwd_malloc_size, "Password: ",
Packit Service 084de1
                     !(passed_salt || in_noverify)) != 0)
Packit Service 084de1
                    goto end;
Packit Service 084de1
            }
Packit Service 084de1
            passwds[0] = passwd_malloc;
Packit Service 084de1
        } else {
Packit Service 084de1
#endif
Packit Service 084de1
            BIO_printf(bio_err, "password required\n");
Packit Service 084de1
            goto end;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (in == NULL) {
Packit Service 084de1
        assert(passwds != NULL);
Packit Service 084de1
        assert(*passwds != NULL);
Packit Service 084de1
Packit Service 084de1
        do {                    /* loop over list of passwords */
Packit Service 084de1
            passwd = *passwds++;
Packit Service 084de1
            if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, bio_out,
Packit Service 084de1
                           quiet, table, reverse, pw_maxlen, mode))
Packit Service 084de1
                goto end;
Packit Service 084de1
        } while (*passwds != NULL);
Packit Service 084de1
    } else {
Packit Service 084de1
        /* in != NULL */
Packit Service 084de1
        int done;
Packit Service 084de1
Packit Service 084de1
        assert(passwd != NULL);
Packit Service 084de1
        do {
Packit Service 084de1
            int r = BIO_gets(in, passwd, pw_maxlen + 1);
Packit Service 084de1
            if (r > 0) {
Packit Service 084de1
                char *c = (strchr(passwd, '\n'));
Packit Service 084de1
                if (c != NULL) {
Packit Service 084de1
                    *c = 0;     /* truncate at newline */
Packit Service 084de1
                } else {
Packit Service 084de1
                    /* ignore rest of line */
Packit Service 084de1
                    char trash[BUFSIZ];
Packit Service 084de1
                    do
Packit Service 084de1
                        r = BIO_gets(in, trash, sizeof(trash));
Packit Service 084de1
                    while ((r > 0) && (!strchr(trash, '\n')));
Packit Service 084de1
                }
Packit Service 084de1
Packit Service 084de1
                if (!do_passwd
Packit Service 084de1
                    (passed_salt, &salt, &salt_malloc, passwd, bio_out, quiet,
Packit Service 084de1
                     table, reverse, pw_maxlen, mode))
Packit Service 084de1
                    goto end;
Packit Service 084de1
            }
Packit Service 084de1
            done = (r <= 0);
Packit Service 084de1
        } while (!done);
Packit Service 084de1
    }
Packit Service 084de1
    ret = 0;
Packit Service 084de1
Packit Service 084de1
 end:
Packit Service 084de1
#if 0
Packit Service 084de1
    ERR_print_errors(bio_err);
Packit Service 084de1
#endif
Packit Service 084de1
    OPENSSL_free(salt_malloc);
Packit Service 084de1
    OPENSSL_free(passwd_malloc);
Packit Service 084de1
    BIO_free(in);
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * MD5-based password algorithm (should probably be available as a library
Packit Service 084de1
 * function; then the static buffer would not be acceptable). For magic
Packit Service 084de1
 * string "1", this should be compatible to the MD5-based BSD password
Packit Service 084de1
 * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
Packit Service 084de1
 * Apache password algorithm. (Apparently, the Apache password algorithm is
Packit Service 084de1
 * identical except that the 'magic' string was changed -- the laziest
Packit Service 084de1
 * application of the NIH principle I've ever encountered.)
Packit Service 084de1
 */
Packit Service 084de1
static char *md5crypt(const char *passwd, const char *magic, const char *salt)
Packit Service 084de1
{
Packit Service 084de1
    /* "$apr1$..salt..$.......md5hash..........\0" */
Packit Service 084de1
    static char out_buf[6 + 9 + 24 + 2];
Packit Service 084de1
    unsigned char buf[MD5_DIGEST_LENGTH];
Packit Service 084de1
    char ascii_magic[5];         /* "apr1" plus '\0' */
Packit Service 084de1
    char ascii_salt[9];          /* Max 8 chars plus '\0' */
Packit Service 084de1
    char *ascii_passwd = NULL;
Packit Service 084de1
    char *salt_out;
Packit Service 084de1
    int n;
Packit Service 084de1
    unsigned int i;
Packit Service 084de1
    EVP_MD_CTX *md = NULL, *md2 = NULL;
Packit Service 084de1
    size_t passwd_len, salt_len, magic_len;
Packit Service 084de1
Packit Service 084de1
    passwd_len = strlen(passwd);
Packit Service 084de1
Packit Service 084de1
    out_buf[0] = 0;
Packit Service 084de1
    magic_len = strlen(magic);
Packit Service 084de1
    OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    if ((magic[0] & 0x80) != 0)    /* High bit is 1 in EBCDIC alnums */
Packit Service 084de1
        ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    /* The salt gets truncated to 8 chars */
Packit Service 084de1
    OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
Packit Service 084de1
    salt_len = strlen(ascii_salt);
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    ascii_passwd = OPENSSL_strdup(passwd);
Packit Service 084de1
    if (ascii_passwd == NULL)
Packit Service 084de1
        return NULL;
Packit Service 084de1
    ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
Packit Service 084de1
    passwd = ascii_passwd;
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    if (magic_len > 0) {
Packit Service 084de1
        OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
Packit Service 084de1
Packit Service 084de1
        if (magic_len > 4)    /* assert it's  "1" or "apr1" */
Packit Service 084de1
            goto err;
Packit Service 084de1
Packit Service 084de1
        OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
Packit Service 084de1
        OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
Packit Service 084de1
Packit Service 084de1
    if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    salt_out = out_buf;
Packit Service 084de1
    if (magic_len > 0)
Packit Service 084de1
        salt_out += 2 + magic_len;
Packit Service 084de1
Packit Service 084de1
    if (salt_len > 8)
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    md = EVP_MD_CTX_new();
Packit Service 084de1
    if (md == NULL
Packit Service 084de1
        || !EVP_DigestInit_ex(md, EVP_md5(), NULL)
Packit Service 084de1
        || !EVP_DigestUpdate(md, passwd, passwd_len))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    if (magic_len > 0)
Packit Service 084de1
        if (!EVP_DigestUpdate(md, ascii_dollar, 1)
Packit Service 084de1
            || !EVP_DigestUpdate(md, ascii_magic, magic_len)
Packit Service 084de1
            || !EVP_DigestUpdate(md, ascii_dollar, 1))
Packit Service 084de1
          goto err;
Packit Service 084de1
Packit Service 084de1
    if (!EVP_DigestUpdate(md, ascii_salt, salt_len))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    md2 = EVP_MD_CTX_new();
Packit Service 084de1
    if (md2 == NULL
Packit Service 084de1
        || !EVP_DigestInit_ex(md2, EVP_md5(), NULL)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, passwd, passwd_len)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, ascii_salt, salt_len)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, passwd, passwd_len)
Packit Service 084de1
        || !EVP_DigestFinal_ex(md2, buf, NULL))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    for (i = passwd_len; i > sizeof(buf); i -= sizeof(buf)) {
Packit Service 084de1
        if (!EVP_DigestUpdate(md, buf, sizeof(buf)))
Packit Service 084de1
            goto err;
Packit Service 084de1
    }
Packit Service 084de1
    if (!EVP_DigestUpdate(md, buf, i))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    n = passwd_len;
Packit Service 084de1
    while (n) {
Packit Service 084de1
        if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1))
Packit Service 084de1
            goto err;
Packit Service 084de1
        n >>= 1;
Packit Service 084de1
    }
Packit Service 084de1
    if (!EVP_DigestFinal_ex(md, buf, NULL))
Packit Service 084de1
        return NULL;
Packit Service 084de1
Packit Service 084de1
    for (i = 0; i < 1000; i++) {
Packit Service 084de1
        if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL))
Packit Service 084de1
            goto err;
Packit Service 084de1
        if (!EVP_DigestUpdate(md2,
Packit Service 084de1
                              (i & 1) ? (unsigned const char *)passwd : buf,
Packit Service 084de1
                              (i & 1) ? passwd_len : sizeof(buf)))
Packit Service 084de1
            goto err;
Packit Service 084de1
        if (i % 3) {
Packit Service 084de1
            if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        }
Packit Service 084de1
        if (i % 7) {
Packit Service 084de1
            if (!EVP_DigestUpdate(md2, passwd, passwd_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        }
Packit Service 084de1
        if (!EVP_DigestUpdate(md2,
Packit Service 084de1
                              (i & 1) ? buf : (unsigned const char *)passwd,
Packit Service 084de1
                              (i & 1) ? sizeof(buf) : passwd_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        if (!EVP_DigestFinal_ex(md2, buf, NULL))
Packit Service 084de1
                goto err;
Packit Service 084de1
    }
Packit Service 084de1
    EVP_MD_CTX_free(md2);
Packit Service 084de1
    EVP_MD_CTX_free(md);
Packit Service 084de1
    md2 = NULL;
Packit Service 084de1
    md = NULL;
Packit Service 084de1
Packit Service 084de1
    {
Packit Service 084de1
        /* transform buf into output string */
Packit Service 084de1
        unsigned char buf_perm[sizeof(buf)];
Packit Service 084de1
        int dest, source;
Packit Service 084de1
        char *output;
Packit Service 084de1
Packit Service 084de1
        /* silly output permutation */
Packit Service 084de1
        for (dest = 0, source = 0; dest < 14;
Packit Service 084de1
             dest++, source = (source + 6) % 17)
Packit Service 084de1
            buf_perm[dest] = buf[source];
Packit Service 084de1
        buf_perm[14] = buf[5];
Packit Service 084de1
        buf_perm[15] = buf[11];
Packit Service 084de1
# ifndef PEDANTIC              /* Unfortunately, this generates a "no
Packit Service 084de1
                                 * effect" warning */
Packit Service 084de1
        assert(16 == sizeof(buf_perm));
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
        output = salt_out + salt_len;
Packit Service 084de1
        assert(output == out_buf + strlen(out_buf));
Packit Service 084de1
Packit Service 084de1
        *output++ = ascii_dollar[0];
Packit Service 084de1
Packit Service 084de1
        for (i = 0; i < 15; i += 3) {
Packit Service 084de1
            *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
Packit Service 084de1
            *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
Packit Service 084de1
                                  (buf_perm[i + 2] >> 6)];
Packit Service 084de1
            *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
Packit Service 084de1
                                  (buf_perm[i + 1] >> 4)];
Packit Service 084de1
            *output++ = cov_2char[buf_perm[i] >> 2];
Packit Service 084de1
        }
Packit Service 084de1
        assert(i == 15);
Packit Service 084de1
        *output++ = cov_2char[buf_perm[i] & 0x3f];
Packit Service 084de1
        *output++ = cov_2char[buf_perm[i] >> 6];
Packit Service 084de1
        *output = 0;
Packit Service 084de1
        assert(strlen(out_buf) < sizeof(out_buf));
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
        ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
Packit Service 084de1
#endif
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    return out_buf;
Packit Service 084de1
Packit Service 084de1
 err:
Packit Service 084de1
    OPENSSL_free(ascii_passwd);
Packit Service 084de1
    EVP_MD_CTX_free(md2);
Packit Service 084de1
    EVP_MD_CTX_free(md);
Packit Service 084de1
    return NULL;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * SHA based password algorithm, describe by Ulrich Drepper here:
Packit Service 084de1
 * https://www.akkadia.org/drepper/SHA-crypt.txt
Packit Service 084de1
 * (note that it's in the public domain)
Packit Service 084de1
 */
Packit Service 084de1
static char *shacrypt(const char *passwd, const char *magic, const char *salt)
Packit Service 084de1
{
Packit Service 084de1
    /* Prefix for optional rounds specification.  */
Packit Service 084de1
    static const char rounds_prefix[] = "rounds=";
Packit Service 084de1
    /* Maximum salt string length.  */
Packit Service 084de1
# define SALT_LEN_MAX 16
Packit Service 084de1
    /* Default number of rounds if not explicitly specified.  */
Packit Service 084de1
# define ROUNDS_DEFAULT 5000
Packit Service 084de1
    /* Minimum number of rounds.  */
Packit Service 084de1
# define ROUNDS_MIN 1000
Packit Service 084de1
    /* Maximum number of rounds.  */
Packit Service 084de1
# define ROUNDS_MAX 999999999
Packit Service 084de1
Packit Service 084de1
    /* "$6$rounds=<N>$......salt......$...shahash(up to 86 chars)...\0" */
Packit Service 084de1
    static char out_buf[3 + 17 + 17 + 86 + 1];
Packit Service 084de1
    unsigned char buf[SHA512_DIGEST_LENGTH];
Packit Service 084de1
    unsigned char temp_buf[SHA512_DIGEST_LENGTH];
Packit Service 084de1
    size_t buf_size = 0;
Packit Service 084de1
    char ascii_magic[2];
Packit Service 084de1
    char ascii_salt[17];          /* Max 16 chars plus '\0' */
Packit Service 084de1
    char *ascii_passwd = NULL;
Packit Service 084de1
    size_t n;
Packit Service 084de1
    EVP_MD_CTX *md = NULL, *md2 = NULL;
Packit Service 084de1
    const EVP_MD *sha = NULL;
Packit Service 084de1
    size_t passwd_len, salt_len, magic_len;
Packit Service 084de1
    unsigned int rounds = 5000;        /* Default */
Packit Service 084de1
    char rounds_custom = 0;
Packit Service 084de1
    char *p_bytes = NULL;
Packit Service 084de1
    char *s_bytes = NULL;
Packit Service 084de1
    char *cp = NULL;
Packit Service 084de1
Packit Service 084de1
    passwd_len = strlen(passwd);
Packit Service 084de1
    magic_len = strlen(magic);
Packit Service 084de1
Packit Service 084de1
    /* assert it's "5" or "6" */
Packit Service 084de1
    if (magic_len != 1)
Packit Service 084de1
        return NULL;
Packit Service 084de1
Packit Service 084de1
    switch (magic[0]) {
Packit Service 084de1
    case '5':
Packit Service 084de1
        sha = EVP_sha256();
Packit Service 084de1
        buf_size = 32;
Packit Service 084de1
        break;
Packit Service 084de1
    case '6':
Packit Service 084de1
        sha = EVP_sha512();
Packit Service 084de1
        buf_size = 64;
Packit Service 084de1
        break;
Packit Service 084de1
    default:
Packit Service 084de1
        return NULL;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    if (strncmp(salt, rounds_prefix, sizeof(rounds_prefix) - 1) == 0) {
Packit Service 084de1
        const char *num = salt + sizeof(rounds_prefix) - 1;
Packit Service 084de1
        char *endp;
Packit Service 084de1
        unsigned long int srounds = strtoul (num, &endp, 10);
Packit Service 084de1
        if (*endp == '$') {
Packit Service 084de1
            salt = endp + 1;
Packit Service 084de1
            if (srounds > ROUNDS_MAX)
Packit Service 084de1
                rounds = ROUNDS_MAX;
Packit Service 084de1
            else if (srounds < ROUNDS_MIN)
Packit Service 084de1
                rounds = ROUNDS_MIN;
Packit Service 084de1
            else
Packit Service 084de1
                rounds = (unsigned int)srounds;
Packit Service 084de1
            rounds_custom = 1;
Packit Service 084de1
        } else {
Packit Service 084de1
            return NULL;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    OPENSSL_strlcpy(ascii_magic, magic, sizeof(ascii_magic));
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    if ((magic[0] & 0x80) != 0)    /* High bit is 1 in EBCDIC alnums */
Packit Service 084de1
        ebcdic2ascii(ascii_magic, ascii_magic, magic_len);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    /* The salt gets truncated to 16 chars */
Packit Service 084de1
    OPENSSL_strlcpy(ascii_salt, salt, sizeof(ascii_salt));
Packit Service 084de1
    salt_len = strlen(ascii_salt);
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    ebcdic2ascii(ascii_salt, ascii_salt, salt_len);
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    ascii_passwd = OPENSSL_strdup(passwd);
Packit Service 084de1
    if (ascii_passwd == NULL)
Packit Service 084de1
        return NULL;
Packit Service 084de1
    ebcdic2ascii(ascii_passwd, ascii_passwd, passwd_len);
Packit Service 084de1
    passwd = ascii_passwd;
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    out_buf[0] = 0;
Packit Service 084de1
    OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
Packit Service 084de1
    OPENSSL_strlcat(out_buf, ascii_magic, sizeof(out_buf));
Packit Service 084de1
    OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
Packit Service 084de1
    if (rounds_custom) {
Packit Service 084de1
        char tmp_buf[80]; /* "rounds=999999999" */
Packit Service 084de1
        sprintf(tmp_buf, "rounds=%u", rounds);
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
        /* In case we're really on a ASCII based platform and just pretend */
Packit Service 084de1
        if (tmp_buf[0] != 0x72)  /* ASCII 'r' */
Packit Service 084de1
            ebcdic2ascii(tmp_buf, tmp_buf, strlen(tmp_buf));
Packit Service 084de1
#endif
Packit Service 084de1
        OPENSSL_strlcat(out_buf, tmp_buf, sizeof(out_buf));
Packit Service 084de1
        OPENSSL_strlcat(out_buf, ascii_dollar, sizeof(out_buf));
Packit Service 084de1
    }
Packit Service 084de1
    OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf));
Packit Service 084de1
Packit Service 084de1
    /* assert "$5$rounds=999999999$......salt......" */
Packit Service 084de1
    if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len )
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    md = EVP_MD_CTX_new();
Packit Service 084de1
    if (md == NULL
Packit Service 084de1
        || !EVP_DigestInit_ex(md, sha, NULL)
Packit Service 084de1
        || !EVP_DigestUpdate(md, passwd, passwd_len)
Packit Service 084de1
        || !EVP_DigestUpdate(md, ascii_salt, salt_len))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    md2 = EVP_MD_CTX_new();
Packit Service 084de1
    if (md2 == NULL
Packit Service 084de1
        || !EVP_DigestInit_ex(md2, sha, NULL)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, passwd, passwd_len)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, ascii_salt, salt_len)
Packit Service 084de1
        || !EVP_DigestUpdate(md2, passwd, passwd_len)
Packit Service 084de1
        || !EVP_DigestFinal_ex(md2, buf, NULL))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    for (n = passwd_len; n > buf_size; n -= buf_size) {
Packit Service 084de1
        if (!EVP_DigestUpdate(md, buf, buf_size))
Packit Service 084de1
            goto err;
Packit Service 084de1
    }
Packit Service 084de1
    if (!EVP_DigestUpdate(md, buf, n))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    n = passwd_len;
Packit Service 084de1
    while (n) {
Packit Service 084de1
        if (!EVP_DigestUpdate(md,
Packit Service 084de1
                              (n & 1) ? buf : (unsigned const char *)passwd,
Packit Service 084de1
                              (n & 1) ? buf_size : passwd_len))
Packit Service 084de1
            goto err;
Packit Service 084de1
        n >>= 1;
Packit Service 084de1
    }
Packit Service 084de1
    if (!EVP_DigestFinal_ex(md, buf, NULL))
Packit Service 084de1
        return NULL;
Packit Service 084de1
Packit Service 084de1
    /* P sequence */
Packit Service 084de1
    if (!EVP_DigestInit_ex(md2, sha, NULL))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    for (n = passwd_len; n > 0; n--)
Packit Service 084de1
        if (!EVP_DigestUpdate(md2, passwd, passwd_len))
Packit Service 084de1
            goto err;
Packit Service 084de1
Packit Service 084de1
    if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
Packit Service 084de1
        return NULL;
Packit Service 084de1
Packit Service 084de1
    if ((p_bytes = OPENSSL_zalloc(passwd_len)) == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    for (cp = p_bytes, n = passwd_len; n > buf_size; n -= buf_size, cp += buf_size)
Packit Service 084de1
        memcpy(cp, temp_buf, buf_size);
Packit Service 084de1
    memcpy(cp, temp_buf, n);
Packit Service 084de1
Packit Service 084de1
    /* S sequence */
Packit Service 084de1
    if (!EVP_DigestInit_ex(md2, sha, NULL))
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    for (n = 16 + buf[0]; n > 0; n--)
Packit Service 084de1
        if (!EVP_DigestUpdate(md2, ascii_salt, salt_len))
Packit Service 084de1
            goto err;
Packit Service 084de1
Packit Service 084de1
    if (!EVP_DigestFinal_ex(md2, temp_buf, NULL))
Packit Service 084de1
        return NULL;
Packit Service 084de1
Packit Service 084de1
    if ((s_bytes = OPENSSL_zalloc(salt_len)) == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    for (cp = s_bytes, n = salt_len; n > buf_size; n -= buf_size, cp += buf_size)
Packit Service 084de1
        memcpy(cp, temp_buf, buf_size);
Packit Service 084de1
    memcpy(cp, temp_buf, n);
Packit Service 084de1
Packit Service 084de1
    for (n = 0; n < rounds; n++) {
Packit Service 084de1
        if (!EVP_DigestInit_ex(md2, sha, NULL))
Packit Service 084de1
            goto err;
Packit Service 084de1
        if (!EVP_DigestUpdate(md2,
Packit Service 084de1
                              (n & 1) ? (unsigned const char *)p_bytes : buf,
Packit Service 084de1
                              (n & 1) ? passwd_len : buf_size))
Packit Service 084de1
            goto err;
Packit Service 084de1
        if (n % 3) {
Packit Service 084de1
            if (!EVP_DigestUpdate(md2, s_bytes, salt_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        }
Packit Service 084de1
        if (n % 7) {
Packit Service 084de1
            if (!EVP_DigestUpdate(md2, p_bytes, passwd_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        }
Packit Service 084de1
        if (!EVP_DigestUpdate(md2,
Packit Service 084de1
                              (n & 1) ? buf : (unsigned const char *)p_bytes,
Packit Service 084de1
                              (n & 1) ? buf_size : passwd_len))
Packit Service 084de1
                goto err;
Packit Service 084de1
        if (!EVP_DigestFinal_ex(md2, buf, NULL))
Packit Service 084de1
                goto err;
Packit Service 084de1
    }
Packit Service 084de1
    EVP_MD_CTX_free(md2);
Packit Service 084de1
    EVP_MD_CTX_free(md);
Packit Service 084de1
    md2 = NULL;
Packit Service 084de1
    md = NULL;
Packit Service 084de1
    OPENSSL_free(p_bytes);
Packit Service 084de1
    OPENSSL_free(s_bytes);
Packit Service 084de1
    p_bytes = NULL;
Packit Service 084de1
    s_bytes = NULL;
Packit Service 084de1
Packit Service 084de1
    cp = out_buf + strlen(out_buf);
Packit Service 084de1
    *cp++ = ascii_dollar[0];
Packit Service 084de1
Packit Service 084de1
# define b64_from_24bit(B2, B1, B0, N)                                   \
Packit Service 084de1
    do {                                                                \
Packit Service 084de1
        unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);             \
Packit Service 084de1
        int i = (N);                                                    \
Packit Service 084de1
        while (i-- > 0)                                                 \
Packit Service 084de1
            {                                                           \
Packit Service 084de1
                *cp++ = cov_2char[w & 0x3f];                            \
Packit Service 084de1
                w >>= 6;                                                \
Packit Service 084de1
            }                                                           \
Packit Service 084de1
    } while (0)
Packit Service 084de1
Packit Service 084de1
    switch (magic[0]) {
Packit Service 084de1
    case '5':
Packit Service 084de1
        b64_from_24bit (buf[0], buf[10], buf[20], 4);
Packit Service 084de1
        b64_from_24bit (buf[21], buf[1], buf[11], 4);
Packit Service 084de1
        b64_from_24bit (buf[12], buf[22], buf[2], 4);
Packit Service 084de1
        b64_from_24bit (buf[3], buf[13], buf[23], 4);
Packit Service 084de1
        b64_from_24bit (buf[24], buf[4], buf[14], 4);
Packit Service 084de1
        b64_from_24bit (buf[15], buf[25], buf[5], 4);
Packit Service 084de1
        b64_from_24bit (buf[6], buf[16], buf[26], 4);
Packit Service 084de1
        b64_from_24bit (buf[27], buf[7], buf[17], 4);
Packit Service 084de1
        b64_from_24bit (buf[18], buf[28], buf[8], 4);
Packit Service 084de1
        b64_from_24bit (buf[9], buf[19], buf[29], 4);
Packit Service 084de1
        b64_from_24bit (0, buf[31], buf[30], 3);
Packit Service 084de1
        break;
Packit Service 084de1
    case '6':
Packit Service 084de1
        b64_from_24bit (buf[0], buf[21], buf[42], 4);
Packit Service 084de1
        b64_from_24bit (buf[22], buf[43], buf[1], 4);
Packit Service 084de1
        b64_from_24bit (buf[44], buf[2], buf[23], 4);
Packit Service 084de1
        b64_from_24bit (buf[3], buf[24], buf[45], 4);
Packit Service 084de1
        b64_from_24bit (buf[25], buf[46], buf[4], 4);
Packit Service 084de1
        b64_from_24bit (buf[47], buf[5], buf[26], 4);
Packit Service 084de1
        b64_from_24bit (buf[6], buf[27], buf[48], 4);
Packit Service 084de1
        b64_from_24bit (buf[28], buf[49], buf[7], 4);
Packit Service 084de1
        b64_from_24bit (buf[50], buf[8], buf[29], 4);
Packit Service 084de1
        b64_from_24bit (buf[9], buf[30], buf[51], 4);
Packit Service 084de1
        b64_from_24bit (buf[31], buf[52], buf[10], 4);
Packit Service 084de1
        b64_from_24bit (buf[53], buf[11], buf[32], 4);
Packit Service 084de1
        b64_from_24bit (buf[12], buf[33], buf[54], 4);
Packit Service 084de1
        b64_from_24bit (buf[34], buf[55], buf[13], 4);
Packit Service 084de1
        b64_from_24bit (buf[56], buf[14], buf[35], 4);
Packit Service 084de1
        b64_from_24bit (buf[15], buf[36], buf[57], 4);
Packit Service 084de1
        b64_from_24bit (buf[37], buf[58], buf[16], 4);
Packit Service 084de1
        b64_from_24bit (buf[59], buf[17], buf[38], 4);
Packit Service 084de1
        b64_from_24bit (buf[18], buf[39], buf[60], 4);
Packit Service 084de1
        b64_from_24bit (buf[40], buf[61], buf[19], 4);
Packit Service 084de1
        b64_from_24bit (buf[62], buf[20], buf[41], 4);
Packit Service 084de1
        b64_from_24bit (0, 0, buf[63], 2);
Packit Service 084de1
        break;
Packit Service 084de1
    default:
Packit Service 084de1
        goto err;
Packit Service 084de1
    }
Packit Service 084de1
    *cp = '\0';
Packit Service 084de1
#ifdef CHARSET_EBCDIC
Packit Service 084de1
    ascii2ebcdic(out_buf, out_buf, strlen(out_buf));
Packit Service 084de1
#endif
Packit Service 084de1
Packit Service 084de1
    return out_buf;
Packit Service 084de1
Packit Service 084de1
 err:
Packit Service 084de1
    EVP_MD_CTX_free(md2);
Packit Service 084de1
    EVP_MD_CTX_free(md);
Packit Service 084de1
    OPENSSL_free(p_bytes);
Packit Service 084de1
    OPENSSL_free(s_bytes);
Packit Service 084de1
    OPENSSL_free(ascii_passwd);
Packit Service 084de1
    return NULL;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
Packit Service 084de1
                     char *passwd, BIO *out, int quiet, int table,
Packit Service 084de1
                     int reverse, size_t pw_maxlen, passwd_modes mode)
Packit Service 084de1
{
Packit Service 084de1
    char *hash = NULL;
Packit Service 084de1
Packit Service 084de1
    assert(salt_p != NULL);
Packit Service 084de1
    assert(salt_malloc_p != NULL);
Packit Service 084de1
Packit Service 084de1
    /* first make sure we have a salt */
Packit Service 084de1
    if (!passed_salt) {
Packit Service 084de1
        size_t saltlen = 0;
Packit Service 084de1
        size_t i;
Packit Service 084de1
Packit Service 084de1
#ifndef OPENSSL_NO_DES
Packit Service 084de1
        if (mode == passwd_crypt)
Packit Service 084de1
            saltlen = 2;
Packit Service 084de1
#endif                         /* !OPENSSL_NO_DES */
Packit Service 084de1
Packit Service 084de1
        if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5)
Packit Service 084de1
            saltlen = 8;
Packit Service 084de1
Packit Service 084de1
        if (mode == passwd_sha256 || mode == passwd_sha512)
Packit Service 084de1
            saltlen = 16;
Packit Service 084de1
Packit Service 084de1
        assert(saltlen != 0);
Packit Service 084de1
Packit Service 084de1
        if (*salt_malloc_p == NULL)
Packit Service 084de1
            *salt_p = *salt_malloc_p = app_malloc(saltlen + 1, "salt buffer");
Packit Service 084de1
        if (RAND_bytes((unsigned char *)*salt_p, saltlen) <= 0)
Packit Service 084de1
            goto end;
Packit Service 084de1
Packit Service 084de1
        for (i = 0; i < saltlen; i++)
Packit Service 084de1
            (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
Packit Service 084de1
        (*salt_p)[i] = 0;
Packit Service 084de1
# ifdef CHARSET_EBCDIC
Packit Service 084de1
        /* The password encryption function will convert back to ASCII */
Packit Service 084de1
        ascii2ebcdic(*salt_p, *salt_p, saltlen);
Packit Service 084de1
# endif
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    assert(*salt_p != NULL);
Packit Service 084de1
Packit Service 084de1
    /* truncate password if necessary */
Packit Service 084de1
    if ((strlen(passwd) > pw_maxlen)) {
Packit Service 084de1
        if (!quiet)
Packit Service 084de1
            /*
Packit Service 084de1
             * XXX: really we should know how to print a size_t, not cast it
Packit Service 084de1
             */
Packit Service 084de1
            BIO_printf(bio_err,
Packit Service 084de1
                       "Warning: truncating password to %u characters\n",
Packit Service 084de1
                       (unsigned)pw_maxlen);
Packit Service 084de1
        passwd[pw_maxlen] = 0;
Packit Service 084de1
    }
Packit Service 084de1
    assert(strlen(passwd) <= pw_maxlen);
Packit Service 084de1
Packit Service 084de1
    /* now compute password hash */
Packit Service 084de1
#ifndef OPENSSL_NO_DES
Packit Service 084de1
    if (mode == passwd_crypt)
Packit Service 084de1
        hash = DES_crypt(passwd, *salt_p);
Packit Service 084de1
#endif
Packit Service 084de1
    if (mode == passwd_md5 || mode == passwd_apr1)
Packit Service 084de1
        hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p);
Packit Service 084de1
    if (mode == passwd_aixmd5)
Packit Service 084de1
        hash = md5crypt(passwd, "", *salt_p);
Packit Service 084de1
    if (mode == passwd_sha256 || mode == passwd_sha512)
Packit Service 084de1
        hash = shacrypt(passwd, (mode == passwd_sha256 ? "5" : "6"), *salt_p);
Packit Service 084de1
    assert(hash != NULL);
Packit Service 084de1
Packit Service 084de1
    if (table && !reverse)
Packit Service 084de1
        BIO_printf(out, "%s\t%s\n", passwd, hash);
Packit Service 084de1
    else if (table && reverse)
Packit Service 084de1
        BIO_printf(out, "%s\t%s\n", hash, passwd);
Packit Service 084de1
    else
Packit Service 084de1
        BIO_printf(out, "%s\n", hash);
Packit Service 084de1
    return 1;
Packit Service 084de1
Packit Service 084de1
 end:
Packit Service 084de1
    return 0;
Packit Service 084de1
}