diff options
author | Stefan Fritsch <sf@apache.org> | 2012-10-07 09:06:10 +0000 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2012-10-07 09:06:10 +0000 |
commit | c2eb43db553701ec12e693d13bca8c7bca113061 (patch) | |
tree | ac64181b7412122b2d499d745c0d872d40764019 | |
parent | 65d07ff463e94a8689a8a93bbe7706ba3734c503 (diff) | |
download | httpd-c2eb43db553701ec12e693d13bca8c7bca113061.tar.gz |
add support for bcrypt
PR: 49288
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1395255 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | support/htdbm.c | 22 | ||||
-rw-r--r-- | support/htpasswd.c | 14 | ||||
-rw-r--r-- | support/passwd_common.c | 48 | ||||
-rw-r--r-- | support/passwd_common.h | 14 |
5 files changed, 87 insertions, 14 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) htpasswd, htdbm: Add support for bcrypt algorithm (requires + apr-util 1.5 or higher). PR 49288. [Stefan Fritsch] + *) htpasswd, htdbm: Put full 48bit of entropy into salt, improve error handling. Add some of htpasswd's improvements to htdbm, e.g. warn if password is truncated by crypt(). [Stefan Fritsch] diff --git a/support/htdbm.c b/support/htdbm.c index 95b29ee0cf..c208b8428a 100644 --- a/support/htdbm.c +++ b/support/htdbm.c @@ -276,29 +276,33 @@ static void htdbm_usage(void) { fprintf(stderr, "htdbm -- program for manipulating DBM password databases.\n\n" - "Usage: htdbm [-cmdpstvx] [-TDBTYPE] database username\n" - " -b[cmdptsv] [-TDBTYPE] database username password\n" - " -n[mdpst] username\n" - " -nb[mdpst] username password\n" - " -v[mdps] [-TDBTYPE] database username\n" - " -vb[mdps] [-TDBTYPE] database username password\n" - " -x [-TDBTYPE] database username\n" - " -l [-TDBTYPE] database\n" + "Usage: htdbm [-cmBdpstvx] [-Ccost] [-TDBTYPE] database username\n" + " -b[cmBdptsv] [-Ccost] [-TDBTYPE] database username password\n" + " -n[mBdpst] [-Ccost] username\n" + " -nb[mBdpst] [-Ccost] username password\n" + " -v[mBdps] [-Ccost] [-TDBTYPE] database username\n" + " -vb[mBdps] [-Ccost] [-TDBTYPE] database username password\n" + " -x [-Ccost] [-TDBTYPE] database username\n" + " -l [-Ccost] [-TDBTYPE] database\n" "Options:\n" " -b Use the password from the command line rather than prompting for it.\n" " -c Create a new database.\n" " -n Don't update database; display results on stdout.\n" " -m Force MD5 encryption of the password (default).\n" + " -B Force BCRYPT encryption of the password (very secure).\n" " -d Force CRYPT encryption of the password (8 chars max, insecure).\n" " -p Do not encrypt the password (plaintext).\n" " -s Force SHA encryption of the password (insecure).\n" + " -C Set the computing time used for the bcrypt algorithm.\n" + " (higher is more secure but slower, default: %d, valid: 4 to 31)\n" " -T DBM Type (SDBM|GDBM|DB|default).\n" " -l Display usernames from database on stdout.\n" " -t The last param is username comment.\n" " -v Verify the username/password.\n" " -x Remove the username record from database.\n" "The SHA algorithm does not use a salt and is less secure than the " - "MD5 algorithm.\n"); + "MD5 algorithm.\n", + BCRYPT_DEFAULT_COST); exit(ERR_SYNTAX); } diff --git a/support/htpasswd.c b/support/htpasswd.c index cdf7f311bd..aed716a0fe 100644 --- a/support/htpasswd.c +++ b/support/htpasswd.c @@ -92,14 +92,17 @@ static int mkrecord(struct passwd_ctx *ctx, char *user) static void usage(void) { apr_file_printf(errfile, "Usage:" NL - "\thtpasswd [-cmdpsD] passwordfile username" NL - "\thtpasswd -b[cmdpsD] passwordfile username password" NL + "\thtpasswd [-cmBdpsD] [-C cost] passwordfile username" NL + "\thtpasswd -b[cmBdpsD] [-C cost] passwordfile username password" NL NL - "\thtpasswd -n[mdps] username" NL - "\thtpasswd -nb[mdps] username password" NL + "\thtpasswd -n[mBdps] [-C cost] username" NL + "\thtpasswd -nb[mBdps] [-C cost] username password" NL " -c Create a new file." NL " -n Don't update file; display results on stdout." NL " -m Force MD5 encryption of the password (default)." NL + " -B Force bcrypt encryption of the password (very secure)." NL + " -C Set the computing time used for the bcrypt algorithm" NL + " (higher is more secure but slower, default: %d, valid: 4 to 31)" NL " -d Force CRYPT encryption of the password (8 chars max, " "insecure)." NL " -p Do not encrypt the password (plaintext, insecure)." NL @@ -110,7 +113,8 @@ static void usage(void) "On other systems than Windows and NetWare the '-p' flag will " "probably not work." NL "The SHA algorithm does not use a salt and is less secure than the " - "MD5 algorithm." NL + "MD5 algorithm." NL, + BCRYPT_DEFAULT_COST ); exit(ERR_SYNTAX); } diff --git a/support/passwd_common.c b/support/passwd_common.c index 5458fad396..2a5b2d8695 100644 --- a/support/passwd_common.c +++ b/support/passwd_common.c @@ -131,6 +131,11 @@ int mkhash(struct passwd_ctx *ctx) char *cbuf; #endif + if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT) { + apr_file_printf(errfile, + "Warning: Ignoring -C argument for this algorithm." NL); + } + if (ctx->passwd != NULL) { pw = ctx->passwd; } @@ -189,6 +194,30 @@ int mkhash(struct passwd_ctx *ctx) } break; #endif /* CRYPT_ALGO_SUPPORTED */ + +#if BCRYPT_ALGO_SUPPORTED + case ALG_BCRYPT: + rv = apr_generate_random_bytes((unsigned char*)salt, 16); + if (rv != APR_SUCCESS) { + ctx->errstr = apr_psprintf(ctx->pool, "Unable to generate random " + "bytes: %pm", &rv); + ret = ERR_RANDOM; + break; + } + + if (ctx->cost == 0) + ctx->cost = BCRYPT_DEFAULT_COST; + rv = apr_bcrypt_encode(pw, ctx->cost, (unsigned char*)salt, 16, + ctx->out, ctx->out_len); + if (rv != APR_SUCCESS) { + ctx->errstr = apr_psprintf(ctx->pool, "Unable to encode with " + "bcrypt: %pm", &rv); + ret = ERR_PWMISMATCH; + break; + } + break; +#endif /* BCRYPT_ALGO_SUPPORTED */ + default: apr_file_printf(errfile, "%s: BUG: invalid algorithm %d", __func__, ctx->alg); @@ -232,6 +261,25 @@ int parse_common_options(struct passwd_ctx *ctx, char opt, ctx->alg = ALG_APMD5; #endif break; + case 'B': +#if BCRYPT_ALGO_SUPPORTED + ctx->alg = ALG_BCRYPT; +#else + /* Don't fall back to something less secure */ + ctx->errstr = "BCRYPT algorithm not supported on this platform"; + return ERR_ALG_NOT_SUPP; +#endif + break; + case 'C': { + char *endptr; + long num = strtol(opt_arg, &endptr, 10); + if (*endptr != '\0' || num <= 0) { + ctx->errstr = "argument to -C must be a positive integer"; + return ERR_SYNTAX; + } + ctx->cost = num; + break; + } default: apr_file_printf(errfile, "%s: BUG: invalid option %c", __func__, opt); abort(); diff --git a/support/passwd_common.h b/support/passwd_common.h index 79341dda6f..6fc5b712cd 100644 --- a/support/passwd_common.h +++ b/support/passwd_common.h @@ -21,6 +21,9 @@ #include "apr_file_io.h" #include "apr_general.h" #include "apr_version.h" +#if !APR_VERSION_AT_LEAST(2,0,0) +#include "apu_version.h" +#endif #define MAX_STRING_LEN 256 @@ -28,6 +31,9 @@ #define ALG_CRYPT 1 #define ALG_APMD5 2 #define ALG_APSHA 3 +#define ALG_BCRYPT 4 + +#define BCRYPT_DEFAULT_COST 5 #define ERR_FILEPERM 1 #define ERR_SYNTAX 2 @@ -50,6 +56,13 @@ #define PLAIN_ALGO_SUPPORTED 0 #endif +#if APR_VERSION_AT_LEAST(2,0,0) || \ + (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 5) +#define BCRYPT_ALGO_SUPPORTED 1 +#else +#define BCRYPT_ALGO_SUPPORTED 0 +#endif + /* * Must be initialized with apr_file_open_stderr() before using any of the * below functions. @@ -63,6 +76,7 @@ struct passwd_ctx { apr_size_t out_len; char *passwd; int alg; + int cost; enum { PW_PROMPT = 0, PW_ARG |