1ebfedea0SLionel Sambuc /* apps/passwd.c */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc #if defined OPENSSL_NO_MD5 || defined CHARSET_EBCDIC
4ebfedea0SLionel Sambuc # define NO_MD5CRYPT_1
5ebfedea0SLionel Sambuc #endif
6ebfedea0SLionel Sambuc
7ebfedea0SLionel Sambuc #if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1)
8ebfedea0SLionel Sambuc
9ebfedea0SLionel Sambuc # include <assert.h>
10ebfedea0SLionel Sambuc # include <string.h>
11ebfedea0SLionel Sambuc
12ebfedea0SLionel Sambuc # include "apps.h"
13ebfedea0SLionel Sambuc
14ebfedea0SLionel Sambuc # include <openssl/bio.h>
15ebfedea0SLionel Sambuc # include <openssl/err.h>
16ebfedea0SLionel Sambuc # include <openssl/evp.h>
17ebfedea0SLionel Sambuc # include <openssl/rand.h>
18ebfedea0SLionel Sambuc # ifndef OPENSSL_NO_DES
19ebfedea0SLionel Sambuc # include <openssl/des.h>
20ebfedea0SLionel Sambuc # endif
21ebfedea0SLionel Sambuc # ifndef NO_MD5CRYPT_1
22ebfedea0SLionel Sambuc # include <openssl/md5.h>
23ebfedea0SLionel Sambuc # endif
24ebfedea0SLionel Sambuc
25ebfedea0SLionel Sambuc # undef PROG
26ebfedea0SLionel Sambuc # define PROG passwd_main
27ebfedea0SLionel Sambuc
28ebfedea0SLionel Sambuc static unsigned const char cov_2char[64] = {
29ebfedea0SLionel Sambuc /* from crypto/des/fcrypt.c */
30ebfedea0SLionel Sambuc 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
31ebfedea0SLionel Sambuc 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44,
32ebfedea0SLionel Sambuc 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
33ebfedea0SLionel Sambuc 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
34ebfedea0SLionel Sambuc 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
35ebfedea0SLionel Sambuc 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
36ebfedea0SLionel Sambuc 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
37ebfedea0SLionel Sambuc 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
38ebfedea0SLionel Sambuc };
39ebfedea0SLionel Sambuc
40ebfedea0SLionel Sambuc static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
41*0a6a1f1dSLionel Sambuc char *passwd, BIO *out, int quiet, int table,
42*0a6a1f1dSLionel Sambuc int reverse, size_t pw_maxlen, int usecrypt, int use1,
43*0a6a1f1dSLionel Sambuc int useapr1);
44ebfedea0SLionel Sambuc
45*0a6a1f1dSLionel Sambuc /*-
46*0a6a1f1dSLionel Sambuc * -crypt - standard Unix password algorithm (default)
47ebfedea0SLionel Sambuc * -1 - MD5-based password algorithm
48ebfedea0SLionel Sambuc * -apr1 - MD5-based password algorithm, Apache variant
49ebfedea0SLionel Sambuc * -salt string - salt
50ebfedea0SLionel Sambuc * -in file - read passwords from file
51ebfedea0SLionel Sambuc * -stdin - read passwords from stdin
52ebfedea0SLionel Sambuc * -noverify - never verify when reading password from terminal
53ebfedea0SLionel Sambuc * -quiet - no warnings
54ebfedea0SLionel Sambuc * -table - format output as table
55ebfedea0SLionel Sambuc * -reverse - switch table columns
56ebfedea0SLionel Sambuc */
57ebfedea0SLionel Sambuc
58ebfedea0SLionel Sambuc int MAIN(int, char **);
59ebfedea0SLionel Sambuc
MAIN(int argc,char ** argv)60ebfedea0SLionel Sambuc int MAIN(int argc, char **argv)
61ebfedea0SLionel Sambuc {
62ebfedea0SLionel Sambuc int ret = 1;
63ebfedea0SLionel Sambuc char *infile = NULL;
64ebfedea0SLionel Sambuc int in_stdin = 0;
65ebfedea0SLionel Sambuc int in_noverify = 0;
66ebfedea0SLionel Sambuc char *salt = NULL, *passwd = NULL, **passwds = NULL;
67ebfedea0SLionel Sambuc char *salt_malloc = NULL, *passwd_malloc = NULL;
68ebfedea0SLionel Sambuc size_t passwd_malloc_size = 0;
69ebfedea0SLionel Sambuc int pw_source_defined = 0;
70ebfedea0SLionel Sambuc BIO *in = NULL, *out = NULL;
71ebfedea0SLionel Sambuc int i, badopt, opt_done;
72ebfedea0SLionel Sambuc int passed_salt = 0, quiet = 0, table = 0, reverse = 0;
73ebfedea0SLionel Sambuc int usecrypt = 0, use1 = 0, useapr1 = 0;
74ebfedea0SLionel Sambuc size_t pw_maxlen = 0;
75ebfedea0SLionel Sambuc
76ebfedea0SLionel Sambuc apps_startup();
77ebfedea0SLionel Sambuc
78ebfedea0SLionel Sambuc if (bio_err == NULL)
79ebfedea0SLionel Sambuc if ((bio_err = BIO_new(BIO_s_file())) != NULL)
80ebfedea0SLionel Sambuc BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
81ebfedea0SLionel Sambuc
82ebfedea0SLionel Sambuc if (!load_config(bio_err, NULL))
83ebfedea0SLionel Sambuc goto err;
84ebfedea0SLionel Sambuc out = BIO_new(BIO_s_file());
85ebfedea0SLionel Sambuc if (out == NULL)
86ebfedea0SLionel Sambuc goto err;
87ebfedea0SLionel Sambuc BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
88ebfedea0SLionel Sambuc # ifdef OPENSSL_SYS_VMS
89ebfedea0SLionel Sambuc {
90ebfedea0SLionel Sambuc BIO *tmpbio = BIO_new(BIO_f_linebuffer());
91ebfedea0SLionel Sambuc out = BIO_push(tmpbio, out);
92ebfedea0SLionel Sambuc }
93ebfedea0SLionel Sambuc # endif
94ebfedea0SLionel Sambuc
95ebfedea0SLionel Sambuc badopt = 0, opt_done = 0;
96ebfedea0SLionel Sambuc i = 0;
97*0a6a1f1dSLionel Sambuc while (!badopt && !opt_done && argv[++i] != NULL) {
98ebfedea0SLionel Sambuc if (strcmp(argv[i], "-crypt") == 0)
99ebfedea0SLionel Sambuc usecrypt = 1;
100ebfedea0SLionel Sambuc else if (strcmp(argv[i], "-1") == 0)
101ebfedea0SLionel Sambuc use1 = 1;
102ebfedea0SLionel Sambuc else if (strcmp(argv[i], "-apr1") == 0)
103ebfedea0SLionel Sambuc useapr1 = 1;
104*0a6a1f1dSLionel Sambuc else if (strcmp(argv[i], "-salt") == 0) {
105*0a6a1f1dSLionel Sambuc if ((argv[i + 1] != NULL) && (salt == NULL)) {
106ebfedea0SLionel Sambuc passed_salt = 1;
107ebfedea0SLionel Sambuc salt = argv[++i];
108*0a6a1f1dSLionel Sambuc } else
109ebfedea0SLionel Sambuc badopt = 1;
110*0a6a1f1dSLionel Sambuc } else if (strcmp(argv[i], "-in") == 0) {
111*0a6a1f1dSLionel Sambuc if ((argv[i + 1] != NULL) && !pw_source_defined) {
112ebfedea0SLionel Sambuc pw_source_defined = 1;
113ebfedea0SLionel Sambuc infile = argv[++i];
114*0a6a1f1dSLionel Sambuc } else
115ebfedea0SLionel Sambuc badopt = 1;
116*0a6a1f1dSLionel Sambuc } else if (strcmp(argv[i], "-stdin") == 0) {
117*0a6a1f1dSLionel Sambuc if (!pw_source_defined) {
118ebfedea0SLionel Sambuc pw_source_defined = 1;
119ebfedea0SLionel Sambuc in_stdin = 1;
120*0a6a1f1dSLionel Sambuc } else
121ebfedea0SLionel Sambuc badopt = 1;
122*0a6a1f1dSLionel Sambuc } else if (strcmp(argv[i], "-noverify") == 0)
123ebfedea0SLionel Sambuc in_noverify = 1;
124ebfedea0SLionel Sambuc else if (strcmp(argv[i], "-quiet") == 0)
125ebfedea0SLionel Sambuc quiet = 1;
126ebfedea0SLionel Sambuc else if (strcmp(argv[i], "-table") == 0)
127ebfedea0SLionel Sambuc table = 1;
128ebfedea0SLionel Sambuc else if (strcmp(argv[i], "-reverse") == 0)
129ebfedea0SLionel Sambuc reverse = 1;
130ebfedea0SLionel Sambuc else if (argv[i][0] == '-')
131ebfedea0SLionel Sambuc badopt = 1;
132ebfedea0SLionel Sambuc else if (!pw_source_defined)
133ebfedea0SLionel Sambuc /* non-option arguments, use as passwords */
134ebfedea0SLionel Sambuc {
135ebfedea0SLionel Sambuc pw_source_defined = 1;
136ebfedea0SLionel Sambuc passwds = &argv[i];
137ebfedea0SLionel Sambuc opt_done = 1;
138*0a6a1f1dSLionel Sambuc } else
139ebfedea0SLionel Sambuc badopt = 1;
140ebfedea0SLionel Sambuc }
141ebfedea0SLionel Sambuc
142ebfedea0SLionel Sambuc if (!usecrypt && !use1 && !useapr1) /* use default */
143ebfedea0SLionel Sambuc usecrypt = 1;
144ebfedea0SLionel Sambuc if (usecrypt + use1 + useapr1 > 1) /* conflict */
145ebfedea0SLionel Sambuc badopt = 1;
146ebfedea0SLionel Sambuc
147ebfedea0SLionel Sambuc /* reject unsupported algorithms */
148ebfedea0SLionel Sambuc # ifdef OPENSSL_NO_DES
149*0a6a1f1dSLionel Sambuc if (usecrypt)
150*0a6a1f1dSLionel Sambuc badopt = 1;
151ebfedea0SLionel Sambuc # endif
152ebfedea0SLionel Sambuc # ifdef NO_MD5CRYPT_1
153*0a6a1f1dSLionel Sambuc if (use1 || useapr1)
154*0a6a1f1dSLionel Sambuc badopt = 1;
155ebfedea0SLionel Sambuc # endif
156ebfedea0SLionel Sambuc
157*0a6a1f1dSLionel Sambuc if (badopt) {
158ebfedea0SLionel Sambuc BIO_printf(bio_err, "Usage: passwd [options] [passwords]\n");
159ebfedea0SLionel Sambuc BIO_printf(bio_err, "where options are\n");
160ebfedea0SLionel Sambuc # ifndef OPENSSL_NO_DES
161*0a6a1f1dSLionel Sambuc BIO_printf(bio_err,
162*0a6a1f1dSLionel Sambuc "-crypt standard Unix password algorithm (default)\n");
163ebfedea0SLionel Sambuc # endif
164ebfedea0SLionel Sambuc # ifndef NO_MD5CRYPT_1
165*0a6a1f1dSLionel Sambuc BIO_printf(bio_err,
166*0a6a1f1dSLionel Sambuc "-1 MD5-based password algorithm\n");
167*0a6a1f1dSLionel Sambuc BIO_printf(bio_err,
168*0a6a1f1dSLionel Sambuc "-apr1 MD5-based password algorithm, Apache variant\n");
169ebfedea0SLionel Sambuc # endif
170ebfedea0SLionel Sambuc BIO_printf(bio_err, "-salt string use provided salt\n");
171ebfedea0SLionel Sambuc BIO_printf(bio_err, "-in file read passwords from file\n");
172ebfedea0SLionel Sambuc BIO_printf(bio_err, "-stdin read passwords from stdin\n");
173*0a6a1f1dSLionel Sambuc BIO_printf(bio_err,
174*0a6a1f1dSLionel Sambuc "-noverify never verify when reading password from terminal\n");
175ebfedea0SLionel Sambuc BIO_printf(bio_err, "-quiet no warnings\n");
176ebfedea0SLionel Sambuc BIO_printf(bio_err, "-table format output as table\n");
177ebfedea0SLionel Sambuc BIO_printf(bio_err, "-reverse switch table columns\n");
178ebfedea0SLionel Sambuc
179ebfedea0SLionel Sambuc goto err;
180ebfedea0SLionel Sambuc }
181ebfedea0SLionel Sambuc
182*0a6a1f1dSLionel Sambuc if ((infile != NULL) || in_stdin) {
183ebfedea0SLionel Sambuc in = BIO_new(BIO_s_file());
184ebfedea0SLionel Sambuc if (in == NULL)
185ebfedea0SLionel Sambuc goto err;
186*0a6a1f1dSLionel Sambuc if (infile != NULL) {
187ebfedea0SLionel Sambuc assert(in_stdin == 0);
188ebfedea0SLionel Sambuc if (BIO_read_filename(in, infile) <= 0)
189ebfedea0SLionel Sambuc goto err;
190*0a6a1f1dSLionel Sambuc } else {
191ebfedea0SLionel Sambuc assert(in_stdin);
192ebfedea0SLionel Sambuc BIO_set_fp(in, stdin, BIO_NOCLOSE);
193ebfedea0SLionel Sambuc }
194ebfedea0SLionel Sambuc }
195ebfedea0SLionel Sambuc
196ebfedea0SLionel Sambuc if (usecrypt)
197ebfedea0SLionel Sambuc pw_maxlen = 8;
198ebfedea0SLionel Sambuc else if (use1 || useapr1)
199*0a6a1f1dSLionel Sambuc pw_maxlen = 256; /* arbitrary limit, should be enough for most
200*0a6a1f1dSLionel Sambuc * passwords */
201ebfedea0SLionel Sambuc
202*0a6a1f1dSLionel Sambuc if (passwds == NULL) {
203ebfedea0SLionel Sambuc /* no passwords on the command line */
204ebfedea0SLionel Sambuc
205ebfedea0SLionel Sambuc passwd_malloc_size = pw_maxlen + 2;
206*0a6a1f1dSLionel Sambuc /*
207*0a6a1f1dSLionel Sambuc * longer than necessary so that we can warn about truncation
208*0a6a1f1dSLionel Sambuc */
209ebfedea0SLionel Sambuc passwd = passwd_malloc = OPENSSL_malloc(passwd_malloc_size);
210ebfedea0SLionel Sambuc if (passwd_malloc == NULL)
211ebfedea0SLionel Sambuc goto err;
212ebfedea0SLionel Sambuc }
213ebfedea0SLionel Sambuc
214*0a6a1f1dSLionel Sambuc if ((in == NULL) && (passwds == NULL)) {
215ebfedea0SLionel Sambuc /* build a null-terminated list */
216ebfedea0SLionel Sambuc static char *passwds_static[2] = { NULL, NULL };
217ebfedea0SLionel Sambuc
218ebfedea0SLionel Sambuc passwds = passwds_static;
219ebfedea0SLionel Sambuc if (in == NULL)
220*0a6a1f1dSLionel Sambuc if (EVP_read_pw_string
221*0a6a1f1dSLionel Sambuc (passwd_malloc, passwd_malloc_size, "Password: ",
222*0a6a1f1dSLionel Sambuc !(passed_salt || in_noverify)) != 0)
223ebfedea0SLionel Sambuc goto err;
224ebfedea0SLionel Sambuc passwds[0] = passwd_malloc;
225ebfedea0SLionel Sambuc }
226ebfedea0SLionel Sambuc
227*0a6a1f1dSLionel Sambuc if (in == NULL) {
228ebfedea0SLionel Sambuc assert(passwds != NULL);
229ebfedea0SLionel Sambuc assert(*passwds != NULL);
230ebfedea0SLionel Sambuc
231*0a6a1f1dSLionel Sambuc do { /* loop over list of passwords */
232ebfedea0SLionel Sambuc passwd = *passwds++;
233ebfedea0SLionel Sambuc if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
234*0a6a1f1dSLionel Sambuc quiet, table, reverse, pw_maxlen, usecrypt, use1,
235*0a6a1f1dSLionel Sambuc useapr1))
236ebfedea0SLionel Sambuc goto err;
237ebfedea0SLionel Sambuc }
238ebfedea0SLionel Sambuc while (*passwds != NULL);
239*0a6a1f1dSLionel Sambuc } else
240ebfedea0SLionel Sambuc /* in != NULL */
241ebfedea0SLionel Sambuc {
242ebfedea0SLionel Sambuc int done;
243ebfedea0SLionel Sambuc
244ebfedea0SLionel Sambuc assert(passwd != NULL);
245*0a6a1f1dSLionel Sambuc do {
246ebfedea0SLionel Sambuc int r = BIO_gets(in, passwd, pw_maxlen + 1);
247*0a6a1f1dSLionel Sambuc if (r > 0) {
248ebfedea0SLionel Sambuc char *c = (strchr(passwd, '\n'));
249ebfedea0SLionel Sambuc if (c != NULL)
250ebfedea0SLionel Sambuc *c = 0; /* truncate at newline */
251*0a6a1f1dSLionel Sambuc else {
252ebfedea0SLionel Sambuc /* ignore rest of line */
253ebfedea0SLionel Sambuc char trash[BUFSIZ];
254ebfedea0SLionel Sambuc do
255ebfedea0SLionel Sambuc r = BIO_gets(in, trash, sizeof trash);
256ebfedea0SLionel Sambuc while ((r > 0) && (!strchr(trash, '\n')));
257ebfedea0SLionel Sambuc }
258ebfedea0SLionel Sambuc
259ebfedea0SLionel Sambuc if (!do_passwd(passed_salt, &salt, &salt_malloc, passwd, out,
260*0a6a1f1dSLionel Sambuc quiet, table, reverse, pw_maxlen, usecrypt,
261*0a6a1f1dSLionel Sambuc use1, useapr1))
262ebfedea0SLionel Sambuc goto err;
263ebfedea0SLionel Sambuc }
264ebfedea0SLionel Sambuc done = (r <= 0);
265ebfedea0SLionel Sambuc }
266ebfedea0SLionel Sambuc while (!done);
267ebfedea0SLionel Sambuc }
268ebfedea0SLionel Sambuc ret = 0;
269ebfedea0SLionel Sambuc
270ebfedea0SLionel Sambuc err:
271ebfedea0SLionel Sambuc ERR_print_errors(bio_err);
272ebfedea0SLionel Sambuc if (salt_malloc)
273ebfedea0SLionel Sambuc OPENSSL_free(salt_malloc);
274ebfedea0SLionel Sambuc if (passwd_malloc)
275ebfedea0SLionel Sambuc OPENSSL_free(passwd_malloc);
276ebfedea0SLionel Sambuc if (in)
277ebfedea0SLionel Sambuc BIO_free(in);
278ebfedea0SLionel Sambuc if (out)
279ebfedea0SLionel Sambuc BIO_free_all(out);
280ebfedea0SLionel Sambuc apps_shutdown();
281ebfedea0SLionel Sambuc OPENSSL_EXIT(ret);
282ebfedea0SLionel Sambuc }
283ebfedea0SLionel Sambuc
284ebfedea0SLionel Sambuc # ifndef NO_MD5CRYPT_1
285*0a6a1f1dSLionel Sambuc /*
286*0a6a1f1dSLionel Sambuc * MD5-based password algorithm (should probably be available as a library
287*0a6a1f1dSLionel Sambuc * function; then the static buffer would not be acceptable). For magic
288*0a6a1f1dSLionel Sambuc * string "1", this should be compatible to the MD5-based BSD password
289*0a6a1f1dSLionel Sambuc * algorithm. For 'magic' string "apr1", this is compatible to the MD5-based
290*0a6a1f1dSLionel Sambuc * Apache password algorithm. (Apparently, the Apache password algorithm is
291*0a6a1f1dSLionel Sambuc * identical except that the 'magic' string was changed -- the laziest
292*0a6a1f1dSLionel Sambuc * application of the NIH principle I've ever encountered.)
293ebfedea0SLionel Sambuc */
md5crypt(const char * passwd,const char * magic,const char * salt)294ebfedea0SLionel Sambuc static char *md5crypt(const char *passwd, const char *magic, const char *salt)
295ebfedea0SLionel Sambuc {
296*0a6a1f1dSLionel Sambuc /* "$apr1$..salt..$.......md5hash..........\0" */
297*0a6a1f1dSLionel Sambuc static char out_buf[6 + 9 + 24 + 2];
298ebfedea0SLionel Sambuc unsigned char buf[MD5_DIGEST_LENGTH];
299ebfedea0SLionel Sambuc char *salt_out;
300ebfedea0SLionel Sambuc int n;
301ebfedea0SLionel Sambuc unsigned int i;
302ebfedea0SLionel Sambuc EVP_MD_CTX md, md2;
303ebfedea0SLionel Sambuc size_t passwd_len, salt_len;
304ebfedea0SLionel Sambuc
305ebfedea0SLionel Sambuc passwd_len = strlen(passwd);
306ebfedea0SLionel Sambuc out_buf[0] = '$';
307ebfedea0SLionel Sambuc out_buf[1] = 0;
308ebfedea0SLionel Sambuc assert(strlen(magic) <= 4); /* "1" or "apr1" */
309ebfedea0SLionel Sambuc strncat(out_buf, magic, 4);
310ebfedea0SLionel Sambuc strncat(out_buf, "$", 1);
311ebfedea0SLionel Sambuc strncat(out_buf, salt, 8);
312ebfedea0SLionel Sambuc assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */
313ebfedea0SLionel Sambuc salt_out = out_buf + 2 + strlen(magic);
314ebfedea0SLionel Sambuc salt_len = strlen(salt_out);
315ebfedea0SLionel Sambuc assert(salt_len <= 8);
316ebfedea0SLionel Sambuc
317ebfedea0SLionel Sambuc EVP_MD_CTX_init(&md);
318ebfedea0SLionel Sambuc EVP_DigestInit_ex(&md, EVP_md5(), NULL);
319ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, passwd, passwd_len);
320ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, "$", 1);
321ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, magic, strlen(magic));
322ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, "$", 1);
323ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, salt_out, salt_len);
324ebfedea0SLionel Sambuc
325ebfedea0SLionel Sambuc EVP_MD_CTX_init(&md2);
326ebfedea0SLionel Sambuc EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
327ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, passwd, passwd_len);
328ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, salt_out, salt_len);
329ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, passwd, passwd_len);
330ebfedea0SLionel Sambuc EVP_DigestFinal_ex(&md2, buf, NULL);
331ebfedea0SLionel Sambuc
332ebfedea0SLionel Sambuc for (i = passwd_len; i > sizeof buf; i -= sizeof buf)
333ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, buf, sizeof buf);
334ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, buf, i);
335ebfedea0SLionel Sambuc
336ebfedea0SLionel Sambuc n = passwd_len;
337*0a6a1f1dSLionel Sambuc while (n) {
338ebfedea0SLionel Sambuc EVP_DigestUpdate(&md, (n & 1) ? "\0" : passwd, 1);
339ebfedea0SLionel Sambuc n >>= 1;
340ebfedea0SLionel Sambuc }
341ebfedea0SLionel Sambuc EVP_DigestFinal_ex(&md, buf, NULL);
342ebfedea0SLionel Sambuc
343*0a6a1f1dSLionel Sambuc for (i = 0; i < 1000; i++) {
344ebfedea0SLionel Sambuc EVP_DigestInit_ex(&md2, EVP_md5(), NULL);
345ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, (i & 1) ? (unsigned const char *)passwd : buf,
346ebfedea0SLionel Sambuc (i & 1) ? passwd_len : sizeof buf);
347ebfedea0SLionel Sambuc if (i % 3)
348ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, salt_out, salt_len);
349ebfedea0SLionel Sambuc if (i % 7)
350ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, passwd, passwd_len);
351ebfedea0SLionel Sambuc EVP_DigestUpdate(&md2, (i & 1) ? buf : (unsigned const char *)passwd,
352ebfedea0SLionel Sambuc (i & 1) ? sizeof buf : passwd_len);
353ebfedea0SLionel Sambuc EVP_DigestFinal_ex(&md2, buf, NULL);
354ebfedea0SLionel Sambuc }
355ebfedea0SLionel Sambuc EVP_MD_CTX_cleanup(&md2);
356ebfedea0SLionel Sambuc
357ebfedea0SLionel Sambuc {
358ebfedea0SLionel Sambuc /* transform buf into output string */
359ebfedea0SLionel Sambuc
360ebfedea0SLionel Sambuc unsigned char buf_perm[sizeof buf];
361ebfedea0SLionel Sambuc int dest, source;
362ebfedea0SLionel Sambuc char *output;
363ebfedea0SLionel Sambuc
364ebfedea0SLionel Sambuc /* silly output permutation */
365*0a6a1f1dSLionel Sambuc for (dest = 0, source = 0; dest < 14;
366*0a6a1f1dSLionel Sambuc dest++, source = (source + 6) % 17)
367ebfedea0SLionel Sambuc buf_perm[dest] = buf[source];
368ebfedea0SLionel Sambuc buf_perm[14] = buf[5];
369ebfedea0SLionel Sambuc buf_perm[15] = buf[11];
370*0a6a1f1dSLionel Sambuc # ifndef PEDANTIC /* Unfortunately, this generates a "no
371*0a6a1f1dSLionel Sambuc * effect" warning */
372ebfedea0SLionel Sambuc assert(16 == sizeof buf_perm);
373ebfedea0SLionel Sambuc # endif
374ebfedea0SLionel Sambuc
375ebfedea0SLionel Sambuc output = salt_out + salt_len;
376ebfedea0SLionel Sambuc assert(output == out_buf + strlen(out_buf));
377ebfedea0SLionel Sambuc
378ebfedea0SLionel Sambuc *output++ = '$';
379ebfedea0SLionel Sambuc
380*0a6a1f1dSLionel Sambuc for (i = 0; i < 15; i += 3) {
381ebfedea0SLionel Sambuc *output++ = cov_2char[buf_perm[i + 2] & 0x3f];
382ebfedea0SLionel Sambuc *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) |
383ebfedea0SLionel Sambuc (buf_perm[i + 2] >> 6)];
384ebfedea0SLionel Sambuc *output++ = cov_2char[((buf_perm[i] & 3) << 4) |
385ebfedea0SLionel Sambuc (buf_perm[i + 1] >> 4)];
386ebfedea0SLionel Sambuc *output++ = cov_2char[buf_perm[i] >> 2];
387ebfedea0SLionel Sambuc }
388ebfedea0SLionel Sambuc assert(i == 15);
389ebfedea0SLionel Sambuc *output++ = cov_2char[buf_perm[i] & 0x3f];
390ebfedea0SLionel Sambuc *output++ = cov_2char[buf_perm[i] >> 6];
391ebfedea0SLionel Sambuc *output = 0;
392ebfedea0SLionel Sambuc assert(strlen(out_buf) < sizeof(out_buf));
393ebfedea0SLionel Sambuc }
394ebfedea0SLionel Sambuc EVP_MD_CTX_cleanup(&md);
395ebfedea0SLionel Sambuc
396ebfedea0SLionel Sambuc return out_buf;
397ebfedea0SLionel Sambuc }
398ebfedea0SLionel Sambuc # endif
399ebfedea0SLionel Sambuc
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)400ebfedea0SLionel Sambuc static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
401*0a6a1f1dSLionel Sambuc char *passwd, BIO *out, int quiet, int table,
402*0a6a1f1dSLionel Sambuc int reverse, size_t pw_maxlen, int usecrypt, int use1,
403*0a6a1f1dSLionel Sambuc int useapr1)
404ebfedea0SLionel Sambuc {
405ebfedea0SLionel Sambuc char *hash = NULL;
406ebfedea0SLionel Sambuc
407ebfedea0SLionel Sambuc assert(salt_p != NULL);
408ebfedea0SLionel Sambuc assert(salt_malloc_p != NULL);
409ebfedea0SLionel Sambuc
410ebfedea0SLionel Sambuc /* first make sure we have a salt */
411*0a6a1f1dSLionel Sambuc if (!passed_salt) {
412ebfedea0SLionel Sambuc # ifndef OPENSSL_NO_DES
413*0a6a1f1dSLionel Sambuc if (usecrypt) {
414*0a6a1f1dSLionel Sambuc if (*salt_malloc_p == NULL) {
415ebfedea0SLionel Sambuc *salt_p = *salt_malloc_p = OPENSSL_malloc(3);
416ebfedea0SLionel Sambuc if (*salt_malloc_p == NULL)
417ebfedea0SLionel Sambuc goto err;
418ebfedea0SLionel Sambuc }
419ebfedea0SLionel Sambuc if (RAND_pseudo_bytes((unsigned char *)*salt_p, 2) < 0)
420ebfedea0SLionel Sambuc goto err;
421ebfedea0SLionel Sambuc (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
422ebfedea0SLionel Sambuc (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
423ebfedea0SLionel Sambuc (*salt_p)[2] = 0;
424ebfedea0SLionel Sambuc # ifdef CHARSET_EBCDIC
425*0a6a1f1dSLionel Sambuc ascii2ebcdic(*salt_p, *salt_p, 2); /* des_crypt will convert back
426*0a6a1f1dSLionel Sambuc * to ASCII */
427ebfedea0SLionel Sambuc # endif
428ebfedea0SLionel Sambuc }
429ebfedea0SLionel Sambuc # endif /* !OPENSSL_NO_DES */
430ebfedea0SLionel Sambuc
431ebfedea0SLionel Sambuc # ifndef NO_MD5CRYPT_1
432*0a6a1f1dSLionel Sambuc if (use1 || useapr1) {
433ebfedea0SLionel Sambuc int i;
434ebfedea0SLionel Sambuc
435*0a6a1f1dSLionel Sambuc if (*salt_malloc_p == NULL) {
436ebfedea0SLionel Sambuc *salt_p = *salt_malloc_p = OPENSSL_malloc(9);
437ebfedea0SLionel Sambuc if (*salt_malloc_p == NULL)
438ebfedea0SLionel Sambuc goto err;
439ebfedea0SLionel Sambuc }
440ebfedea0SLionel Sambuc if (RAND_pseudo_bytes((unsigned char *)*salt_p, 8) < 0)
441ebfedea0SLionel Sambuc goto err;
442ebfedea0SLionel Sambuc
443ebfedea0SLionel Sambuc for (i = 0; i < 8; i++)
444ebfedea0SLionel Sambuc (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */
445ebfedea0SLionel Sambuc (*salt_p)[8] = 0;
446ebfedea0SLionel Sambuc }
447ebfedea0SLionel Sambuc # endif /* !NO_MD5CRYPT_1 */
448ebfedea0SLionel Sambuc }
449ebfedea0SLionel Sambuc
450ebfedea0SLionel Sambuc assert(*salt_p != NULL);
451ebfedea0SLionel Sambuc
452ebfedea0SLionel Sambuc /* truncate password if necessary */
453*0a6a1f1dSLionel Sambuc if ((strlen(passwd) > pw_maxlen)) {
454ebfedea0SLionel Sambuc if (!quiet)
455*0a6a1f1dSLionel Sambuc /*
456*0a6a1f1dSLionel Sambuc * XXX: really we should know how to print a size_t, not cast it
457*0a6a1f1dSLionel Sambuc */
458*0a6a1f1dSLionel Sambuc BIO_printf(bio_err,
459*0a6a1f1dSLionel Sambuc "Warning: truncating password to %u characters\n",
460*0a6a1f1dSLionel Sambuc (unsigned)pw_maxlen);
461ebfedea0SLionel Sambuc passwd[pw_maxlen] = 0;
462ebfedea0SLionel Sambuc }
463ebfedea0SLionel Sambuc assert(strlen(passwd) <= pw_maxlen);
464ebfedea0SLionel Sambuc
465ebfedea0SLionel Sambuc /* now compute password hash */
466ebfedea0SLionel Sambuc # ifndef OPENSSL_NO_DES
467ebfedea0SLionel Sambuc if (usecrypt)
468ebfedea0SLionel Sambuc hash = DES_crypt(passwd, *salt_p);
469ebfedea0SLionel Sambuc # endif
470ebfedea0SLionel Sambuc # ifndef NO_MD5CRYPT_1
471ebfedea0SLionel Sambuc if (use1 || useapr1)
472ebfedea0SLionel Sambuc hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p);
473ebfedea0SLionel Sambuc # endif
474ebfedea0SLionel Sambuc assert(hash != NULL);
475ebfedea0SLionel Sambuc
476ebfedea0SLionel Sambuc if (table && !reverse)
477ebfedea0SLionel Sambuc BIO_printf(out, "%s\t%s\n", passwd, hash);
478ebfedea0SLionel Sambuc else if (table && reverse)
479ebfedea0SLionel Sambuc BIO_printf(out, "%s\t%s\n", hash, passwd);
480ebfedea0SLionel Sambuc else
481ebfedea0SLionel Sambuc BIO_printf(out, "%s\n", hash);
482ebfedea0SLionel Sambuc return 1;
483ebfedea0SLionel Sambuc
484ebfedea0SLionel Sambuc err:
485ebfedea0SLionel Sambuc return 0;
486ebfedea0SLionel Sambuc }
487ebfedea0SLionel Sambuc #else
488ebfedea0SLionel Sambuc
MAIN(int argc,char ** argv)489ebfedea0SLionel Sambuc int MAIN(int argc, char **argv)
490ebfedea0SLionel Sambuc {
491ebfedea0SLionel Sambuc fputs("Program not available.\n", stderr)
492ebfedea0SLionel Sambuc OPENSSL_EXIT(1);
493ebfedea0SLionel Sambuc }
494ebfedea0SLionel Sambuc #endif
495