10Sstevel@tonic-gate /* apps/passwd.c */
20Sstevel@tonic-gate
30Sstevel@tonic-gate #if defined OPENSSL_NO_MD5 || defined CHARSET_EBCDIC
40Sstevel@tonic-gate # define NO_MD5CRYPT_1
50Sstevel@tonic-gate #endif
60Sstevel@tonic-gate
70Sstevel@tonic-gate #if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1)
80Sstevel@tonic-gate
90Sstevel@tonic-gate #include <assert.h>
100Sstevel@tonic-gate #include <string.h>
110Sstevel@tonic-gate
120Sstevel@tonic-gate #include "apps.h"
130Sstevel@tonic-gate
140Sstevel@tonic-gate #include <openssl/bio.h>
150Sstevel@tonic-gate #include <openssl/err.h>
160Sstevel@tonic-gate #include <openssl/evp.h>
170Sstevel@tonic-gate #include <openssl/rand.h>
180Sstevel@tonic-gate #ifndef OPENSSL_NO_DES
190Sstevel@tonic-gate # include <openssl/des.h>
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate #ifndef NO_MD5CRYPT_1
220Sstevel@tonic-gate # include <openssl/md5.h>
230Sstevel@tonic-gate #endif
240Sstevel@tonic-gate
250Sstevel@tonic-gate
260Sstevel@tonic-gate #undef PROG
270Sstevel@tonic-gate #define PROG passwd_main
280Sstevel@tonic-gate
290Sstevel@tonic-gate
300Sstevel@tonic-gate static unsigned const char cov_2char[64]={
310Sstevel@tonic-gate /* from crypto/des/fcrypt.c */
320Sstevel@tonic-gate 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
330Sstevel@tonic-gate 0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,
340Sstevel@tonic-gate 0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,
350Sstevel@tonic-gate 0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,
360Sstevel@tonic-gate 0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,
370Sstevel@tonic-gate 0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
380Sstevel@tonic-gate 0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,
390Sstevel@tonic-gate 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A
400Sstevel@tonic-gate };
410Sstevel@tonic-gate
420Sstevel@tonic-gate static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
430Sstevel@tonic-gate char *passwd, BIO *out, int quiet, int table, int reverse,
440Sstevel@tonic-gate size_t pw_maxlen, int usecrypt, int use1, int useapr1);
450Sstevel@tonic-gate
460Sstevel@tonic-gate /* -crypt - standard Unix password algorithm (default)
470Sstevel@tonic-gate * -1 - MD5-based password algorithm
480Sstevel@tonic-gate * -apr1 - MD5-based password algorithm, Apache variant
490Sstevel@tonic-gate * -salt string - salt
500Sstevel@tonic-gate * -in file - read passwords from file
510Sstevel@tonic-gate * -stdin - read passwords from stdin
520Sstevel@tonic-gate * -noverify - never verify when reading password from terminal
530Sstevel@tonic-gate * -quiet - no warnings
540Sstevel@tonic-gate * -table - format output as table
550Sstevel@tonic-gate * -reverse - switch table columns
560Sstevel@tonic-gate */
570Sstevel@tonic-gate
580Sstevel@tonic-gate int MAIN(int, char **);
590Sstevel@tonic-gate
MAIN(int argc,char ** argv)600Sstevel@tonic-gate int MAIN(int argc, char **argv)
610Sstevel@tonic-gate {
620Sstevel@tonic-gate int ret = 1;
630Sstevel@tonic-gate char *infile = NULL;
640Sstevel@tonic-gate int in_stdin = 0;
650Sstevel@tonic-gate int in_noverify = 0;
660Sstevel@tonic-gate char *salt = NULL, *passwd = NULL, **passwds = NULL;
670Sstevel@tonic-gate char *salt_malloc = NULL, *passwd_malloc = NULL;
680Sstevel@tonic-gate size_t passwd_malloc_size = 0;
690Sstevel@tonic-gate int pw_source_defined = 0;
700Sstevel@tonic-gate BIO *in = NULL, *out = NULL;
710Sstevel@tonic-gate int i, badopt, opt_done;
720Sstevel@tonic-gate int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
730Sstevel@tonic-gate int usecrypt = 0, use1 = 0, useapr1 = 0;
740Sstevel@tonic-gate size_t pw_maxlen = 0;
750Sstevel@tonic-gate
760Sstevel@tonic-gate apps_startup();
770Sstevel@tonic-gate
780Sstevel@tonic-gate if (bio_err == NULL)
790Sstevel@tonic-gate if ((bio_err=BIO_new(BIO_s_file())) != NULL)
800Sstevel@tonic-gate BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
810Sstevel@tonic-gate
820Sstevel@tonic-gate if (!load_config(bio_err, NULL))
830Sstevel@tonic-gate goto err;
840Sstevel@tonic-gate out = BIO_new(BIO_s_file());
850Sstevel@tonic-gate if (out == NULL)
860Sstevel@tonic-gate goto err;
870Sstevel@tonic-gate BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
880Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
890Sstevel@tonic-gate {
900Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer());
910Sstevel@tonic-gate out = BIO_push(tmpbio, out);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate #endif
940Sstevel@tonic-gate
950Sstevel@tonic-gate badopt = 0, opt_done = 0;
960Sstevel@tonic-gate i = 0;
970Sstevel@tonic-gate while (!badopt && !opt_done && argv[++i] != NULL)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate if (strcmp(argv[i], "-crypt") == 0)
1000Sstevel@tonic-gate usecrypt = 1;
1010Sstevel@tonic-gate else if (strcmp(argv[i], "-1") == 0)
1020Sstevel@tonic-gate use1 = 1;
1030Sstevel@tonic-gate else if (strcmp(argv[i], "-apr1") == 0)
1040Sstevel@tonic-gate useapr1 = 1;
1050Sstevel@tonic-gate else if (strcmp(argv[i], "-salt") == 0)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate if ((argv[i+1] != NULL) && (salt == NULL))
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate passed_salt = 1;
1100Sstevel@tonic-gate salt = argv[++i];
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate else
1130Sstevel@tonic-gate badopt = 1;
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate else if (strcmp(argv[i], "-in") == 0)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate if ((argv[i+1] != NULL) && !pw_source_defined)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate pw_source_defined = 1;
1200Sstevel@tonic-gate infile = argv[++i];
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate else
1230Sstevel@tonic-gate badopt = 1;
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate else if (strcmp(argv[i], "-stdin") == 0)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate if (!pw_source_defined)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate pw_source_defined = 1;
1300Sstevel@tonic-gate in_stdin = 1;
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate else
1330Sstevel@tonic-gate badopt = 1;
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate else if (strcmp(argv[i], "-noverify") == 0)
1360Sstevel@tonic-gate in_noverify = 1;
1370Sstevel@tonic-gate else if (strcmp(argv[i], "-quiet") == 0)
1380Sstevel@tonic-gate quiet = 1;
1390Sstevel@tonic-gate else if (strcmp(argv[i], "-table") == 0)
1400Sstevel@tonic-gate table = 1;
1410Sstevel@tonic-gate else if (strcmp(argv[i], "-reverse") == 0)
1420Sstevel@tonic-gate reverse = 1;
1430Sstevel@tonic-gate else if (argv[i][0] == '-')
1440Sstevel@tonic-gate badopt = 1;
1450Sstevel@tonic-gate else if (!pw_source_defined)
1460Sstevel@tonic-gate /* non-option arguments, use as passwords */
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate pw_source_defined = 1;
1490Sstevel@tonic-gate passwds = &argv[i];
1500Sstevel@tonic-gate opt_done = 1;
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate else
1530Sstevel@tonic-gate badopt = 1;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate if (!usecrypt && !use1 && !useapr1) /* use default */
1570Sstevel@tonic-gate usecrypt = 1;
1580Sstevel@tonic-gate if (usecrypt + use1 + useapr1 > 1) /* conflict */
1590Sstevel@tonic-gate badopt = 1;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /* reject unsupported algorithms */
1620Sstevel@tonic-gate #ifdef OPENSSL_NO_DES
1630Sstevel@tonic-gate if (usecrypt) badopt = 1;
1640Sstevel@tonic-gate #endif
1650Sstevel@tonic-gate #ifdef NO_MD5CRYPT_1
1660Sstevel@tonic-gate if (use1 || useapr1) badopt = 1;
1670Sstevel@tonic-gate #endif
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (badopt)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate BIO_printf(bio_err, "Usage: passwd [options] [passwords]\n");
1720Sstevel@tonic-gate BIO_printf(bio_err, "where options are\n");
1730Sstevel@tonic-gate #ifndef OPENSSL_NO_DES
1740Sstevel@tonic-gate BIO_printf(bio_err, "-crypt standard Unix password algorithm (default)\n");
1750Sstevel@tonic-gate #endif
1760Sstevel@tonic-gate #ifndef NO_MD5CRYPT_1
1770Sstevel@tonic-gate BIO_printf(bio_err, "-1 MD5-based password algorithm\n");
1780Sstevel@tonic-gate BIO_printf(bio_err, "-apr1 MD5-based password algorithm, Apache variant\n");
1790Sstevel@tonic-gate #endif
1800Sstevel@tonic-gate BIO_printf(bio_err, "-salt string use provided salt\n");
1810Sstevel@tonic-gate BIO_printf(bio_err, "-in file read passwords from file\n");
1820Sstevel@tonic-gate BIO_printf(bio_err, "-stdin read passwords from stdin\n");
1830Sstevel@tonic-gate BIO_printf(bio_err, "-noverify never verify when reading password from terminal\n");
1840Sstevel@tonic-gate BIO_printf(bio_err, "-quiet no warnings\n");
1850Sstevel@tonic-gate BIO_printf(bio_err, "-table format output as table\n");
1860Sstevel@tonic-gate BIO_printf(bio_err, "-reverse switch table columns\n");
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate goto err;
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate if ((infile != NULL) || in_stdin)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate in = BIO_new(BIO_s_file());
1940Sstevel@tonic-gate if (in == NULL)
1950Sstevel@tonic-gate goto err;
1960Sstevel@tonic-gate if (infile != NULL)
1970Sstevel@tonic-gate {
1980Sstevel@tonic-gate assert(in_stdin == 0);
1990Sstevel@tonic-gate if (BIO_read_filename(in, infile) <= 0)
2000Sstevel@tonic-gate goto err;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate else
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate assert(in_stdin);
2050Sstevel@tonic-gate BIO_set_fp(in, stdin, BIO_NOCLOSE);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate if (usecrypt)
2100Sstevel@tonic-gate pw_maxlen = 8;
2110Sstevel@tonic-gate else if (use1 || useapr1)
2120Sstevel@tonic-gate pw_maxlen = 256; /* arbitrary limit, should be enough for most passwords */
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate if (passwds == NULL)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate /* no passwords on the command line */
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate passwd_malloc_size = pw_maxlen + 2;
2190Sstevel@tonic-gate /* longer than necessary so that we can warn about truncation */
2200Sstevel@tonic-gate passwd = passwd_malloc = OPENSSL_malloc(passwd_malloc_size);
2210Sstevel@tonic-gate if (passwd_malloc == NULL)
2220Sstevel@tonic-gate goto err;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate if ((in == NULL) && (passwds == NULL))
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate /* build a null-terminated list */
2280Sstevel@tonic-gate static char *passwds_static[2] = {NULL, NULL};
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate passwds = passwds_static;
2310Sstevel@tonic-gate if (in == NULL)
2320Sstevel@tonic-gate if (EVP_read_pw_string(passwd_malloc, passwd_malloc_size, "Password: ", !(passed_salt || in_noverify)) != 0)
2330Sstevel@tonic-gate goto err;
2340Sstevel@tonic-gate passwds[0] = passwd_malloc;
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate if (in == NULL)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate assert(passwds != NULL);
2400Sstevel@tonic-gate assert(*passwds != NULL);
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate do /* loop over list of passwords */
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate passwd = *passwds++;
2450Sstevel@tonic-gate if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
2460Sstevel@tonic-gate quiet, table, reverse, pw_maxlen, usecrypt, use1, useapr1))
2470Sstevel@tonic-gate goto err;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate while (*passwds != NULL);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate else
2520Sstevel@tonic-gate /* in != NULL */
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate int done;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate assert (passwd != NULL);
2570Sstevel@tonic-gate do
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate int r = BIO_gets(in, passwd, pw_maxlen + 1);
2600Sstevel@tonic-gate if (r > 0)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate char *c = (strchr(passwd, '\n')) ;
2630Sstevel@tonic-gate if (c != NULL)
2640Sstevel@tonic-gate *c = 0; /* truncate at newline */
2650Sstevel@tonic-gate else
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate /* ignore rest of line */
2680Sstevel@tonic-gate char trash[BUFSIZ];
2690Sstevel@tonic-gate do
2700Sstevel@tonic-gate r = BIO_gets(in, trash, sizeof trash);
2710Sstevel@tonic-gate while ((r > 0) && (!strchr(trash, '\n')));
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
2750Sstevel@tonic-gate quiet, table, reverse, pw_maxlen, usecrypt, use1, useapr1))
2760Sstevel@tonic-gate goto err;
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate done = (r <= 0);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate while (!done);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate ret = 0;
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate err:
2850Sstevel@tonic-gate ERR_print_errors(bio_err);
2860Sstevel@tonic-gate if (salt_malloc)
2870Sstevel@tonic-gate OPENSSL_free(salt_malloc);
2880Sstevel@tonic-gate if (passwd_malloc)
2890Sstevel@tonic-gate OPENSSL_free(passwd_malloc);
2900Sstevel@tonic-gate if (in)
2910Sstevel@tonic-gate BIO_free(in);
2920Sstevel@tonic-gate if (out)
2930Sstevel@tonic-gate BIO_free_all(out);
2940Sstevel@tonic-gate apps_shutdown();
2950Sstevel@tonic-gate OPENSSL_EXIT(ret);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate #ifndef NO_MD5CRYPT_1
3000Sstevel@tonic-gate /* MD5-based password algorithm (should probably be available as a library
3010Sstevel@tonic-gate * function; then the static buffer would not be acceptable).
3020Sstevel@tonic-gate * For magic string "1", this should be compatible to the MD5-based BSD
3030Sstevel@tonic-gate * password algorithm.
3040Sstevel@tonic-gate * For 'magic' string "apr1", this is compatible to the MD5-based Apache
3050Sstevel@tonic-gate * password algorithm.
3060Sstevel@tonic-gate * (Apparently, the Apache password algorithm is identical except that the
3070Sstevel@tonic-gate * 'magic' string was changed -- the laziest application of the NIH principle
3080Sstevel@tonic-gate * I've ever encountered.)
3090Sstevel@tonic-gate */
md5crypt(const char * passwd,const char * magic,const char * salt)3100Sstevel@tonic-gate static char *md5crypt(const char *passwd, const char *magic, const char *salt)
3110Sstevel@tonic-gate {
3120Sstevel@tonic-gate static char out_buf[6 + 9 + 24 + 2]; /* "$apr1$..salt..$.......md5hash..........\0" */
3130Sstevel@tonic-gate unsigned char buf[MD5_DIGEST_LENGTH];
3140Sstevel@tonic-gate char *salt_out;
315*2139Sjp161948 int n;
316*2139Sjp161948 unsigned int i;
3170Sstevel@tonic-gate EVP_MD_CTX md,md2;
3180Sstevel@tonic-gate size_t passwd_len, salt_len;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate passwd_len = strlen(passwd);
3210Sstevel@tonic-gate out_buf[0] = '$';
3220Sstevel@tonic-gate out_buf[1] = 0;
3230Sstevel@tonic-gate assert(strlen(magic) <= 4); /* "1" or "apr1" */
3240Sstevel@tonic-gate strncat(out_buf, magic, 4);
3250Sstevel@tonic-gate strncat(out_buf, "$", 1);
3260Sstevel@tonic-gate strncat(out_buf, salt, 8);
3270Sstevel@tonic-gate assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */
3280Sstevel@tonic-gate salt_out = out_buf + 2 + strlen(magic);
3290Sstevel@tonic-gate salt_len = strlen(salt_out);
3300Sstevel@tonic-gate assert(salt_len <= 8);
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate EVP_MD_CTX_init(&md);
3330Sstevel@tonic-gate EVP_DigestInit_ex(&md,EVP_md5(), NULL);
3340Sstevel@tonic-gate EVP_DigestUpdate(&md, passwd, passwd_len);
3350Sstevel@tonic-gate EVP_DigestUpdate(&md, "$", 1);
3360Sstevel@tonic-gate EVP_DigestUpdate(&md, magic, strlen(magic));
3370Sstevel@tonic-gate EVP_DigestUpdate(&md, "$", 1);
3380Sstevel@tonic-gate EVP_DigestUpdate(&md, salt_out, salt_len);
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate EVP_MD_CTX_init(&md2);
3410Sstevel@tonic-gate EVP_DigestInit_ex(&md2,EVP_md5(), NULL);
3420Sstevel@tonic-gate EVP_DigestUpdate(&md2, passwd, passwd_len);
3430Sstevel@tonic-gate EVP_DigestUpdate(&md2, salt_out, salt_len);
3440Sstevel@tonic-gate EVP_DigestUpdate(&md2, passwd, passwd_len);
3450Sstevel@tonic-gate EVP_DigestFinal_ex(&md2, buf, NULL);
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate for (i = passwd_len; i > sizeof buf; i -= sizeof buf)
3480Sstevel@tonic-gate EVP_DigestUpdate(&md, buf, sizeof buf);
3490Sstevel@tonic-gate EVP_DigestUpdate(&md, buf, i);
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate n = passwd_len;
3520Sstevel@tonic-gate while (n)
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate EVP_DigestUpdate(&md, (n & 1) ? "\0" : passwd, 1);
3550Sstevel@tonic-gate n >>= 1;
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate EVP_DigestFinal_ex(&md, buf, NULL);
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate for (i = 0; i < 1000; i++)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate EVP_DigestInit_ex(&md2,EVP_md5(), NULL);
362*2139Sjp161948 EVP_DigestUpdate(&md2, (i & 1) ? (unsigned const char *) passwd : buf,
3630Sstevel@tonic-gate (i & 1) ? passwd_len : sizeof buf);
3640Sstevel@tonic-gate if (i % 3)
3650Sstevel@tonic-gate EVP_DigestUpdate(&md2, salt_out, salt_len);
3660Sstevel@tonic-gate if (i % 7)
3670Sstevel@tonic-gate EVP_DigestUpdate(&md2, passwd, passwd_len);
368*2139Sjp161948 EVP_DigestUpdate(&md2, (i & 1) ? buf : (unsigned const char *) passwd,
3690Sstevel@tonic-gate (i & 1) ? sizeof buf : passwd_len);
3700Sstevel@tonic-gate EVP_DigestFinal_ex(&md2, buf, NULL);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate EVP_MD_CTX_cleanup(&md2);
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate /* transform buf into output string */
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate unsigned char buf_perm[sizeof buf];
3780Sstevel@tonic-gate int dest, source;
3790Sstevel@tonic-gate char *output;
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /* silly output permutation */
3820Sstevel@tonic-gate for (dest = 0, source = 0; dest < 14; dest++, source = (source + 6) % 17)
3830Sstevel@tonic-gate buf_perm[dest] = buf[source];
3840Sstevel@tonic-gate buf_perm[14] = buf[5];
3850Sstevel@tonic-gate buf_perm[15] = buf[11];
3860Sstevel@tonic-gate #ifndef PEDANTIC /* Unfortunately, this generates a "no effect" warning */
3870Sstevel@tonic-gate assert(16 == sizeof buf_perm);
3880Sstevel@tonic-gate #endif
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate output = salt_out + salt_len;
3910Sstevel@tonic-gate assert(output == out_buf + strlen(out_buf));
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate *output++ = '$';
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate for (i = 0; i < 15; i += 3)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate *output++ = cov_2char[buf_perm[i+2] & 0x3f];
3980Sstevel@tonic-gate *output++ = cov_2char[((buf_perm[i+1] & 0xf) << 2) |
3990Sstevel@tonic-gate (buf_perm[i+2] >> 6)];
4000Sstevel@tonic-gate *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
4010Sstevel@tonic-gate (buf_perm[i+1] >> 4)];
4020Sstevel@tonic-gate *output++ = cov_2char[buf_perm[i] >> 2];
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate assert(i == 15);
4050Sstevel@tonic-gate *output++ = cov_2char[buf_perm[i] & 0x3f];
4060Sstevel@tonic-gate *output++ = cov_2char[buf_perm[i] >> 6];
4070Sstevel@tonic-gate *output = 0;
4080Sstevel@tonic-gate assert(strlen(out_buf) < sizeof(out_buf));
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate EVP_MD_CTX_cleanup(&md);
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate return out_buf;
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate #endif
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate
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)4170Sstevel@tonic-gate static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
4180Sstevel@tonic-gate char *passwd, BIO *out, int quiet, int table, int reverse,
4190Sstevel@tonic-gate size_t pw_maxlen, int usecrypt, int use1, int useapr1)
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate char *hash = NULL;
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate assert(salt_p != NULL);
4240Sstevel@tonic-gate assert(salt_malloc_p != NULL);
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate /* first make sure we have a salt */
4270Sstevel@tonic-gate if (!passed_salt)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate #ifndef OPENSSL_NO_DES
4300Sstevel@tonic-gate if (usecrypt)
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate if (*salt_malloc_p == NULL)
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate *salt_p = *salt_malloc_p = OPENSSL_malloc(3);
4350Sstevel@tonic-gate if (*salt_malloc_p == NULL)
4360Sstevel@tonic-gate goto err;
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate if (RAND_pseudo_bytes((unsigned char *)*salt_p, 2) < 0)
4390Sstevel@tonic-gate goto err;
4400Sstevel@tonic-gate (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
4410Sstevel@tonic-gate (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
4420Sstevel@tonic-gate (*salt_p)[2] = 0;
4430Sstevel@tonic-gate #ifdef CHARSET_EBCDIC
4440Sstevel@tonic-gate ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert
4450Sstevel@tonic-gate * back to ASCII */
4460Sstevel@tonic-gate #endif
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate #endif /* !OPENSSL_NO_DES */
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate #ifndef NO_MD5CRYPT_1
4510Sstevel@tonic-gate if (use1 || useapr1)
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate int i;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate if (*salt_malloc_p == NULL)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate *salt_p = *salt_malloc_p = OPENSSL_malloc(9);
4580Sstevel@tonic-gate if (*salt_malloc_p == NULL)
4590Sstevel@tonic-gate goto err;
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate if (RAND_pseudo_bytes((unsigned char *)*salt_p, 8) < 0)
4620Sstevel@tonic-gate goto err;
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate for (i = 0; i < 8; i++)
4650Sstevel@tonic-gate (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
4660Sstevel@tonic-gate (*salt_p)[8] = 0;
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate #endif /* !NO_MD5CRYPT_1 */
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate assert(*salt_p != NULL);
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* truncate password if necessary */
4740Sstevel@tonic-gate if ((strlen(passwd) > pw_maxlen))
4750Sstevel@tonic-gate {
4760Sstevel@tonic-gate if (!quiet)
477*2139Sjp161948 /* XXX: really we should know how to print a size_t, not cast it */
478*2139Sjp161948 BIO_printf(bio_err, "Warning: truncating password to %u characters\n", (unsigned)pw_maxlen);
4790Sstevel@tonic-gate passwd[pw_maxlen] = 0;
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate assert(strlen(passwd) <= pw_maxlen);
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /* now compute password hash */
4840Sstevel@tonic-gate #ifndef OPENSSL_NO_DES
4850Sstevel@tonic-gate if (usecrypt)
4860Sstevel@tonic-gate hash = DES_crypt(passwd, *salt_p);
4870Sstevel@tonic-gate #endif
4880Sstevel@tonic-gate #ifndef NO_MD5CRYPT_1
4890Sstevel@tonic-gate if (use1 || useapr1)
4900Sstevel@tonic-gate hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p);
4910Sstevel@tonic-gate #endif
4920Sstevel@tonic-gate assert(hash != NULL);
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (table && !reverse)
4950Sstevel@tonic-gate BIO_printf(out, "%s\t%s\n", passwd, hash);
4960Sstevel@tonic-gate else if (table && reverse)
4970Sstevel@tonic-gate BIO_printf(out, "%s\t%s\n", hash, passwd);
4980Sstevel@tonic-gate else
4990Sstevel@tonic-gate BIO_printf(out, "%s\n", hash);
5000Sstevel@tonic-gate return 1;
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate err:
5030Sstevel@tonic-gate return 0;
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate #else
5060Sstevel@tonic-gate
MAIN(int argc,char ** argv)5070Sstevel@tonic-gate int MAIN(int argc, char **argv)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate fputs("Program not available.\n", stderr)
5100Sstevel@tonic-gate OPENSSL_EXIT(1);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate #endif
513