diff --git a/apps/passwd.c b/apps/passwd.c index 681af49b8ef16e0c1e665d7981f32a2eacf30b4c..9be92843ea3c3d9faef7af35315657a822c4fbf8 100644 --- a/apps/passwd.c +++ b/apps/passwd.c @@ -53,7 +53,8 @@ typedef enum { passwd_md5, passwd_apr1, passwd_sha256, - passwd_sha512 + passwd_sha512, + passwd_aixmd5 } passwd_modes; static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, @@ -64,7 +65,7 @@ typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_IN, OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1, - OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_SALT, OPT_STDIN + OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN } OPTION_CHOICE; const OPTIONS passwd_options[] = { @@ -84,6 +85,7 @@ const OPTIONS passwd_options[] = { # ifndef NO_MD5CRYPT_1 {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"}, {"1", OPT_1, '-', "MD5-based password algorithm"}, + {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"}, # endif # ifndef OPENSSL_NO_DES {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"}, @@ -160,6 +162,11 @@ int passwd_main(int argc, char **argv) goto opthelp; mode = passwd_apr1; break; + case OPT_AIXMD5: + if (mode != passwd_unset) + goto opthelp; + mode = passwd_aixmd5; + break; case OPT_CRYPT: if (mode != passwd_unset) goto opthelp; @@ -197,7 +204,7 @@ int passwd_main(int argc, char **argv) goto opthelp; # endif # ifdef NO_MD5CRYPT_1 - if (mode == passwd_md5 || mode == passwd_apr1) + if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5) goto opthelp; # endif # ifdef NO_SHACRYPT @@ -325,21 +332,29 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) size_t passwd_len, salt_len, magic_len; passwd_len = strlen(passwd); - out_buf[0] = '$'; - out_buf[1] = 0; + + out_buf[0] = 0; magic_len = strlen(magic); - if (magic_len > 4) /* assert it's "1" or "apr1" */ - return NULL; + if (magic_len > 0) { + out_buf[0] = '$'; + out_buf[1] = 0; + + if (magic_len > 4) /* assert it's "1" or "apr1" */ + return NULL; + + OPENSSL_strlcat(out_buf, magic, sizeof out_buf); + OPENSSL_strlcat(out_buf, "$", sizeof out_buf); + } - OPENSSL_strlcat(out_buf, magic, sizeof out_buf); - OPENSSL_strlcat(out_buf, "$", sizeof out_buf); OPENSSL_strlcat(out_buf, salt, sizeof out_buf); if (strlen(out_buf) > 6 + 8) /* assert "$apr1$..salt.." */ return NULL; - salt_out = out_buf + 2 + magic_len; + salt_out = out_buf; + if (magic_len > 0) + salt_out += 2 + magic_len; salt_len = strlen(salt_out); if (salt_len > 8) @@ -348,11 +363,16 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) md = EVP_MD_CTX_new(); if (md == NULL || !EVP_DigestInit_ex(md, EVP_md5(), NULL) - || !EVP_DigestUpdate(md, passwd, passwd_len) - || !EVP_DigestUpdate(md, "$", 1) - || !EVP_DigestUpdate(md, magic, magic_len) - || !EVP_DigestUpdate(md, "$", 1) - || !EVP_DigestUpdate(md, salt_out, salt_len)) + || !EVP_DigestUpdate(md, passwd, passwd_len)) + goto err; + + if (magic_len > 0) + if (!EVP_DigestUpdate(md, "$", 1) + || !EVP_DigestUpdate(md, magic, magic_len) + || !EVP_DigestUpdate(md, "$", 1)) + goto err; + + if (!EVP_DigestUpdate(md, salt_out, salt_len)) goto err; md2 = EVP_MD_CTX_new(); @@ -742,7 +762,7 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, # endif /* !OPENSSL_NO_DES */ # ifndef NO_MD5CRYPT_1 - if (mode == passwd_md5 || mode == passwd_apr1) { + if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5) { int i; if (*salt_malloc_p == NULL) { @@ -797,6 +817,8 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, # ifndef NO_MD5CRYPT_1 if (mode == passwd_md5 || mode == passwd_apr1) hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p); + if (mode == passwd_aixmd5) + hash = md5crypt(passwd, "", *salt_p); # endif # ifndef NO_SHACRYPT if (mode == passwd_sha256 || mode == passwd_sha512) diff --git a/doc/man1/passwd.pod b/doc/man1/passwd.pod index fa11f630cf5f50a4a358ed952088f177b297ee9e..02f6339883354f96bc63278c7c79a89ab4b29285 100644 --- a/doc/man1/passwd.pod +++ b/doc/man1/passwd.pod @@ -11,6 +11,7 @@ B [B<-crypt>] [B<-1>] [B<-apr1>] +[B<-aixmd5>] [B<-5>] [B<-6>] [B<-salt> I] @@ -28,7 +29,7 @@ run-time or the hash of each password in a list. The password list is taken from the named file for option B<-in file>, from stdin for option B<-stdin>, or from the command line, or from the terminal otherwise. The Unix standard algorithm B and the MD5-based BSD password -algorithm B<1> and its Apache variant B are available. +algorithm B<1>, its Apache variant B, and its AIX variant are available. =head1 OPTIONS @@ -50,6 +51,10 @@ Use the MD5 based BSD password algorithm B<1>. Use the B algorithm (Apache variant of the BSD algorithm). +=item B<-aixmd5> + +Use the B algorithm (AIX variant of the BSD algorithm). + =item B<-5> =item B<-6> @@ -93,6 +98,8 @@ B prints B<$1$xxxxxxxx$UYCIxa628.9qXj B prints B<$apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0>. +B prints B. + =head1 COPYRIGHT Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. diff --git a/test/recipes/20-test_passwd.t b/test/recipes/20-test_passwd.t index 5b69f88a49f3bfbfde10d25c908c61756baae2cb..32aa7a3171b5ebddaa12cb07d9f88eb11cd78a16 100644 --- a/test/recipes/20-test_passwd.t +++ b/test/recipes/20-test_passwd.t @@ -76,7 +76,7 @@ my @sha_tests = expected => '$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX.' } ); -plan tests => (disabled("des") ? 8 : 10) + scalar @sha_tests; +plan tests => (disabled("des") ? 9 : 11) + scalar @sha_tests; ok(compare1stline_re([qw{openssl passwd password}], '^.{13}\R$'), @@ -96,6 +96,8 @@ ok(compare1stline([qw{openssl passwd -salt xxxxxxxx -1 password}], '$1$xxxxxxxx$ 'BSD style MD5 password with salt xxxxxxxx'); ok(compare1stline([qw{openssl passwd -salt xxxxxxxx -apr1 password}], '$apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0'), 'Apache style MD5 password with salt xxxxxxxx'); +ok(compare1stline([qw{openssl passwd -salt xxxxxxxx -aixmd5 password}], 'xxxxxxxx$8Oaipk/GPKhC64w/YVeFD/'), + 'AIX style MD5 password with salt xxxxxxxx'); ok(compare1stline([qw{openssl passwd -salt xxxxxxxxxxxxxxxx -5 password}], '$5$xxxxxxxxxxxxxxxx$fHytsM.wVD..zPN/h3i40WJRggt/1f73XkAC/gkelkB'), 'SHA256 password with salt xxxxxxxxxxxxxxxx'); ok(compare1stline([qw{openssl passwd -salt xxxxxxxxxxxxxxxx -6 password}], '$6$xxxxxxxxxxxxxxxx$VjGUrXBG6/8yW0f6ikBJVOb/lK/Tm9LxHJmFfwMvT7cpk64N9BW7ZQhNeMXAYFbOJ6HDG7wb0QpxJyYQn0rh81'),