From: Stefan Fritsch Date: Sun, 7 Oct 2012 09:10:14 +0000 (+0000) Subject: Optionally read passwords from stdin X-Git-Tag: 2.5.0-alpha~6223 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=566312f891445678481d3a5cb5050f12fb518f3a;p=thirdparty%2Fapache%2Fhttpd.git Optionally read passwords from stdin PR: 40243 Submitted by: Adomas Paltanavicius , sf git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1395256 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 0460e1e4c01..86bb45cf07b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) htpasswd, htdbm: Optionally read passwords from stdin, as more + secure alternative to -b. PR 40243. [Adomas Paltanavicius , Stefan Fritsch] + *) htpasswd, htdbm: Add support for bcrypt algorithm (requires apr-util 1.5 or higher). PR 49288. [Stefan Fritsch] diff --git a/support/htdbm.c b/support/htdbm.c index c208b8428a8..1ce57436d8a 100644 --- a/support/htdbm.c +++ b/support/htdbm.c @@ -276,11 +276,11 @@ static void htdbm_usage(void) { fprintf(stderr, "htdbm -- program for manipulating DBM password databases.\n\n" - "Usage: htdbm [-cmBdpstvx] [-Ccost] [-TDBTYPE] database username\n" + "Usage: htdbm [-cimBdpstvx] [-Ccost] [-TDBTYPE] database username\n" " -b[cmBdptsv] [-Ccost] [-TDBTYPE] database username password\n" - " -n[mBdpst] [-Ccost] username\n" + " -n[imBdpst] [-Ccost] username\n" " -nb[mBdpst] [-Ccost] username password\n" - " -v[mBdps] [-Ccost] [-TDBTYPE] database username\n" + " -v[imBdps] [-Ccost] [-TDBTYPE] database username\n" " -vb[mBdps] [-Ccost] [-TDBTYPE] database username password\n" " -x [-Ccost] [-TDBTYPE] database username\n" " -l [-Ccost] [-TDBTYPE] database\n" @@ -288,6 +288,7 @@ static void htdbm_usage(void) " -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" + " -i Read password from stdin without verification (for script usage)\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" diff --git a/support/htpasswd.c b/support/htpasswd.c index aed716a0fe3..9175a7bc404 100644 --- a/support/htpasswd.c +++ b/support/htpasswd.c @@ -92,13 +92,14 @@ static int mkrecord(struct passwd_ctx *ctx, char *user) static void usage(void) { apr_file_printf(errfile, "Usage:" NL - "\thtpasswd [-cmBdpsD] [-C cost] passwordfile username" NL + "\thtpasswd [-cimBdpsD] [-C cost] passwordfile username" NL "\thtpasswd -b[cmBdpsD] [-C cost] passwordfile username password" NL NL - "\thtpasswd -n[mBdps] [-C cost] username" NL + "\thtpasswd -n[imBdps] [-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 + " -i Read password from stdin without verification (for script usage)" 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 diff --git a/support/passwd_common.c b/support/passwd_common.c index 2a5b2d8695a..d1b10d194b5 100644 --- a/support/passwd_common.c +++ b/support/passwd_common.c @@ -95,18 +95,41 @@ void putline(apr_file_t *f, const char *l) int get_password(struct passwd_ctx *ctx) { - char buf[MAX_STRING_LEN + 1]; - apr_size_t bufsize = sizeof(buf); - if (apr_password_get("New password: ", ctx->out, &ctx->out_len) != 0) - goto err_too_long; - apr_password_get("Re-type new password: ", buf, &bufsize); - if (strcmp(ctx->out, buf) != 0) { - ctx->errstr = "password verification error"; - memset(ctx->out, '\0', ctx->out_len); + if (ctx->passwd_src == PW_STDIN) { + char *buf = ctx->out; + apr_file_t *file_stdin; + apr_size_t nread; + if (apr_file_open_stdin(&file_stdin, ctx->pool) != APR_SUCCESS) { + ctx->errstr = "Unable to read from stdin."; + return ERR_GENERAL; + } + if (apr_file_read_full(file_stdin, buf, ctx->out_len - 1, + &nread) != APR_EOF + || nread == ctx->out_len - 1) { + goto err_too_long; + } + buf[nread] = '\0'; + if (nread >= 1 && buf[nread-1] == '\n') { + buf[nread-1] = '\0'; + if (nread >= 2 && buf[nread-2] == '\r') + buf[nread-2] = '\0'; + } + apr_file_close(file_stdin); + } + else { + char buf[MAX_STRING_LEN + 1]; + apr_size_t bufsize = sizeof(buf); + if (apr_password_get("New password: ", ctx->out, &ctx->out_len) != 0) + goto err_too_long; + apr_password_get("Re-type new password: ", buf, &bufsize); + if (strcmp(ctx->out, buf) != 0) { + ctx->errstr = "password verification error"; + memset(ctx->out, '\0', ctx->out_len); + memset(buf, '\0', sizeof(buf)); + return ERR_PWMISMATCH; + } memset(buf, '\0', sizeof(buf)); - return ERR_PWMISMATCH; } - memset(buf, '\0', sizeof(buf)); return 0; err_too_long: @@ -234,6 +257,9 @@ int parse_common_options(struct passwd_ctx *ctx, char opt, case 'b': ctx->passwd_src = PW_ARG; break; + case 'i': + ctx->passwd_src = PW_STDIN; + break; case 'm': ctx->alg = ALG_APMD5; break; diff --git a/support/passwd_common.h b/support/passwd_common.h index 6fc5b712cd4..67b66da1614 100644 --- a/support/passwd_common.h +++ b/support/passwd_common.h @@ -79,7 +79,8 @@ struct passwd_ctx { int cost; enum { PW_PROMPT = 0, - PW_ARG + PW_ARG, + PW_STDIN } passwd_src; };