summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Fritsch <sf@apache.org>2012-10-07 09:06:10 +0000
committerStefan Fritsch <sf@apache.org>2012-10-07 09:06:10 +0000
commitc2eb43db553701ec12e693d13bca8c7bca113061 (patch)
treeac64181b7412122b2d499d745c0d872d40764019
parent65d07ff463e94a8689a8a93bbe7706ba3734c503 (diff)
downloadhttpd-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--CHANGES3
-rw-r--r--support/htdbm.c22
-rw-r--r--support/htpasswd.c14
-rw-r--r--support/passwd_common.c48
-rw-r--r--support/passwd_common.h14
5 files changed, 87 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index f466c36f53..0460e1e4c0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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