Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 351408 Details for
Bug 468306
htpasswd is broken in apache-2.4.4
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed patch to fix critical bug in apache-tools-2.4.4
apache-tools-2.4.4-htpasswd.patch (text/plain), 15.90 KB, created by
Chet McNeill
on 2013-06-19 17:07:24 UTC
(
hide
)
Description:
Proposed patch to fix critical bug in apache-tools-2.4.4
Filename:
MIME Type:
Creator:
Chet McNeill
Created:
2013-06-19 17:07:24 UTC
Size:
15.90 KB
patch
obsolete
>Index: support/htdbm.c >=================================================================== >--- support/htdbm.c (revision 1447461) >+++ support/htdbm.c (working copy) >@@ -110,6 +110,7 @@ > #endif > > apr_pool_create( pool, NULL); >+ apr_pool_abort_set(abort_on_oom, *pool); > apr_file_open_stderr(&errfile, *pool); > apr_signal(SIGINT, (void (*)(int)) htdbm_interrupted); > >Index: support/passwd_common.c >=================================================================== >--- support/passwd_common.c (revision 1447461) >+++ support/passwd_common.c (working copy) >@@ -46,6 +46,24 @@ > > apr_file_t *errfile; > >+int abort_on_oom(int rc) >+{ >+ const char *buf = "Error: out of memory\n"; >+ int written, count = strlen(buf); >+ do { >+ written = write(STDERR_FILENO, buf, count); >+ if (written == count) >+ break; >+ if (written > 0) { >+ buf += written; >+ count -= written; >+ } >+ } while (written >= 0 || errno == EINTR); >+ abort(); >+ /* NOTREACHED */ >+ return 0; >+} >+ > static int generate_salt(char *s, size_t size, const char **errstr, > apr_pool_t *pool) > { >@@ -85,6 +103,8 @@ > void putline(apr_file_t *f, const char *l) > { > apr_status_t rv; >+ if (f == NULL) >+ return; > rv = apr_file_puts(l, f); > if (rv != APR_SUCCESS) { > apr_file_printf(errfile, "Error writing temp file: %pm", &rv); >@@ -95,17 +115,17 @@ > > int get_password(struct passwd_ctx *ctx) > { >+ char buf[MAX_STRING_LEN + 1]; > 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, >+ if (apr_file_read_full(file_stdin, buf, sizeof(buf) - 1, > &nread) != APR_EOF >- || nread == ctx->out_len - 1) { >+ || nread == sizeof(buf) - 1) { > goto err_too_long; > } > buf[nread] = '\0'; >@@ -115,21 +135,30 @@ > buf[nread-2] = '\0'; > } > apr_file_close(file_stdin); >+ ctx->passwd = apr_pstrdup(ctx->pool, buf); > } >+ else if (ctx->passwd_src == PW_PROMPT_VERIFY) { >+ apr_size_t bufsize = sizeof(buf); >+ if (apr_password_get("Enter password: ", buf, &bufsize) != 0) >+ goto err_too_long; >+ ctx->passwd = apr_pstrdup(ctx->pool, buf); >+ } > 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) >+ if (apr_password_get("New password: ", buf, &bufsize) != 0) > goto err_too_long; >+ ctx->passwd = apr_pstrdup(ctx->pool, buf); >+ bufsize = sizeof(buf); >+ buf[0] = '\0'; > apr_password_get("Re-type new password: ", buf, &bufsize); >- if (strcmp(ctx->out, buf) != 0) { >+ if (strcmp(ctx->passwd, buf) != 0) { > ctx->errstr = "password verification error"; >- memset(ctx->out, '\0', ctx->out_len); >+ memset(ctx->passwd, '\0', strlen(ctx->passwd)); > memset(buf, '\0', sizeof(buf)); > return ERR_PWMISMATCH; > } >- memset(buf, '\0', sizeof(buf)); > } >+ memset(buf, '\0', sizeof(buf)); > return 0; > > err_too_long: >@@ -146,7 +175,6 @@ > int mkhash(struct passwd_ctx *ctx) > { > char *pw; >- char pwin[MAX_STRING_LEN]; > char salt[16]; > apr_status_t rv; > int ret = 0; >@@ -159,14 +187,11 @@ > "Warning: Ignoring -C argument for this algorithm." NL); > } > >- if (ctx->passwd != NULL) { >- pw = ctx->passwd; >- } >- else { >+ if (ctx->passwd == NULL) { > if ((ret = get_password(ctx)) != 0) > return ret; >- pw = pwin; > } >+ pw = ctx->passwd; > > switch (ctx->alg) { > case ALG_APSHA: >@@ -206,14 +231,13 @@ > > apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1); > if (strlen(pw) > 8) { >- char *truncpw = strdup(pw); >+ char *truncpw = apr_pstrdup(ctx->pool, pw); > truncpw[8] = '\0'; > if (!strcmp(ctx->out, crypt(truncpw, salt))) { > apr_file_printf(errfile, "Warning: Password truncated to 8 " > "characters by CRYPT algorithm." NL); > } > memset(truncpw, '\0', strlen(pw)); >- free(truncpw); > } > break; > #endif /* CRYPT_ALGO_SUPPORTED */ >Index: support/htdigest.c >=================================================================== >--- support/htdigest.c (revision 1447461) >+++ support/htdigest.c (working copy) >@@ -96,12 +96,15 @@ > char ch; > apr_status_t rv = APR_EINVAL; > >- while (i < (n - 1) && >+ /* we need 2 remaining bytes in buffer */ >+ while (i < (n - 2) && > ((rv = apr_file_getc(&ch, f)) == APR_SUCCESS) && (ch != '\n')) { > s[i++] = ch; > } >+ /* First remaining byte potentially used here */ > if (ch == '\n') > s[i++] = ch; >+ /* Second remaining byte used here */ > s[i] = '\0'; > > if (rv != APR_SUCCESS) >@@ -202,8 +205,8 @@ > #if APR_CHARSET_EBCDIC > rv = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, cntxt); > if (rv) { >- apr_file_printf(errfile, "apr_xlate_open(): %s (%d)\n", >- apr_strerror(rv, line, sizeof(line)), rv); >+ apr_file_printf(errfile, "apr_xlate_open(): %pm (%d)\n", >+ &rv, rv); > exit(1); > } > #endif >@@ -215,11 +218,8 @@ > rv = apr_file_open(&f, argv[2], APR_WRITE | APR_CREATE, > APR_OS_DEFAULT, cntxt); > if (rv != APR_SUCCESS) { >- char errmsg[120]; >- >- apr_file_printf(errfile, "Could not open passwd file %s for writing: %s\n", >- argv[2], >- apr_strerror(rv, errmsg, sizeof errmsg)); >+ apr_file_printf(errfile, "Could not open passwd file %s for writing: %pm\n", >+ argv[2], &rv); > exit(1); > } > apr_cpystrn(user, argv[4], sizeof(user)); >Index: support/passwd_common.h >=================================================================== >--- support/passwd_common.h (revision 1447461) >+++ support/passwd_common.h (working copy) >@@ -80,11 +80,18 @@ > enum { > PW_PROMPT = 0, > PW_ARG, >- PW_STDIN >+ PW_STDIN, >+ PW_PROMPT_VERIFY, > } passwd_src; > }; > >+ > /* >+ * To be used as apr_pool_abort_fn >+ */ >+int abort_on_oom(int rc); >+ >+/* > * Write a line to the file. On error, print a message and exit > */ > void putline(apr_file_t *f, const char *l); >Index: support/htpasswd.c >=================================================================== >--- support/htpasswd.c (revision 1447461) >+++ support/htpasswd.c (working copy) >@@ -67,6 +67,7 @@ > #define APHTP_NEWFILE 1 > #define APHTP_NOFILE 2 > #define APHTP_DELUSER 4 >+#define APHTP_VERIFY 8 > > apr_file_t *ftemp = NULL; > >@@ -92,8 +93,8 @@ > static void usage(void) > { > apr_file_printf(errfile, "Usage:" NL >- "\thtpasswd [-cimBdpsD] [-C cost] passwordfile username" NL >- "\thtpasswd -b[cmBdpsD] [-C cost] passwordfile username password" NL >+ "\thtpasswd [-cimBdpsDv] [-C cost] passwordfile username" NL >+ "\thtpasswd -b[cmBdpsDv] [-C cost] passwordfile username password" NL > NL > "\thtpasswd -n[imBdps] [-C cost] username" NL > "\thtpasswd -nb[mBdps] [-C cost] username password" NL >@@ -110,6 +111,7 @@ > " -s Force SHA encryption of the password (insecure)." NL > " -p Do not encrypt the password (plaintext, insecure)." NL > " -D Delete the specified user." NL >+ " -v Verify password for the specified user." NL > "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 " >@@ -155,7 +157,7 @@ > } > > static void check_args(int argc, const char *const argv[], >- struct passwd_ctx *ctx, int *mask, char **user, >+ struct passwd_ctx *ctx, unsigned *mask, char **user, > char **pwfilename) > { > const char *arg; >@@ -171,7 +173,7 @@ > if (rv != APR_SUCCESS) > exit(ERR_SYNTAX); > >- while ((rv = apr_getopt(state, "cnmspdBbDiC:", &opt, &opt_arg)) == APR_SUCCESS) { >+ while ((rv = apr_getopt(state, "cnmspdBbDiC:v", &opt, &opt_arg)) == APR_SUCCESS) { > switch (opt) { > case 'c': > *mask |= APHTP_NEWFILE; >@@ -183,6 +185,9 @@ > case 'D': > *mask |= APHTP_DELUSER; > break; >+ case 'v': >+ *mask |= APHTP_VERIFY; >+ break; > default: > ret = parse_common_options(ctx, opt, opt_arg); > if (ret) { >@@ -196,18 +201,15 @@ > if (rv != APR_EOF) > usage(); > >- if ((*mask & APHTP_NEWFILE) && (*mask & APHTP_NOFILE)) { >- apr_file_printf(errfile, "%s: -c and -n options conflict" NL, argv[0]); >+ if ((*mask) & (*mask - 1)) { >+ /* not a power of two, i.e. more than one flag specified */ >+ apr_file_printf(errfile, "%s: only one of -c -n -v -D may be specified" NL, >+ argv[0]); > exit(ERR_SYNTAX); > } >- if ((*mask & APHTP_NEWFILE) && (*mask & APHTP_DELUSER)) { >- apr_file_printf(errfile, "%s: -c and -D options conflict" NL, argv[0]); >- exit(ERR_SYNTAX); >- } >- if ((*mask & APHTP_NOFILE) && (*mask & APHTP_DELUSER)) { >- apr_file_printf(errfile, "%s: -n and -D options conflict" NL, argv[0]); >- exit(ERR_SYNTAX); >- } >+ if ((*mask & APHTP_VERIFY) && ctx->passwd_src == PW_PROMPT) >+ ctx->passwd_src = PW_PROMPT_VERIFY; >+ > /* > * Make sure we still have exactly the right number of arguments left > * (the filename, the username, and possibly the password if -b was >@@ -246,6 +248,25 @@ > } > } > >+static int verify(struct passwd_ctx *ctx, const char *hash) >+{ >+ apr_status_t rv; >+ int ret; >+ >+ if (ctx->passwd == NULL && (ret = get_password(ctx)) != 0) >+ return ret; >+ rv = apr_password_validate(ctx->passwd, hash); >+ if (rv == APR_SUCCESS) >+ return 0; >+ if (APR_STATUS_IS_EMISMATCH(rv)) { >+ ctx->errstr = "password verification failed"; >+ return ERR_PWMISMATCH; >+ } >+ ctx->errstr = apr_psprintf(ctx->pool, "Could not verify password: %pm", >+ &rv); >+ return ERR_GENERAL; >+} >+ > /* > * Let's do it. We end up doing a lot of file opening and closing, > * but what do we care? This application isn't run constantly. >@@ -253,7 +274,6 @@ > int main(int argc, const char * const argv[]) > { > apr_file_t *fpw = NULL; >- const char *errstr = NULL; > char line[MAX_STRING_LEN]; > char *pwfilename = NULL; > char *user = NULL; >@@ -262,7 +282,7 @@ > char *scratch, cp[MAX_STRING_LEN]; > int found = 0; > int i; >- int mask = 0; >+ unsigned mask = 0; > apr_pool_t *pool; > int existing_file = 0; > struct passwd_ctx ctx = { 0 }; >@@ -274,6 +294,7 @@ > apr_app_initialize(&argc, &argv, NULL); > atexit(terminate); > apr_pool_create(&pool, NULL); >+ apr_pool_abort_set(abort_on_oom, pool); > apr_file_open_stderr(&errfile, pool); > ctx.pool = pool; > ctx.alg = ALG_APMD5; >@@ -341,10 +362,10 @@ > * Any error message text is returned in the record buffer, since > * the mkrecord() routine doesn't have access to argv[]. > */ >- if (!(mask & APHTP_DELUSER)) { >+ if ((mask & (APHTP_DELUSER|APHTP_VERIFY)) == 0) { > i = mkrecord(&ctx, user); > if (i != 0) { >- apr_file_printf(errfile, "%s: %s" NL, argv[0], errstr); >+ apr_file_printf(errfile, "%s: %s" NL, argv[0], ctx.errstr); > exit(i); > } > if (mask & APHTP_NOFILE) { >@@ -353,21 +374,23 @@ > } > } > >- /* >- * We can access the files the right way, and we have a record >- * to add or update. Let's do it.. >- */ >- if (apr_temp_dir_get((const char**)&dirname, pool) != APR_SUCCESS) { >- apr_file_printf(errfile, "%s: could not determine temp dir" NL, >- argv[0]); >- exit(ERR_FILEPERM); >- } >- dirname = apr_psprintf(pool, "%s/%s", dirname, tn); >+ if ((mask & APHTP_VERIFY) == 0) { >+ /* >+ * We can access the files the right way, and we have a record >+ * to add or update. Let's do it.. >+ */ >+ if (apr_temp_dir_get((const char**)&dirname, pool) != APR_SUCCESS) { >+ apr_file_printf(errfile, "%s: could not determine temp dir" NL, >+ argv[0]); >+ exit(ERR_FILEPERM); >+ } >+ dirname = apr_psprintf(pool, "%s/%s", dirname, tn); > >- if (apr_file_mktemp(&ftemp, dirname, 0, pool) != APR_SUCCESS) { >- apr_file_printf(errfile, "%s: unable to create temporary file %s" NL, >- argv[0], dirname); >- exit(ERR_FILEPERM); >+ if (apr_file_mktemp(&ftemp, dirname, 0, pool) != APR_SUCCESS) { >+ apr_file_printf(errfile, "%s: unable to create temporary file %s" NL, >+ argv[0], dirname); >+ exit(ERR_FILEPERM); >+ } > } > > /* >@@ -418,33 +441,59 @@ > continue; > } > else { >- if (!(mask & APHTP_DELUSER)) { >- /* We found the user we were looking for. >- * Add him to the file. >- */ >+ /* We found the user we were looking for */ >+ found++; >+ if ((mask & APHTP_DELUSER)) { >+ /* Delete entry from the file */ >+ apr_file_printf(errfile, "Deleting "); >+ } >+ else if ((mask & APHTP_VERIFY)) { >+ /* Verify */ >+ char *hash = colon + 1; >+ size_t len; >+ >+ len = strcspn(hash, "\r\n"); >+ if (len == 0) { >+ apr_file_printf(errfile, "Empty hash for user %s" NL, >+ user); >+ exit(ERR_INVALID); >+ } >+ hash[len] = '\0'; >+ >+ i = verify(&ctx, hash); >+ if (i != 0) { >+ apr_file_printf(errfile, "%s" NL, ctx.errstr); >+ exit(i); >+ } >+ } >+ else { >+ /* Update entry */ > apr_file_printf(errfile, "Updating "); > putline(ftemp, ctx.out); >- found++; > } >- else { >- /* We found the user we were looking for. >- * Delete them from the file. >- */ >- apr_file_printf(errfile, "Deleting "); >- found++; >- } > } > } > apr_file_close(fpw); > } >- if (!found && !(mask & APHTP_DELUSER)) { >- apr_file_printf(errfile, "Adding "); >- putline(ftemp, ctx.out); >+ if (!found) { >+ if (mask & APHTP_DELUSER) { >+ apr_file_printf(errfile, "User %s not found" NL, user); >+ exit(0); >+ } >+ else if (mask & APHTP_VERIFY) { >+ apr_file_printf(errfile, "User %s not found" NL, user); >+ exit(ERR_BADUSER); >+ } >+ else { >+ apr_file_printf(errfile, "Adding "); >+ putline(ftemp, ctx.out); >+ } > } >- else if (!found && (mask & APHTP_DELUSER)) { >- apr_file_printf(errfile, "User %s not found" NL, user); >+ if (mask & APHTP_VERIFY) { >+ apr_file_printf(errfile, "Password for user %s correct." NL, user); > exit(0); > } >+ > apr_file_printf(errfile, "password for user %s" NL, user); > > /* The temporary file has all the data, just copy it to the new location.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 468306
:
351406
| 351408