webbuilder_pel7ppc64lebuilder0
2 years ago
16 changed files with 1376 additions and 3 deletions
@ -0,0 +1,19 @@ |
|||||||
|
--- a/modules/aaa/mod_authnz_ldap.c 2018/02/15 17:33:04 1824335 |
||||||
|
+++ b/modules/aaa/mod_authnz_ldap.c 2018/02/15 17:42:14 1824336 |
||||||
|
@@ -126,9 +126,13 @@ |
||||||
|
|
||||||
|
charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING); |
||||||
|
|
||||||
|
- if (!charset) { |
||||||
|
- language[2] = '\0'; |
||||||
|
- charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING); |
||||||
|
+ /* |
||||||
|
+ * Test if language values like 'en-US' return a match from the charset |
||||||
|
+ * conversion map when shortened to 'en'. |
||||||
|
+ */ |
||||||
|
+ if (!charset && strlen(language) > 3 && language[2] == '-') { |
||||||
|
+ char *language_short = apr_pstrndup(p, language, 2); |
||||||
|
+ charset = (char*) apr_hash_get(charset_conversions, language_short, APR_HASH_KEY_STRING); |
||||||
|
} |
||||||
|
|
||||||
|
if (charset) { |
@ -0,0 +1,190 @@ |
|||||||
|
diff --git a/include/ap_regex.h b/include/ap_regex.h |
||||||
|
index 5122154..349ae83 100644 |
||||||
|
--- a/include/ap_regex.h |
||||||
|
+++ b/include/ap_regex.h |
||||||
|
@@ -77,6 +77,8 @@ extern "C" { |
||||||
|
#define AP_REG_NOMEM 0x20 /* nomem in our code */ |
||||||
|
#define AP_REG_DOTALL 0x40 /* perl's /s flag */ |
||||||
|
|
||||||
|
+#define AP_REG_DOLLAR_ENDONLY 0x200 /**< '$' matches at end of subject string only */ |
||||||
|
+ |
||||||
|
/* Error values: */ |
||||||
|
enum { |
||||||
|
AP_REG_ASSERT = 1, /** internal error ? */ |
||||||
|
@@ -100,6 +102,26 @@ typedef struct { |
||||||
|
|
||||||
|
/* The functions */ |
||||||
|
|
||||||
|
+/** |
||||||
|
+ * Get default compile flags |
||||||
|
+ * @return Bitwise OR of AP_REG_* flags |
||||||
|
+ */ |
||||||
|
+AP_DECLARE(int) ap_regcomp_get_default_cflags(void); |
||||||
|
+ |
||||||
|
+/** |
||||||
|
+ * Set default compile flags |
||||||
|
+ * @param cflags Bitwise OR of AP_REG_* flags |
||||||
|
+ */ |
||||||
|
+AP_DECLARE(void) ap_regcomp_set_default_cflags(int cflags); |
||||||
|
+ |
||||||
|
+/** |
||||||
|
+ * Get the AP_REG_* corresponding to the string. |
||||||
|
+ * @param name The name (i.e. AP_REG_<name>) |
||||||
|
+ * @return The AP_REG_*, or zero if the string is unknown |
||||||
|
+ * |
||||||
|
+ */ |
||||||
|
+AP_DECLARE(int) ap_regcomp_default_cflag_by_name(const char *name); |
||||||
|
+ |
||||||
|
/** |
||||||
|
* Compile a regular expression. |
||||||
|
* @param preg Returned compiled regex |
||||||
|
diff --git a/server/core.c b/server/core.c |
||||||
|
index b3240a0..e073ddf 100644 |
||||||
|
--- a/server/core.c |
||||||
|
+++ b/server/core.c |
||||||
|
@@ -48,6 +48,7 @@ |
||||||
|
#include "mod_core.h" |
||||||
|
#include "mod_proxy.h" |
||||||
|
#include "ap_listen.h" |
||||||
|
+#include "ap_regex.h" |
||||||
|
|
||||||
|
#include "mod_so.h" /* for ap_find_loaded_module_symbol */ |
||||||
|
|
||||||
|
@@ -2646,6 +2647,58 @@ static const char *virtualhost_section(cmd_parms *cmd, void *dummy, |
||||||
|
return errmsg; |
||||||
|
} |
||||||
|
|
||||||
|
+static const char *set_regex_default_options(cmd_parms *cmd, |
||||||
|
+ void *dummy, |
||||||
|
+ const char *arg) |
||||||
|
+{ |
||||||
|
+ const command_rec *thiscmd = cmd->cmd; |
||||||
|
+ int cflags, cflag; |
||||||
|
+ |
||||||
|
+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); |
||||||
|
+ if (err != NULL) { |
||||||
|
+ return err; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ cflags = ap_regcomp_get_default_cflags(); |
||||||
|
+ while (*arg) { |
||||||
|
+ const char *name = ap_getword_conf(cmd->pool, &arg); |
||||||
|
+ int how = 0; |
||||||
|
+ |
||||||
|
+ if (strcasecmp(name, "none") == 0) { |
||||||
|
+ cflags = 0; |
||||||
|
+ continue; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ if (*name == '+') { |
||||||
|
+ name++; |
||||||
|
+ how = +1; |
||||||
|
+ } |
||||||
|
+ else if (*name == '-') { |
||||||
|
+ name++; |
||||||
|
+ how = -1; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ cflag = ap_regcomp_default_cflag_by_name(name); |
||||||
|
+ if (!cflag) { |
||||||
|
+ return apr_psprintf(cmd->pool, "%s: option '%s' unknown", |
||||||
|
+ thiscmd->name, name); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ if (how > 0) { |
||||||
|
+ cflags |= cflag; |
||||||
|
+ } |
||||||
|
+ else if (how < 0) { |
||||||
|
+ cflags &= ~cflag; |
||||||
|
+ } |
||||||
|
+ else { |
||||||
|
+ cflags = cflag; |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
+ ap_regcomp_set_default_cflags(cflags); |
||||||
|
+ |
||||||
|
+ return NULL; |
||||||
|
+} |
||||||
|
+ |
||||||
|
static const char *set_server_alias(cmd_parms *cmd, void *dummy, |
||||||
|
const char *arg) |
||||||
|
{ |
||||||
|
@@ -4164,6 +4217,9 @@ AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL, |
||||||
|
OR_ALL, "soft/hard limits for max number of processes per uid"), |
||||||
|
#endif |
||||||
|
|
||||||
|
+AP_INIT_RAW_ARGS("RegexDefaultOptions", set_regex_default_options, NULL, RSRC_CONF, |
||||||
|
+ "default options for regexes (prefixed by '+' to add, '-' to del)"), |
||||||
|
+ |
||||||
|
/* internal recursion stopper */ |
||||||
|
AP_INIT_TAKE12("LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF, |
||||||
|
"maximum recursion depth of internal redirects and subrequests"), |
||||||
|
@@ -4569,6 +4625,8 @@ static int core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptem |
||||||
|
apr_pool_cleanup_register(pconf, NULL, reset_config_defines, |
||||||
|
apr_pool_cleanup_null); |
||||||
|
|
||||||
|
+ ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY); |
||||||
|
+ |
||||||
|
mpm_common_pre_config(pconf); |
||||||
|
|
||||||
|
return OK; |
||||||
|
diff --git a/server/util_pcre.c b/server/util_pcre.c |
||||||
|
index 1e83cad..d7df400 100644 |
||||||
|
--- a/server/util_pcre.c |
||||||
|
+++ b/server/util_pcre.c |
||||||
|
@@ -110,6 +110,38 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg) |
||||||
|
* Compile a regular expression * |
||||||
|
*************************************************/ |
||||||
|
|
||||||
|
+static int default_cflags = AP_REG_DOLLAR_ENDONLY; |
||||||
|
+ |
||||||
|
+AP_DECLARE(int) ap_regcomp_get_default_cflags(void) |
||||||
|
+{ |
||||||
|
+ return default_cflags; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+AP_DECLARE(void) ap_regcomp_set_default_cflags(int cflags) |
||||||
|
+{ |
||||||
|
+ default_cflags = cflags; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+AP_DECLARE(int) ap_regcomp_default_cflag_by_name(const char *name) |
||||||
|
+{ |
||||||
|
+ int cflag = 0; |
||||||
|
+ |
||||||
|
+ if (strcasecmp(name, "ICASE") == 0) { |
||||||
|
+ cflag = AP_REG_ICASE; |
||||||
|
+ } |
||||||
|
+ else if (strcasecmp(name, "DOTALL") == 0) { |
||||||
|
+ cflag = AP_REG_DOTALL; |
||||||
|
+ } |
||||||
|
+ else if (strcasecmp(name, "DOLLAR_ENDONLY") == 0) { |
||||||
|
+ cflag = AP_REG_DOLLAR_ENDONLY; |
||||||
|
+ } |
||||||
|
+ else if (strcasecmp(name, "EXTENDED") == 0) { |
||||||
|
+ cflag = AP_REG_EXTENDED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ return cflag; |
||||||
|
+} |
||||||
|
+ |
||||||
|
/* |
||||||
|
* Arguments: |
||||||
|
* preg points to a structure for recording the compiled expression |
||||||
|
@@ -126,12 +158,16 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags) |
||||||
|
int errcode = 0; |
||||||
|
int options = 0; |
||||||
|
|
||||||
|
+ cflags |= default_cflags; |
||||||
|
if ((cflags & AP_REG_ICASE) != 0) |
||||||
|
options |= PCRE_CASELESS; |
||||||
|
if ((cflags & AP_REG_NEWLINE) != 0) |
||||||
|
options |= PCRE_MULTILINE; |
||||||
|
if ((cflags & AP_REG_DOTALL) != 0) |
||||||
|
options |= PCRE_DOTALL; |
||||||
|
+ if ((cflags & AP_REG_DOLLAR_ENDONLY) != 0) |
||||||
|
+ options |= PCRE_DOLLAR_ENDONLY; |
||||||
|
+ |
||||||
|
|
||||||
|
preg->re_pcre = |
||||||
|
pcre_compile2(pattern, options, &errcode, &errorptr, &erroffset, NULL); |
@ -0,0 +1,23 @@ |
|||||||
|
--- a/modules/session/mod_session.c 2018/02/16 13:39:47 1824476 |
||||||
|
+++ b/modules/session/mod_session.c 2018/02/16 13:41:31 1824477 |
||||||
|
@@ -510,12 +510,15 @@ |
||||||
|
*/ |
||||||
|
ap_session_load(r, &z); |
||||||
|
|
||||||
|
- if (z && conf->env) { |
||||||
|
- session_identity_encode(r, z); |
||||||
|
- if (z->encoded) { |
||||||
|
- apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded); |
||||||
|
- z->encoded = NULL; |
||||||
|
+ if (conf->env) { |
||||||
|
+ if (z) { |
||||||
|
+ session_identity_encode(r, z); |
||||||
|
+ if (z->encoded) { |
||||||
|
+ apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded); |
||||||
|
+ z->encoded = NULL; |
||||||
|
+ } |
||||||
|
} |
||||||
|
+ apr_table_unset(r->headers_in, "Session"); |
||||||
|
} |
||||||
|
|
||||||
|
return OK; |
@ -0,0 +1,198 @@ |
|||||||
|
diff --git a/server/protocol.c b/server/protocol.c |
||||||
|
index 9e23325..8428129 100644 |
||||||
|
--- a/server/protocol.c |
||||||
|
+++ b/server/protocol.c |
||||||
|
@@ -222,6 +222,12 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
int fold = flags & AP_GETLINE_FOLD; |
||||||
|
int crlf = flags & AP_GETLINE_CRLF; |
||||||
|
|
||||||
|
+ if (!n) { |
||||||
|
+ /* Needs room for NUL byte at least */ |
||||||
|
+ *read = 0; |
||||||
|
+ return APR_BADARG; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* |
||||||
|
* Initialize last_char as otherwise a random value will be compared |
||||||
|
* against APR_ASCII_LF at the end of the loop if bb only contains |
||||||
|
@@ -235,14 +241,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE, |
||||||
|
APR_BLOCK_READ, 0); |
||||||
|
if (rv != APR_SUCCESS) { |
||||||
|
- return rv; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
/* Something horribly wrong happened. Someone didn't block! |
||||||
|
* (this also happens at the end of each keepalive connection) |
||||||
|
*/ |
||||||
|
if (APR_BRIGADE_EMPTY(bb)) { |
||||||
|
- return APR_EGENERAL; |
||||||
|
+ rv = APR_EGENERAL; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
for (e = APR_BRIGADE_FIRST(bb); |
||||||
|
@@ -260,7 +267,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
|
||||||
|
rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ); |
||||||
|
if (rv != APR_SUCCESS) { |
||||||
|
- return rv; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
if (len == 0) { |
||||||
|
@@ -273,17 +280,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
|
||||||
|
/* Would this overrun our buffer? If so, we'll die. */ |
||||||
|
if (n < bytes_handled + len) { |
||||||
|
- *read = bytes_handled; |
||||||
|
- if (*s) { |
||||||
|
- /* ensure this string is NUL terminated */ |
||||||
|
- if (bytes_handled > 0) { |
||||||
|
- (*s)[bytes_handled-1] = '\0'; |
||||||
|
- } |
||||||
|
- else { |
||||||
|
- (*s)[0] = '\0'; |
||||||
|
- } |
||||||
|
- } |
||||||
|
- return APR_ENOSPC; |
||||||
|
+ rv = APR_ENOSPC; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
/* Do we have to handle the allocation ourselves? */ |
||||||
|
@@ -291,7 +289,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
/* We'll assume the common case where one bucket is enough. */ |
||||||
|
if (!*s) { |
||||||
|
current_alloc = len; |
||||||
|
- *s = apr_palloc(r->pool, current_alloc); |
||||||
|
+ *s = apr_palloc(r->pool, current_alloc + 1); |
||||||
|
} |
||||||
|
else if (bytes_handled + len > current_alloc) { |
||||||
|
/* Increase the buffer size */ |
||||||
|
@@ -302,7 +300,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
new_size = (bytes_handled + len) * 2; |
||||||
|
} |
||||||
|
|
||||||
|
- new_buffer = apr_palloc(r->pool, new_size); |
||||||
|
+ new_buffer = apr_palloc(r->pool, new_size + 1); |
||||||
|
|
||||||
|
/* Copy what we already had. */ |
||||||
|
memcpy(new_buffer, *s, bytes_handled); |
||||||
|
@@ -326,19 +324,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- if (crlf && (last_char <= *s || last_char[-1] != APR_ASCII_CR)) { |
||||||
|
- *last_char = '\0'; |
||||||
|
- bytes_handled = last_char - *s; |
||||||
|
- *read = bytes_handled; |
||||||
|
- return APR_EINVAL; |
||||||
|
- } |
||||||
|
- |
||||||
|
- /* Now NUL-terminate the string at the end of the line; |
||||||
|
+ /* Now terminate the string at the end of the line; |
||||||
|
* if the last-but-one character is a CR, terminate there */ |
||||||
|
if (last_char > *s && last_char[-1] == APR_ASCII_CR) { |
||||||
|
last_char--; |
||||||
|
} |
||||||
|
- *last_char = '\0'; |
||||||
|
+ else if (crlf) { |
||||||
|
+ rv = APR_EINVAL; |
||||||
|
+ goto cleanup; |
||||||
|
+ } |
||||||
|
bytes_handled = last_char - *s; |
||||||
|
|
||||||
|
/* If we're folding, we have more work to do. |
||||||
|
@@ -358,7 +352,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE, |
||||||
|
APR_BLOCK_READ, 1); |
||||||
|
if (rv != APR_SUCCESS) { |
||||||
|
- return rv; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
if (APR_BRIGADE_EMPTY(bb)) { |
||||||
|
@@ -375,7 +369,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ); |
||||||
|
if (rv != APR_SUCCESS) { |
||||||
|
apr_brigade_cleanup(bb); |
||||||
|
- return rv; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
/* Found one, so call ourselves again to get the next line. |
||||||
|
@@ -392,10 +386,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) { |
||||||
|
/* Do we have enough space? We may be full now. */ |
||||||
|
if (bytes_handled >= n) { |
||||||
|
- *read = n; |
||||||
|
- /* ensure this string is terminated */ |
||||||
|
- (*s)[n-1] = '\0'; |
||||||
|
- return APR_ENOSPC; |
||||||
|
+ rv = APR_ENOSPC; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
else { |
||||||
|
apr_size_t next_size, next_len; |
||||||
|
@@ -408,7 +400,6 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
tmp = NULL; |
||||||
|
} |
||||||
|
else { |
||||||
|
- /* We're null terminated. */ |
||||||
|
tmp = last_char; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -417,7 +408,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
rv = ap_rgetline_core(&tmp, next_size, |
||||||
|
&next_len, r, 0, bb); |
||||||
|
if (rv != APR_SUCCESS) { |
||||||
|
- return rv; |
||||||
|
+ goto cleanup; |
||||||
|
} |
||||||
|
|
||||||
|
if (do_alloc && next_len > 0) { |
||||||
|
@@ -431,7 +422,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
memcpy(new_buffer, *s, bytes_handled); |
||||||
|
|
||||||
|
/* copy the new line, including the trailing null */ |
||||||
|
- memcpy(new_buffer + bytes_handled, tmp, next_len + 1); |
||||||
|
+ memcpy(new_buffer + bytes_handled, tmp, next_len); |
||||||
|
*s = new_buffer; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -444,8 +435,21 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
+ |
||||||
|
+cleanup: |
||||||
|
+ if (bytes_handled >= n) { |
||||||
|
+ bytes_handled = n - 1; |
||||||
|
+ } |
||||||
|
+ if (*s) { |
||||||
|
+ /* ensure the string is NUL terminated */ |
||||||
|
+ (*s)[bytes_handled] = '\0'; |
||||||
|
+ } |
||||||
|
*read = bytes_handled; |
||||||
|
|
||||||
|
+ if (rv != APR_SUCCESS) { |
||||||
|
+ return rv; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* PR#43039: We shouldn't accept NULL bytes within the line */ |
||||||
|
if (strlen(*s) < bytes_handled) { |
||||||
|
return APR_EINVAL; |
||||||
|
@@ -484,6 +488,11 @@ AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int flags) |
||||||
|
apr_size_t len; |
||||||
|
apr_bucket_brigade *tmp_bb; |
||||||
|
|
||||||
|
+ if (n < 1) { |
||||||
|
+ /* Can't work since we always NUL terminate */ |
||||||
|
+ return -1; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); |
||||||
|
rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb); |
||||||
|
apr_brigade_destroy(tmp_bb); |
@ -0,0 +1,12 @@ |
|||||||
|
--- a/modules/cache/mod_cache_socache.c 2018/02/16 13:32:48 1824474 |
||||||
|
+++ b/modules/cache/mod_cache_socache.c 2018/02/16 13:34:35 1824475 |
||||||
|
@@ -213,7 +213,8 @@ |
||||||
|
"Premature end of cache headers."); |
||||||
|
return APR_EGENERAL; |
||||||
|
} |
||||||
|
- while (apr_isspace(buffer[colon])) { |
||||||
|
+ /* Do not go past the \r from above as apr_isspace('\r') is true */ |
||||||
|
+ while (apr_isspace(buffer[colon]) && (colon < *slider)) { |
||||||
|
colon++; |
||||||
|
} |
||||||
|
apr_table_addn(table, apr_pstrndup(r->pool, (const char *) buffer |
@ -0,0 +1,46 @@ |
|||||||
|
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c |
||||||
|
index 7213eb3..3e73c7a 100644 |
||||||
|
--- a/modules/session/mod_session.c |
||||||
|
+++ b/modules/session/mod_session.c |
||||||
|
@@ -126,15 +126,9 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z) |
||||||
|
|
||||||
|
/* found a session that hasn't expired? */ |
||||||
|
now = apr_time_now(); |
||||||
|
- if (!zz || (zz->expiry && zz->expiry < now)) { |
||||||
|
- |
||||||
|
- /* no luck, create a blank session */ |
||||||
|
- zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec)); |
||||||
|
- zz->pool = r->pool; |
||||||
|
- zz->entries = apr_table_make(zz->pool, 10); |
||||||
|
- |
||||||
|
- } |
||||||
|
- else { |
||||||
|
+ |
||||||
|
+ if (zz){ |
||||||
|
+ /* load the session attibutes */ |
||||||
|
rv = ap_run_session_decode(r, zz); |
||||||
|
if (OK != rv) { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817) |
||||||
|
@@ -142,8 +136,22 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z) |
||||||
|
"session not loaded: %s", r->uri); |
||||||
|
return rv; |
||||||
|
} |
||||||
|
+ |
||||||
|
+ /* invalidate session if session is expired */ |
||||||
|
+ if (zz && zz->expiry && zz->expiry < now){ |
||||||
|
+ zz = NULL; |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
+ if (!zz || (zz->expiry && zz->expiry < now)) { |
||||||
|
+ |
||||||
|
+ /* no luck, create a blank session */ |
||||||
|
+ zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec)); |
||||||
|
+ zz->pool = r->pool; |
||||||
|
+ zz->entries = apr_table_make(zz->pool, 10); |
||||||
|
+ |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* make sure the expiry is set, if present */ |
||||||
|
if (!zz->expiry && dconf->maxage) { |
||||||
|
zz->expiry = now + dconf->maxage * APR_USEC_PER_SEC; |
@ -0,0 +1,91 @@ |
|||||||
|
diff --git a/include/ap_regex.h b/include/ap_regex.h |
||||||
|
index 349ae83..952e77a 100644 |
||||||
|
--- a/include/ap_regex.h |
||||||
|
+++ b/include/ap_regex.h |
||||||
|
@@ -79,6 +79,12 @@ extern "C" { |
||||||
|
|
||||||
|
#define AP_REG_DOLLAR_ENDONLY 0x200 /**< '$' matches at end of subject string only */ |
||||||
|
|
||||||
|
+#define AP_REG_NO_DEFAULT 0x400 /**< Don't implicitely add AP_REG_DEFAULT options */ |
||||||
|
+ |
||||||
|
+#define AP_REG_MATCH "MATCH_" /**< suggested prefix for ap_regname */ |
||||||
|
+ |
||||||
|
+#define AP_REG_DEFAULT (AP_REG_DOTALL|AP_REG_DOLLAR_ENDONLY) |
||||||
|
+ |
||||||
|
/* Error values: */ |
||||||
|
enum { |
||||||
|
AP_REG_ASSERT = 1, /** internal error ? */ |
||||||
|
diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c |
||||||
|
index 15cd8ee..69af111 100644 |
||||||
|
--- a/modules/filters/mod_substitute.c |
||||||
|
+++ b/modules/filters/mod_substitute.c |
||||||
|
@@ -599,8 +599,10 @@ static const char *set_pattern(cmd_parms *cmd, void *cfg, const char *line) |
||||||
|
|
||||||
|
/* first see if we can compile the regex */ |
||||||
|
if (!is_pattern) { |
||||||
|
- r = ap_pregcomp(cmd->pool, from, AP_REG_EXTENDED | |
||||||
|
- (ignore_case ? AP_REG_ICASE : 0)); |
||||||
|
+ int flags = AP_REG_NO_DEFAULT |
||||||
|
+ | (ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY) |
||||||
|
+ | (ignore_case ? AP_REG_ICASE : 0); |
||||||
|
+ r = ap_pregcomp(cmd->pool, from, flags); |
||||||
|
if (!r) |
||||||
|
return "Substitute could not compile regex"; |
||||||
|
} |
||||||
|
diff --git a/server/core.c b/server/core.c |
||||||
|
index d4af287..6ae0f5f 100644 |
||||||
|
--- a/server/core.c |
||||||
|
+++ b/server/core.c |
||||||
|
@@ -4625,7 +4625,7 @@ static int core_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptem |
||||||
|
apr_pool_cleanup_register(pconf, NULL, reset_config_defines, |
||||||
|
apr_pool_cleanup_null); |
||||||
|
|
||||||
|
- ap_regcomp_set_default_cflags(AP_REG_DOLLAR_ENDONLY); |
||||||
|
+ ap_regcomp_set_default_cflags(AP_REG_DEFAULT); |
||||||
|
|
||||||
|
mpm_common_pre_config(pconf); |
||||||
|
|
||||||
|
diff --git a/server/util_pcre.c b/server/util_pcre.c |
||||||
|
index d7df400..f778c75 100644 |
||||||
|
--- a/server/util_pcre.c |
||||||
|
+++ b/server/util_pcre.c |
||||||
|
@@ -110,7 +110,7 @@ AP_DECLARE(void) ap_regfree(ap_regex_t *preg) |
||||||
|
* Compile a regular expression * |
||||||
|
*************************************************/ |
||||||
|
|
||||||
|
-static int default_cflags = AP_REG_DOLLAR_ENDONLY; |
||||||
|
+static int default_cflags = AP_REG_DEFAULT; |
||||||
|
|
||||||
|
AP_DECLARE(int) ap_regcomp_get_default_cflags(void) |
||||||
|
{ |
||||||
|
@@ -158,7 +158,8 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags) |
||||||
|
int errcode = 0; |
||||||
|
int options = 0; |
||||||
|
|
||||||
|
- cflags |= default_cflags; |
||||||
|
+ if ((cflags & AP_REG_NO_DEFAULT) == 0) |
||||||
|
+ cflags |= default_cflags; |
||||||
|
if ((cflags & AP_REG_ICASE) != 0) |
||||||
|
options |= PCRE_CASELESS; |
||||||
|
if ((cflags & AP_REG_NEWLINE) != 0) |
||||||
|
diff --git a/server/util_regex.c b/server/util_regex.c |
||||||
|
index 73eccec..5038b99 100644 |
||||||
|
--- a/server/util_regex.c |
||||||
|
+++ b/server/util_regex.c |
||||||
|
@@ -93,6 +93,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool, |
||||||
|
} |
||||||
|
|
||||||
|
/* anything after the current delimiter is flags */ |
||||||
|
+ ret->flags = ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY; |
||||||
|
while (*++endp) { |
||||||
|
switch (*endp) { |
||||||
|
case 'i': ret->flags |= AP_REG_ICASE; break; |
||||||
|
@@ -105,7 +106,7 @@ AP_DECLARE(ap_rxplus_t*) ap_rxplus_compile(apr_pool_t *pool, |
||||||
|
default: break; /* we should probably be stricter here */ |
||||||
|
} |
||||||
|
} |
||||||
|
- if (ap_regcomp(&ret->rx, rxstr, ret->flags) == 0) { |
||||||
|
+ if (ap_regcomp(&ret->rx, rxstr, AP_REG_NO_DEFAULT | ret->flags) == 0) { |
||||||
|
apr_pool_cleanup_register(pool, &ret->rx, rxplus_cleanup, |
||||||
|
apr_pool_cleanup_null); |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c |
||||||
|
index 680be8b..10382df 100644 |
||||||
|
--- a/modules/proxy/mod_proxy_ftp.c |
||||||
|
+++ b/modules/proxy/mod_proxy_ftp.c |
||||||
|
@@ -218,7 +218,7 @@ static int ftp_check_string(const char *x) |
||||||
|
* (EBCDIC) machines either. |
||||||
|
*/ |
||||||
|
static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb, |
||||||
|
- char *buff, apr_size_t bufflen, int *eos) |
||||||
|
+ char *buff, apr_size_t bufflen, int *eos, apr_size_t *outlen) |
||||||
|
{ |
||||||
|
apr_bucket *e; |
||||||
|
apr_status_t rv; |
||||||
|
@@ -230,6 +230,7 @@ static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb, |
||||||
|
/* start with an empty string */ |
||||||
|
buff[0] = 0; |
||||||
|
*eos = 0; |
||||||
|
+ *outlen = 0; |
||||||
|
|
||||||
|
/* loop through each brigade */ |
||||||
|
while (!found) { |
||||||
|
@@ -273,6 +274,7 @@ static apr_status_t ftp_string_read(conn_rec *c, apr_bucket_brigade *bb, |
||||||
|
if (len > 0) { |
||||||
|
memcpy(pos, response, len); |
||||||
|
pos += len; |
||||||
|
+ *outlen += len; |
||||||
|
} |
||||||
|
} |
||||||
|
APR_BUCKET_REMOVE(e); |
||||||
|
@@ -386,28 +388,37 @@ static int ftp_getrc_msg(conn_rec *ftp_ctrl, apr_bucket_brigade *bb, char *msgbu |
||||||
|
char buff[5]; |
||||||
|
char *mb = msgbuf, *me = &msgbuf[msglen]; |
||||||
|
apr_status_t rv; |
||||||
|
+ apr_size_t nread; |
||||||
|
+ |
||||||
|
int eos; |
||||||
|
|
||||||
|
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) { |
||||||
|
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
/* |
||||||
|
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, |
||||||
|
"<%s", response); |
||||||
|
*/ |
||||||
|
+ if (nread < 4) { |
||||||
|
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(10229) "Malformed FTP response '%s'", response); |
||||||
|
+ *mb = '\0'; |
||||||
|
+ return -1; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ |
||||||
|
if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) || |
||||||
|
- !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-')) |
||||||
|
+ !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-')) |
||||||
|
status = 0; |
||||||
|
else |
||||||
|
status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0'; |
||||||
|
|
||||||
|
mb = apr_cpystrn(mb, response + 4, me - mb); |
||||||
|
|
||||||
|
- if (response[3] == '-') { |
||||||
|
+ if (response[3] == '-') { /* multi-line reply "123-foo\nbar\n123 baz" */ |
||||||
|
memcpy(buff, response, 3); |
||||||
|
buff[3] = ' '; |
||||||
|
do { |
||||||
|
- if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) { |
||||||
|
+ if (APR_SUCCESS != (rv = ftp_string_read(ftp_ctrl, bb, response, sizeof(response), &eos, &nread))) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb); |
@ -0,0 +1,19 @@ |
|||||||
|
--- a/modules/mappers/mod_alias.c 2014/03/30 18:15:25 1583174 |
||||||
|
+++ b/modules/mappers/mod_alias.c 2014/03/30 18:20:09 1583175 |
||||||
|
@@ -371,15 +371,11 @@ |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
- int pathlen = strlen(found) - |
||||||
|
- (strlen(r->uri + regm[0].rm_eo)); |
||||||
|
- AP_DEBUG_ASSERT(pathlen >= 0); |
||||||
|
- AP_DEBUG_ASSERT(pathlen <= strlen(found)); |
||||||
|
ap_set_context_info(r, |
||||||
|
apr_pstrmemdup(r->pool, r->uri, |
||||||
|
regm[0].rm_eo), |
||||||
|
apr_pstrmemdup(r->pool, found, |
||||||
|
- pathlen)); |
||||||
|
+ strlen(found))); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
@ -0,0 +1,285 @@ |
|||||||
|
# ./pullrev.sh 1861793 1862611 1862612 |
||||||
|
http://svn.apache.org/viewvc?view=revision&revision=1861793 |
||||||
|
http://svn.apache.org/viewvc?view=revision&revision=1862611 |
||||||
|
http://svn.apache.org/viewvc?view=revision&revision=1862612 |
||||||
|
http://svn.apache.org/viewvc?view=revision&revision=1862724 |
||||||
|
|
||||||
|
--- httpd-2.4.6/configure.in.r1861793+ |
||||||
|
+++ httpd-2.4.6/configure.in |
||||||
|
@@ -464,6 +464,28 @@ |
||||||
|
AC_SEARCH_LIBS(crypt, crypt) |
||||||
|
CRYPT_LIBS="$LIBS" |
||||||
|
APACHE_SUBST(CRYPT_LIBS) |
||||||
|
+ |
||||||
|
+if test "$ac_cv_search_crypt" != "no"; then |
||||||
|
+ # Test crypt() with the SHA-512 test vector from https://akkadia.org/drepper/SHA-crypt.txt |
||||||
|
+ AC_CACHE_CHECK([whether crypt() supports SHA-2], [ap_cv_crypt_sha2], [ |
||||||
|
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([[ |
||||||
|
+#include <crypt.h> |
||||||
|
+#include <stdlib.h> |
||||||
|
+#include <string.h> |
||||||
|
+ |
||||||
|
+#define PASSWD_0 "Hello world!" |
||||||
|
+#define SALT_0 "\$6\$saltstring" |
||||||
|
+#define EXPECT_0 "\$6\$saltstring\$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu" \ |
||||||
|
+ "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1" |
||||||
|
+]], [char *result = crypt(PASSWD_0, SALT_0); |
||||||
|
+ if (!result) return 1; |
||||||
|
+ if (strcmp(result, EXPECT_0)) return 2; |
||||||
|
+])], [ap_cv_crypt_sha2=yes], [ap_cv_crypt_sha2=no])]) |
||||||
|
+ if test "$ap_cv_crypt_sha2" = yes; then |
||||||
|
+ AC_DEFINE([HAVE_CRYPT_SHA2], 1, [Define if crypt() supports SHA-2 hashes]) |
||||||
|
+ fi |
||||||
|
+fi |
||||||
|
+ |
||||||
|
LIBS="$saved_LIBS" |
||||||
|
|
||||||
|
dnl See Comment #Spoon |
||||||
|
--- httpd-2.4.6/docs/man/htpasswd.1.r1861793+ |
||||||
|
+++ httpd-2.4.6/docs/man/htpasswd.1 |
||||||
|
@@ -27,16 +27,16 @@ |
||||||
|
.SH "SYNOPSIS" |
||||||
|
|
||||||
|
.PP |
||||||
|
-\fBhtpasswd\fR [ -\fBc\fR ] [ -\fBi\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBC\fR \fIcost\fR ] [ -\fBD\fR ] [ -\fBv\fR ] \fIpasswdfile\fR \fIusername\fR |
||||||
|
+\fBhtpasswd\fR [ -\fBc\fR ] [ -\fBi\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBr\fR \fIrounds\fR ] [ -\fBC\fR \fIcost\fR ] [ -\fBD\fR ] [ -\fBv\fR ] \fIpasswdfile\fR \fIusername\fR |
||||||
|
|
||||||
|
.PP |
||||||
|
-\fBhtpasswd\fR -\fBb\fR [ -\fBc\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBC\fR \fIcost\fR ] [ -\fBD\fR ] [ -\fBv\fR ] \fIpasswdfile\fR \fIusername\fR \fIpassword\fR |
||||||
|
+\fBhtpasswd\fR -\fBb\fR [ -\fBc\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBr\fR \fIrounds\fR ] [ -\fBC\fR \fIcost\fR ] [ -\fBD\fR ] [ -\fBv\fR ] \fIpasswdfile\fR \fIusername\fR \fIpassword\fR |
||||||
|
|
||||||
|
.PP |
||||||
|
-\fBhtpasswd\fR -\fBn\fR [ -\fBi\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBC\fR \fIcost\fR ] \fIusername\fR |
||||||
|
+\fBhtpasswd\fR -\fBn\fR [ -\fBi\fR ] [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBr\fR \fIrounds\fR ] [ -\fBC\fR \fIcost\fR ] \fIusername\fR |
||||||
|
|
||||||
|
.PP |
||||||
|
-\fBhtpasswd\fR -\fBnb\fR [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBC\fR \fIcost\fR ] \fIusername\fR \fIpassword\fR |
||||||
|
+\fBhtpasswd\fR -\fBnb\fR [ -\fBm\fR | -\fBB\fR | -\fBd\fR | -\fBs\fR | -\fBp\fR ] [ -\fBr\fR \fIrounds\fR ] [ -\fBC\fR \fIcost\fR ] \fIusername\fR \fIpassword\fR |
||||||
|
|
||||||
|
|
||||||
|
.SH "SUMMARY" |
||||||
|
@@ -48,7 +48,7 @@ |
||||||
|
Resources available from the Apache HTTP server can be restricted to just the users listed in the files created by htpasswd\&. This program can only manage usernames and passwords stored in a flat-file\&. It can encrypt and display password information for use in other types of data stores, though\&. To use a DBM database see dbmmanage or htdbm\&. |
||||||
|
|
||||||
|
.PP |
||||||
|
-htpasswd encrypts passwords using either bcrypt, a version of MD5 modified for Apache, SHA1, or the system's crypt() routine\&. Files managed by htpasswd may contain a mixture of different encoding types of passwords; some user records may have bcrypt or MD5-encrypted passwords while others in the same file may have passwords encrypted with crypt()\&. |
||||||
|
++\fBhtpasswd\fR encrypts passwords using either bcrypt, a version of MD5 modified for Apache, SHA-1, or the system's \fBcrypt()\fR routine\&. SHA-2-based hashes (SHA-256 and SHA-512) are supported for \fBcrypt()\fR\&. Files managed by \fBhtpasswd\fR may contain a mixture of different encoding types of passwords; some user records may have bcrypt or MD5-encrypted passwords while others in the same file may have passwords encrypted with \fBcrypt()\fR\&. |
||||||
|
|
||||||
|
.PP |
||||||
|
This manual page only lists the command line arguments\&. For details of the directives necessary to configure user authentication in httpd see the Apache manual, which is part of the Apache distribution or can be found at http://httpd\&.apache\&.org/\&. |
||||||
|
@@ -73,17 +73,26 @@ |
||||||
|
-m |
||||||
|
Use MD5 encryption for passwords\&. This is the default (since version 2\&.2\&.18)\&. |
||||||
|
.TP |
||||||
|
+-2 |
||||||
|
+Use SHA-256 \fBcrypt()\fR based hashes for passwords\&. This is supported on most Unix platforms\&. |
||||||
|
+.TP |
||||||
|
+-5 |
||||||
|
+Use SHA-512 \fBcrypt()\fR based hashes for passwords\&. This is supported on most Unix platforms\&. |
||||||
|
+.TP |
||||||
|
-B |
||||||
|
Use bcrypt encryption for passwords\&. This is currently considered to be very secure\&. |
||||||
|
.TP |
||||||
|
-C |
||||||
|
This flag is only allowed in combination with -B (bcrypt encryption)\&. It sets the computing time used for the bcrypt algorithm (higher is more secure but slower, default: 5, valid: 4 to 31)\&. |
||||||
|
.TP |
||||||
|
+-r |
||||||
|
+This flag is only allowed in combination with \fB-2\fR or \fB-5\fR\&. It sets the number of hash rounds used for the SHA-2 algorithms (higher is more secure but slower; the default is 5,000)\&. |
||||||
|
+.TP |
||||||
|
-d |
||||||
|
Use crypt() encryption for passwords\&. This is not supported by the httpd server on Windows and Netware\&. This algorithm limits the password length to 8 characters\&. This algorithm is \fBinsecure\fR by today's standards\&. It used to be the default algorithm until version 2\&.2\&.17\&. |
||||||
|
.TP |
||||||
|
-s |
||||||
|
-Use SHA encryption for passwords\&. Facilitates migration from/to Netscape servers using the LDAP Directory Interchange Format (ldif)\&. This algorithm is \fBinsecure\fR by today's standards\&. |
||||||
|
+Use SHA-1 encryption for passwords\&. Facilitates migration from/to Netscape servers using the LDAP Directory Interchange Format (ldif)\&. This algorithm is \fBinsecure\fR by today's standards\&. |
||||||
|
.TP |
||||||
|
-p |
||||||
|
Use plaintext passwords\&. Though htpasswd will support creation on all platforms, the httpd daemon will only accept plain text passwords on Windows and Netware\&. |
||||||
|
@@ -152,11 +161,14 @@ |
||||||
|
When using the crypt() algorithm, note that only the first 8 characters of the password are used to form the password\&. If the supplied password is longer, the extra characters will be silently discarded\&. |
||||||
|
|
||||||
|
.PP |
||||||
|
-The SHA encryption format does not use salting: for a given password, there is only one encrypted representation\&. The crypt() and MD5 formats permute the representation by prepending a random salt string, to make dictionary attacks against the passwords more difficult\&. |
||||||
|
+The SHA-1 encryption format does not use salting: for a given password, there is only one encrypted representation\&. The crypt() and MD5 formats permute the representation by prepending a random salt string, to make dictionary attacks against the passwords more difficult\&. |
||||||
|
|
||||||
|
.PP |
||||||
|
-The SHA and crypt() formats are insecure by today's standards\&. |
||||||
|
- |
||||||
|
+The SHA-1 and crypt() formats are insecure by today's standards\&. |
||||||
|
+ |
||||||
|
+.PP |
||||||
|
+The SHA-2-based \fBcrypt()\fR formats (SHA-256 and SHA-512) are supported on most modern Unix systems, and follow the specification at https://www\&.akkadia\&.org/drepper/SHA-crypt\&.txt\& |
||||||
|
+ |
||||||
|
.SH "RESTRICTIONS" |
||||||
|
|
||||||
|
.PP |
||||||
|
--- httpd-2.4.6/support/htpasswd.c.r1861793+ |
||||||
|
+++ httpd-2.4.6/support/htpasswd.c |
||||||
|
@@ -93,28 +93,32 @@ |
||||||
|
static void usage(void) |
||||||
|
{ |
||||||
|
apr_file_printf(errfile, "Usage:" NL |
||||||
|
- "\thtpasswd [-cimBdpsDv] [-C cost] passwordfile username" NL |
||||||
|
- "\thtpasswd -b[cmBdpsDv] [-C cost] passwordfile username password" NL |
||||||
|
+ "\thtpasswd [-cimB25dpsDv] [-C cost] [-r rounds] passwordfile username" NL |
||||||
|
+ "\thtpasswd -b[cmB25dpsDv] [-C cost] [-r rounds] passwordfile username password" NL |
||||||
|
NL |
||||||
|
- "\thtpasswd -n[imBdps] [-C cost] username" NL |
||||||
|
- "\thtpasswd -nb[mBdps] [-C cost] username password" NL |
||||||
|
+ "\thtpasswd -n[imB25dps] [-C cost] [-r rounds] username" NL |
||||||
|
+ "\thtpasswd -nb[mB25dps] [-C cost] [-r rounds] username password" NL |
||||||
|
" -c Create a new file." NL |
||||||
|
" -n Don't update file; display results on stdout." NL |
||||||
|
" -b Use the password from the command line rather than prompting " |
||||||
|
"for it." 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 |
||||||
|
+ " -2 Force SHA-256 crypt() hash of the password (secure)." NL |
||||||
|
+ " -5 Force SHA-512 crypt() hash of the password (secure)." NL |
||||||
|
+ " -B Force bcrypt aencryption 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 |
||||||
|
+ " -r Set the number of rounds used for the SHA-256, SHA-512 algorithms" NL |
||||||
|
+ " (higher is more secure but slower, default: 5000)." NL |
||||||
|
" -d Force CRYPT encryption of the password (8 chars max, insecure)." NL |
||||||
|
- " -s Force SHA encryption of the password (insecure)." NL |
||||||
|
+ " -s Force SHA-1 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 " |
||||||
|
+ "The SHA-1 algorithm does not use a salt and is less secure than the " |
||||||
|
"MD5 algorithm." NL, |
||||||
|
BCRYPT_DEFAULT_COST |
||||||
|
); |
||||||
|
@@ -173,7 +177,7 @@ |
||||||
|
if (rv != APR_SUCCESS) |
||||||
|
exit(ERR_SYNTAX); |
||||||
|
|
||||||
|
- while ((rv = apr_getopt(state, "cnmspdBbDiC:v", &opt, &opt_arg)) == APR_SUCCESS) { |
||||||
|
+ while ((rv = apr_getopt(state, "cnmspdBbDi25C:r:v", &opt, &opt_arg)) == APR_SUCCESS) { |
||||||
|
switch (opt) { |
||||||
|
case 'c': |
||||||
|
*mask |= APHTP_NEWFILE; |
||||||
|
--- httpd-2.4.6/support/passwd_common.c.r1861793+ |
||||||
|
+++ httpd-2.4.6/support/passwd_common.c |
||||||
|
@@ -185,10 +185,15 @@ |
||||||
|
#if CRYPT_ALGO_SUPPORTED |
||||||
|
char *cbuf; |
||||||
|
#endif |
||||||
|
+#ifdef HAVE_CRYPT_SHA2 |
||||||
|
+ const char *setting; |
||||||
|
+ char method; |
||||||
|
+#endif |
||||||
|
|
||||||
|
- if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT) { |
||||||
|
+ if (ctx->cost != 0 && ctx->alg != ALG_BCRYPT |
||||||
|
+ && ctx->alg != ALG_CRYPT_SHA256 && ctx->alg != ALG_CRYPT_SHA512 ) { |
||||||
|
apr_file_printf(errfile, |
||||||
|
- "Warning: Ignoring -C argument for this algorithm." NL); |
||||||
|
+ "Warning: Ignoring -C/-r argument for this algorithm." NL); |
||||||
|
} |
||||||
|
|
||||||
|
if (ctx->passwd == NULL) { |
||||||
|
@@ -246,6 +251,34 @@ |
||||||
|
break; |
||||||
|
#endif /* CRYPT_ALGO_SUPPORTED */ |
||||||
|
|
||||||
|
+#ifdef HAVE_CRYPT_SHA2 |
||||||
|
+ case ALG_CRYPT_SHA256: |
||||||
|
+ case ALG_CRYPT_SHA512: |
||||||
|
+ ret = generate_salt(salt, 16, &ctx->errstr, ctx->pool); |
||||||
|
+ if (ret != 0) |
||||||
|
+ break; |
||||||
|
+ |
||||||
|
+ method = ctx->alg == ALG_CRYPT_SHA256 ? '5': '6'; |
||||||
|
+ |
||||||
|
+ if (ctx->cost) |
||||||
|
+ setting = apr_psprintf(ctx->pool, "$%c$rounds=%d$%s", |
||||||
|
+ method, ctx->cost, salt); |
||||||
|
+ else |
||||||
|
+ setting = apr_psprintf(ctx->pool, "$%c$%s", |
||||||
|
+ method, salt); |
||||||
|
+ |
||||||
|
+ cbuf = crypt(pw, setting); |
||||||
|
+ if (cbuf == NULL) { |
||||||
|
+ rv = APR_FROM_OS_ERROR(errno); |
||||||
|
+ ctx->errstr = apr_psprintf(ctx->pool, "crypt() failed: %pm", &rv); |
||||||
|
+ ret = ERR_PWMISMATCH; |
||||||
|
+ break; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1); |
||||||
|
+ break; |
||||||
|
+#endif /* HAVE_CRYPT_SHA2 */ |
||||||
|
+ |
||||||
|
#if BCRYPT_ALGO_SUPPORTED |
||||||
|
case ALG_BCRYPT: |
||||||
|
rv = apr_generate_random_bytes((unsigned char*)salt, 16); |
||||||
|
@@ -294,6 +327,19 @@ |
||||||
|
case 's': |
||||||
|
ctx->alg = ALG_APSHA; |
||||||
|
break; |
||||||
|
+#ifdef HAVE_CRYPT_SHA2 |
||||||
|
+ case '2': |
||||||
|
+ ctx->alg = ALG_CRYPT_SHA256; |
||||||
|
+ break; |
||||||
|
+ case '5': |
||||||
|
+ ctx->alg = ALG_CRYPT_SHA512; |
||||||
|
+ break; |
||||||
|
+#else |
||||||
|
+ case '2': |
||||||
|
+ case '5': |
||||||
|
+ ctx->errstr = "SHA-2 crypt() algorithms are not supported on this platform."; |
||||||
|
+ return ERR_ALG_NOT_SUPP; |
||||||
|
+#endif |
||||||
|
case 'p': |
||||||
|
ctx->alg = ALG_PLAIN; |
||||||
|
#if !PLAIN_ALGO_SUPPORTED |
||||||
|
@@ -324,11 +370,12 @@ |
||||||
|
return ERR_ALG_NOT_SUPP; |
||||||
|
#endif |
||||||
|
break; |
||||||
|
- case 'C': { |
||||||
|
+ case 'C': |
||||||
|
+ case 'r': { |
||||||
|
char *endptr; |
||||||
|
long num = strtol(opt_arg, &endptr, 10); |
||||||
|
if (*endptr != '\0' || num <= 0) { |
||||||
|
- ctx->errstr = "argument to -C must be a positive integer"; |
||||||
|
+ ctx->errstr = "argument to -C/-r must be a positive integer"; |
||||||
|
return ERR_SYNTAX; |
||||||
|
} |
||||||
|
ctx->cost = num; |
||||||
|
--- httpd-2.4.6/support/passwd_common.h.r1861793+ |
||||||
|
+++ httpd-2.4.6/support/passwd_common.h |
||||||
|
@@ -28,6 +28,8 @@ |
||||||
|
#include "apu_version.h" |
||||||
|
#endif |
||||||
|
|
||||||
|
+#include "ap_config_auto.h" |
||||||
|
+ |
||||||
|
#define MAX_STRING_LEN 256 |
||||||
|
|
||||||
|
#define ALG_PLAIN 0 |
||||||
|
@@ -35,6 +37,8 @@ |
||||||
|
#define ALG_APMD5 2 |
||||||
|
#define ALG_APSHA 3 |
||||||
|
#define ALG_BCRYPT 4 |
||||||
|
+#define ALG_CRYPT_SHA256 5 |
||||||
|
+#define ALG_CRYPT_SHA512 6 |
||||||
|
|
||||||
|
#define BCRYPT_DEFAULT_COST 5 |
||||||
|
|
||||||
|
@@ -79,7 +83,7 @@ |
||||||
|
apr_size_t out_len; |
||||||
|
char *passwd; |
||||||
|
int alg; |
||||||
|
- int cost; |
||||||
|
+ int cost; /* cost for bcrypt, rounds for SHA-2 */ |
||||||
|
enum { |
||||||
|
PW_PROMPT = 0, |
||||||
|
PW_ARG, |
@ -0,0 +1,22 @@ |
|||||||
|
--- a/docs/conf/magic 2019/07/05 11:22:46 1862603 |
||||||
|
+++ b/docs/conf/magic 2019/07/05 11:26:12 1862604 |
||||||
|
@@ -87,7 +87,7 @@ |
||||||
|
# Microsoft WAVE format (*.wav) |
||||||
|
# [GRR 950115: probably all of the shorts and longs should be leshort/lelong] |
||||||
|
# Microsoft RIFF |
||||||
|
-0 string RIFF audio/unknown |
||||||
|
+0 string RIFF |
||||||
|
# - WAVE format |
||||||
|
>8 string WAVE audio/x-wav |
||||||
|
# MPEG audio. |
||||||
|
--- a/modules/metadata/mod_mime_magic.c 2019/07/05 11:22:46 1862603 |
||||||
|
+++ b/modules/metadata/mod_mime_magic.c 2019/07/05 11:26:12 1862604 |
||||||
|
@@ -606,7 +606,7 @@ |
||||||
|
/* high overhead for 1 char - just hope they don't do this much */ |
||||||
|
str[0] = c; |
||||||
|
str[1] = '\0'; |
||||||
|
- return magic_rsl_add(r, str); |
||||||
|
+ return magic_rsl_add(r, apr_pstrdup(r->pool, str)); |
||||||
|
} |
||||||
|
|
||||||
|
/* allocate and copy a contiguous string from a result string list */ |
@ -0,0 +1,194 @@ |
|||||||
|
diff --git a/docs/manual/mod/mod_session.html.en b/docs/manual/mod/mod_session.html.en |
||||||
|
index 96a61e6..4ecc97d 100644 |
||||||
|
--- a/docs/manual/mod/mod_session.html.en |
||||||
|
+++ b/docs/manual/mod/mod_session.html.en |
||||||
|
@@ -69,6 +69,7 @@ |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessionheader">SessionHeader</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessioninclude">SessionInclude</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessionmaxage">SessionMaxAge</a></li> |
||||||
|
+<li><img alt="" src="../images/down.gif" /> <a href="#sessionexpiryupdateinterval">SessionExpiryUpdateInterval</a></li> |
||||||
|
</ul> |
||||||
|
<h3>Topics</h3> |
||||||
|
<ul id="topics"> |
||||||
|
@@ -494,6 +495,37 @@ AuthName realm |
||||||
|
|
||||||
|
<p>Setting the maxage to zero disables session expiry.</p> |
||||||
|
|
||||||
|
+</div> |
||||||
|
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> |
||||||
|
+<div class="directive-section"><h2><a name="SessionExpiryUpdateInterval" id="sessionexpiryupdateinterval">SessionExpiryUpdateInterval</a> <a name="sessionexpiryupdateinterval" id="sessionexpiryupdateinterval">Directive</a></h2> |
||||||
|
+<table class="directive"> |
||||||
|
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Define the number of seconds a session's expiry may change without the session being updated</td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>SessionExpiryUpdateInterval <var>interval</var></code></td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>SessionExpiryUpdateInterval 0 (always update)</code></td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_session</td></tr> |
||||||
|
+</table> |
||||||
|
+ <p>The <code class="directive">SessionExpiryUpdateInterval</code> directive allows |
||||||
|
+ sessions to avoid the cost associated with writing the session each request |
||||||
|
+ when only the expiry time has changed. This can be used to make a website |
||||||
|
+ more efficient or reduce load on a database when using |
||||||
|
+ <module>mod_session_dbd</module>. The session is always written if the data |
||||||
|
+ stored in the session has changed or the expiry has changed by more than the |
||||||
|
+ configured interval.</p> |
||||||
|
+ |
||||||
|
+ <p>Setting the interval to zero disables this directive, and the session |
||||||
|
+ expiry is refreshed for each request.</p> |
||||||
|
+ |
||||||
|
+ <p>This directive only has an effect when combined with <code class="directive"><a href="../mod/mod_session.html#sessionmaxage">SessionMaxAge</a></code> to enable session |
||||||
|
+ expiry. Sessions without an expiry are only written when the data stored in |
||||||
|
+ the session has changed.</p> |
||||||
|
+ |
||||||
|
+ <div class="warning"><h3>Warning</h3> |
||||||
|
+ <p>Because the session expiry may not be refreshed with each request, it's |
||||||
|
+ possible for sessions to expire up to <var>interval</var> seconds early. |
||||||
|
+ Using a small interval usually provides sufficient savings while having a |
||||||
|
+ minimal effect on expiry resolution.</p></div> |
||||||
|
+ |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="bottomlang"> |
||||||
|
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c |
||||||
|
index 3e73c7a..83bf3fc 100644 |
||||||
|
--- a/modules/session/mod_session.c |
||||||
|
+++ b/modules/session/mod_session.c |
||||||
|
@@ -177,6 +177,7 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z) |
||||||
|
{ |
||||||
|
if (z) { |
||||||
|
apr_time_t now = apr_time_now(); |
||||||
|
+ apr_time_t initialExpiry = z->expiry; |
||||||
|
int rv = 0; |
||||||
|
|
||||||
|
session_dir_conf *dconf = ap_get_module_config(r->per_dir_config, |
||||||
|
@@ -202,6 +203,17 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z) |
||||||
|
z->maxage = dconf->maxage; |
||||||
|
} |
||||||
|
|
||||||
|
+ /* don't save if the only change is the expiry by a small amount */ |
||||||
|
+ if (!z->dirty && dconf->expiry_update_time |
||||||
|
+ && (z->expiry - initialExpiry < dconf->expiry_update_time)) { |
||||||
|
+ return APR_SUCCESS; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ /* also don't save sessions that didn't change at all */ |
||||||
|
+ if (!z->dirty && !z->maxage) { |
||||||
|
+ return APR_SUCCESS; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* encode the session */ |
||||||
|
rv = ap_run_session_encode(r, z); |
||||||
|
if (OK != rv) { |
||||||
|
@@ -544,6 +556,10 @@ static void *merge_session_dir_config(apr_pool_t * p, void *basev, void *addv) |
||||||
|
new->env_set = add->env_set || base->env_set; |
||||||
|
new->includes = apr_array_append(p, base->includes, add->includes); |
||||||
|
new->excludes = apr_array_append(p, base->excludes, add->excludes); |
||||||
|
+ new->expiry_update_time = (add->expiry_update_set == 0) |
||||||
|
+ ? base->expiry_update_time |
||||||
|
+ : add->expiry_update_time; |
||||||
|
+ new->expiry_update_set = add->expiry_update_set || base->expiry_update_set; |
||||||
|
|
||||||
|
return new; |
||||||
|
} |
||||||
|
@@ -613,6 +629,21 @@ static const char *add_session_exclude(cmd_parms * cmd, void *dconf, const char |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
+static const char * |
||||||
|
+ set_session_expiry_update(cmd_parms * parms, void *dconf, const char *arg) |
||||||
|
+{ |
||||||
|
+ session_dir_conf *conf = dconf; |
||||||
|
+ |
||||||
|
+ conf->expiry_update_time = atoi(arg); |
||||||
|
+ if (conf->expiry_update_time < 0) { |
||||||
|
+ return "SessionExpiryUpdateInterval must be positive or nul"; |
||||||
|
+ } |
||||||
|
+ conf->expiry_update_time = apr_time_from_sec(conf->expiry_update_time); |
||||||
|
+ conf->expiry_update_set = 1; |
||||||
|
+ |
||||||
|
+ return NULL; |
||||||
|
+} |
||||||
|
+ |
||||||
|
|
||||||
|
static const command_rec session_cmds[] = |
||||||
|
{ |
||||||
|
@@ -628,6 +659,9 @@ static const command_rec session_cmds[] = |
||||||
|
"URL prefixes to include in the session. Defaults to all URLs"), |
||||||
|
AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, RSRC_CONF|OR_AUTHCFG, |
||||||
|
"URL prefixes to exclude from the session. Defaults to no URLs"), |
||||||
|
+ AP_INIT_TAKE1("SessionExpiryUpdateInterval", set_session_expiry_update, NULL, RSRC_CONF|OR_AUTHCFG, |
||||||
|
+ "time interval for which a session's expiry time may change " |
||||||
|
+ "without having to be rewritten. Zero to disable"), |
||||||
|
{NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
diff --git a/modules/session/mod_session.h b/modules/session/mod_session.h |
||||||
|
index a6dd5e9..bdeb532 100644 |
||||||
|
--- a/modules/session/mod_session.h |
||||||
|
+++ b/modules/session/mod_session.h |
||||||
|
@@ -115,6 +115,9 @@ typedef struct { |
||||||
|
* URLs included if empty */ |
||||||
|
apr_array_header_t *excludes; /* URL prefixes to be excluded. No |
||||||
|
* URLs excluded if empty */ |
||||||
|
+ apr_time_t expiry_update_time; /* seconds the session expiry may change and |
||||||
|
+ * not have to be rewritten */ |
||||||
|
+ int expiry_update_set; |
||||||
|
} session_dir_conf; |
||||||
|
|
||||||
|
/** |
||||||
|
diff --git a/modules/session/mod_session_cookie.c b/modules/session/mod_session_cookie.c |
||||||
|
index 6a02322..4aa75e4 100644 |
||||||
|
--- a/modules/session/mod_session_cookie.c |
||||||
|
+++ b/modules/session/mod_session_cookie.c |
||||||
|
@@ -60,9 +60,6 @@ static apr_status_t session_cookie_save(request_rec * r, session_rec * z) |
||||||
|
session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config, |
||||||
|
&session_cookie_module); |
||||||
|
|
||||||
|
- /* don't cache auth protected pages */ |
||||||
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
||||||
|
- |
||||||
|
/* create RFC2109 compliant cookie */ |
||||||
|
if (conf->name_set) { |
||||||
|
if (z->encoded && z->encoded[0]) { |
||||||
|
@@ -162,6 +159,9 @@ static apr_status_t session_cookie_load(request_rec * r, session_rec ** z) |
||||||
|
/* put the session in the notes so we don't have to parse it again */ |
||||||
|
apr_table_setn(m->notes, note, (char *)zz); |
||||||
|
|
||||||
|
+ /* don't cache auth protected pages */ |
||||||
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
||||||
|
+ |
||||||
|
return OK; |
||||||
|
|
||||||
|
} |
||||||
|
diff --git a/modules/session/mod_session_dbd.c b/modules/session/mod_session_dbd.c |
||||||
|
index cf65e5a..20ef72e 100644 |
||||||
|
--- a/modules/session/mod_session_dbd.c |
||||||
|
+++ b/modules/session/mod_session_dbd.c |
||||||
|
@@ -243,6 +243,9 @@ static apr_status_t session_dbd_load(request_rec * r, session_rec ** z) |
||||||
|
/* put the session in the notes so we don't have to parse it again */ |
||||||
|
apr_table_setn(m->notes, note, (char *)zz); |
||||||
|
|
||||||
|
+ /* don't cache pages with a session */ |
||||||
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
||||||
|
+ |
||||||
|
return OK; |
||||||
|
|
||||||
|
} |
||||||
|
@@ -407,9 +410,6 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z) |
||||||
|
if (conf->name_set || conf->name2_set) { |
||||||
|
char *oldkey = NULL, *newkey = NULL; |
||||||
|
|
||||||
|
- /* don't cache pages with a session */ |
||||||
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
||||||
|
- |
||||||
|
/* if the session is new or changed, make a new session ID */ |
||||||
|
if (z->uuid) { |
||||||
|
oldkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); |
||||||
|
@@ -456,7 +456,7 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z) |
||||||
|
else if (conf->peruser) { |
||||||
|
|
||||||
|
/* don't cache pages with a session */ |
||||||
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
||||||
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
||||||
|
|
||||||
|
if (r->user) { |
||||||
|
ret = dbd_save(r, r->user, r->user, z->encoded, z->expiry); |
@ -0,0 +1,161 @@ |
|||||||
|
diff --git a/include/http_connection.h b/include/http_connection.h |
||||||
|
index 2192507..924ddda 100644 |
||||||
|
--- a/include/http_connection.h |
||||||
|
+++ b/include/http_connection.h |
||||||
|
@@ -47,9 +47,18 @@ extern "C" { |
||||||
|
*/ |
||||||
|
AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, void *csd); |
||||||
|
|
||||||
|
+/** |
||||||
|
+ * Shutdown the connection for writing. |
||||||
|
+ * @param c The connection to shutdown |
||||||
|
+ * @param flush Whether or not to flush pending data before |
||||||
|
+ * @return APR_SUCCESS or the underlying error |
||||||
|
+ */ |
||||||
|
+AP_CORE_DECLARE(apr_status_t) ap_shutdown_conn(conn_rec *c, int flush); |
||||||
|
+ |
||||||
|
/** |
||||||
|
* Flushes all remain data in the client send buffer |
||||||
|
* @param c The connection to flush |
||||||
|
+ * @remark calls ap_shutdown_conn(c, 1) |
||||||
|
*/ |
||||||
|
AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c); |
||||||
|
|
||||||
|
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c |
||||||
|
index 8be833a..6c79a1a 100644 |
||||||
|
--- a/modules/proxy/proxy_util.c |
||||||
|
+++ b/modules/proxy/proxy_util.c |
||||||
|
@@ -2886,6 +2886,33 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
+static apr_status_t connection_shutdown(void *theconn) |
||||||
|
+{ |
||||||
|
+ proxy_conn_rec *conn = (proxy_conn_rec *)theconn; |
||||||
|
+ conn_rec *c = conn->connection; |
||||||
|
+ if (c) { |
||||||
|
+ if (!c->aborted) { |
||||||
|
+ apr_interval_time_t saved_timeout = 0; |
||||||
|
+ apr_socket_timeout_get(conn->sock, &saved_timeout); |
||||||
|
+ if (saved_timeout) { |
||||||
|
+ apr_socket_timeout_set(conn->sock, 0); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ (void)ap_shutdown_conn(c, 0); |
||||||
|
+ c->aborted = 1; |
||||||
|
+ |
||||||
|
+ if (saved_timeout) { |
||||||
|
+ apr_socket_timeout_set(conn->sock, saved_timeout); |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02642) |
||||||
|
+ "proxy: connection shutdown"); |
||||||
|
+ } |
||||||
|
+ return APR_SUCCESS; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+ |
||||||
|
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, |
||||||
|
proxy_conn_rec *conn, |
||||||
|
conn_rec *c, |
||||||
|
@@ -2958,6 +2985,11 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, |
||||||
|
} |
||||||
|
apr_socket_timeout_set(conn->sock, current_timeout); |
||||||
|
|
||||||
|
+ /* Shutdown the connection before closing it (eg. SSL connections |
||||||
|
+ * need to be close-notify-ed). |
||||||
|
+ */ |
||||||
|
+ apr_pool_pre_cleanup_register(conn->scpool, conn, connection_shutdown); |
||||||
|
+ |
||||||
|
return OK; |
||||||
|
} |
||||||
|
|
||||||
|
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c |
||||||
|
index fbd701f..a8778d4 100644 |
||||||
|
--- a/modules/ssl/ssl_util_ssl.c |
||||||
|
+++ b/modules/ssl/ssl_util_ssl.c |
||||||
|
@@ -166,6 +166,7 @@ int SSL_smart_shutdown(SSL *ssl) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
int rc; |
||||||
|
+ int flush; |
||||||
|
|
||||||
|
/* |
||||||
|
* Repeat the calls, because SSL_shutdown internally dispatches through a |
||||||
|
@@ -175,8 +176,20 @@ int SSL_smart_shutdown(SSL *ssl) |
||||||
|
* connection and OpenSSL cannot recognize it. |
||||||
|
*/ |
||||||
|
rc = 0; |
||||||
|
+ flush = !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN); |
||||||
|
for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) { |
||||||
|
- if ((rc = SSL_shutdown(ssl))) |
||||||
|
+ rc = SSL_shutdown(ssl); |
||||||
|
+ if (rc >= 0 && flush && (SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) { |
||||||
|
+ /* Once the close notity is sent through the output filters, |
||||||
|
+ * ensure it is flushed through the socket. |
||||||
|
+ */ |
||||||
|
+ if (BIO_flush(SSL_get_wbio(ssl)) <= 0) { |
||||||
|
+ rc = -1; |
||||||
|
+ break; |
||||||
|
+ } |
||||||
|
+ flush = 0; |
||||||
|
+ } |
||||||
|
+ if (rc != 0) |
||||||
|
break; |
||||||
|
} |
||||||
|
return rc; |
||||||
|
diff --git a/server/connection.c b/server/connection.c |
||||||
|
index 6e4495f..4942c77 100644 |
||||||
|
--- a/server/connection.c |
||||||
|
+++ b/server/connection.c |
||||||
|
@@ -64,22 +64,32 @@ AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),O |
||||||
|
#define MAX_SECS_TO_LINGER 30 |
||||||
|
#endif |
||||||
|
|
||||||
|
-AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) |
||||||
|
+AP_CORE_DECLARE(apr_status_t) ap_shutdown_conn(conn_rec *c, int flush) |
||||||
|
{ |
||||||
|
+ apr_status_t rv; |
||||||
|
apr_bucket_brigade *bb; |
||||||
|
apr_bucket *b; |
||||||
|
|
||||||
|
bb = apr_brigade_create(c->pool, c->bucket_alloc); |
||||||
|
|
||||||
|
- /* FLUSH bucket */ |
||||||
|
- b = apr_bucket_flush_create(c->bucket_alloc); |
||||||
|
- APR_BRIGADE_INSERT_TAIL(bb, b); |
||||||
|
+ if (flush) { |
||||||
|
+ /* FLUSH bucket */ |
||||||
|
+ b = apr_bucket_flush_create(c->bucket_alloc); |
||||||
|
+ APR_BRIGADE_INSERT_TAIL(bb, b); |
||||||
|
+ } |
||||||
|
|
||||||
|
/* End Of Connection bucket */ |
||||||
|
b = ap_bucket_eoc_create(c->bucket_alloc); |
||||||
|
APR_BRIGADE_INSERT_TAIL(bb, b); |
||||||
|
|
||||||
|
- ap_pass_brigade(c->output_filters, bb); |
||||||
|
+ rv = ap_pass_brigade(c->output_filters, bb); |
||||||
|
+ apr_brigade_destroy(bb); |
||||||
|
+ return rv; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) |
||||||
|
+{ |
||||||
|
+ (void)ap_shutdown_conn(c, 1); |
||||||
|
} |
||||||
|
|
||||||
|
/* we now proceed to read from the client until we get EOF, or until |
||||||
|
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c |
||||||
|
index 5852685..defa109 100644 |
||||||
|
--- a/server/mpm/event/event.c |
||||||
|
+++ b/server/mpm/event/event.c |
||||||
|
@@ -841,6 +841,7 @@ static int start_lingering_close_nonblocking(event_conn_state_t *cs) |
||||||
|
apr_socket_t *csd = cs->pfd.desc.s; |
||||||
|
|
||||||
|
if (c->aborted |
||||||
|
+ || ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted |
||||||
|
|| apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { |
||||||
|
apr_socket_close(csd); |
||||||
|
apr_pool_clear(cs->p); |
Loading…
Reference in new issue