add support for bcrypt

PR: 49288


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1395255 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stefan Fritsch
2012-10-07 09:06:10 +00:00
parent 65d07ff463
commit c2eb43db55
5 changed files with 87 additions and 14 deletions

View File

@ -1,6 +1,9 @@
-*- coding: utf-8 -*- -*- coding: utf-8 -*-
Changes with Apache 2.5.0 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 *) htpasswd, htdbm: Put full 48bit of entropy into salt, improve
error handling. Add some of htpasswd's improvements to htdbm, error handling. Add some of htpasswd's improvements to htdbm,
e.g. warn if password is truncated by crypt(). [Stefan Fritsch] e.g. warn if password is truncated by crypt(). [Stefan Fritsch]

View File

@ -276,29 +276,33 @@ static void htdbm_usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"htdbm -- program for manipulating DBM password databases.\n\n" "htdbm -- program for manipulating DBM password databases.\n\n"
"Usage: htdbm [-cmdpstvx] [-TDBTYPE] database username\n" "Usage: htdbm [-cmBdpstvx] [-Ccost] [-TDBTYPE] database username\n"
" -b[cmdptsv] [-TDBTYPE] database username password\n" " -b[cmBdptsv] [-Ccost] [-TDBTYPE] database username password\n"
" -n[mdpst] username\n" " -n[mBdpst] [-Ccost] username\n"
" -nb[mdpst] username password\n" " -nb[mBdpst] [-Ccost] username password\n"
" -v[mdps] [-TDBTYPE] database username\n" " -v[mBdps] [-Ccost] [-TDBTYPE] database username\n"
" -vb[mdps] [-TDBTYPE] database username password\n" " -vb[mBdps] [-Ccost] [-TDBTYPE] database username password\n"
" -x [-TDBTYPE] database username\n" " -x [-Ccost] [-TDBTYPE] database username\n"
" -l [-TDBTYPE] database\n" " -l [-Ccost] [-TDBTYPE] database\n"
"Options:\n" "Options:\n"
" -b Use the password from the command line rather than prompting for it.\n" " -b Use the password from the command line rather than prompting for it.\n"
" -c Create a new database.\n" " -c Create a new database.\n"
" -n Don't update database; display results on stdout.\n" " -n Don't update database; display results on stdout.\n"
" -m Force MD5 encryption of the password (default).\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" " -d Force CRYPT encryption of the password (8 chars max, insecure).\n"
" -p Do not encrypt the password (plaintext).\n" " -p Do not encrypt the password (plaintext).\n"
" -s Force SHA encryption of the password (insecure).\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" " -T DBM Type (SDBM|GDBM|DB|default).\n"
" -l Display usernames from database on stdout.\n" " -l Display usernames from database on stdout.\n"
" -t The last param is username comment.\n" " -t The last param is username comment.\n"
" -v Verify the username/password.\n" " -v Verify the username/password.\n"
" -x Remove the username record from database.\n" " -x Remove the username record from database.\n"
"The SHA algorithm does not use a salt and is less secure than the " "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); exit(ERR_SYNTAX);
} }

View File

@ -92,14 +92,17 @@ static int mkrecord(struct passwd_ctx *ctx, char *user)
static void usage(void) static void usage(void)
{ {
apr_file_printf(errfile, "Usage:" NL apr_file_printf(errfile, "Usage:" NL
"\thtpasswd [-cmdpsD] passwordfile username" NL "\thtpasswd [-cmBdpsD] [-C cost] passwordfile username" NL
"\thtpasswd -b[cmdpsD] passwordfile username password" NL "\thtpasswd -b[cmBdpsD] [-C cost] passwordfile username password" NL
NL NL
"\thtpasswd -n[mdps] username" NL "\thtpasswd -n[mBdps] [-C cost] username" NL
"\thtpasswd -nb[mdps] username password" NL "\thtpasswd -nb[mBdps] [-C cost] username password" NL
" -c Create a new file." NL " -c Create a new file." NL
" -n Don't update file; display results on stdout." NL " -n Don't update file; display results on stdout." NL
" -m Force MD5 encryption of the password (default)." 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, " " -d Force CRYPT encryption of the password (8 chars max, "
"insecure)." NL "insecure)." NL
" -p Do not encrypt the password (plaintext, 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 " "On other systems than Windows and NetWare the '-p' flag will "
"probably not work." NL "probably not work." NL
"The SHA algorithm does not use a salt and is less secure than the " "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); exit(ERR_SYNTAX);
} }

View File

@ -131,6 +131,11 @@ int mkhash(struct passwd_ctx *ctx)
char *cbuf; char *cbuf;
#endif #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) { if (ctx->passwd != NULL) {
pw = ctx->passwd; pw = ctx->passwd;
} }
@ -189,6 +194,30 @@ int mkhash(struct passwd_ctx *ctx)
} }
break; break;
#endif /* CRYPT_ALGO_SUPPORTED */ #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: default:
apr_file_printf(errfile, "%s: BUG: invalid algorithm %d", __func__, apr_file_printf(errfile, "%s: BUG: invalid algorithm %d", __func__,
ctx->alg); ctx->alg);
@ -232,6 +261,25 @@ int parse_common_options(struct passwd_ctx *ctx, char opt,
ctx->alg = ALG_APMD5; ctx->alg = ALG_APMD5;
#endif #endif
break; 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: default:
apr_file_printf(errfile, "%s: BUG: invalid option %c", __func__, opt); apr_file_printf(errfile, "%s: BUG: invalid option %c", __func__, opt);
abort(); abort();

View File

@ -21,6 +21,9 @@
#include "apr_file_io.h" #include "apr_file_io.h"
#include "apr_general.h" #include "apr_general.h"
#include "apr_version.h" #include "apr_version.h"
#if !APR_VERSION_AT_LEAST(2,0,0)
#include "apu_version.h"
#endif
#define MAX_STRING_LEN 256 #define MAX_STRING_LEN 256
@ -28,6 +31,9 @@
#define ALG_CRYPT 1 #define ALG_CRYPT 1
#define ALG_APMD5 2 #define ALG_APMD5 2
#define ALG_APSHA 3 #define ALG_APSHA 3
#define ALG_BCRYPT 4
#define BCRYPT_DEFAULT_COST 5
#define ERR_FILEPERM 1 #define ERR_FILEPERM 1
#define ERR_SYNTAX 2 #define ERR_SYNTAX 2
@ -50,6 +56,13 @@
#define PLAIN_ALGO_SUPPORTED 0 #define PLAIN_ALGO_SUPPORTED 0
#endif #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 * Must be initialized with apr_file_open_stderr() before using any of the
* below functions. * below functions.
@ -63,6 +76,7 @@ struct passwd_ctx {
apr_size_t out_len; apr_size_t out_len;
char *passwd; char *passwd;
int alg; int alg;
int cost;
enum { enum {
PW_PROMPT = 0, PW_PROMPT = 0,
PW_ARG PW_ARG