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