xref: /minix3/crypto/external/bsd/openssl/dist/apps/passwd.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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