summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2018-02-16 14:56:15 +0000
committerYann Ylavic <ylavic@apache.org>2018-02-16 14:56:15 +0000
commit48a8c0a962a64d6283e8163d0d72323f405d6d51 (patch)
tree99b7c00d9c311011008ada8ba9993503058b692d
parentd0859a04de81f4c6c74ba6993acbdebaa1101751 (diff)
parent7301e2d3762adffad70753bea09e6227351eed59 (diff)
downloadhttpd-48a8c0a962a64d6283e8163d0d72323f405d6d51.tar.gz
Follow up to r1821624: sync with 2.4.x.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x-mpm_fdqueue@1824502 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES22
-rw-r--r--STATUS89
-rw-r--r--include/ap_mmn.h5
-rw-r--r--include/ap_regex.h22
-rw-r--r--modules/aaa/mod_auth_digest.c241
-rw-r--r--modules/aaa/mod_authnz_ldap.c10
-rw-r--r--modules/cache/mod_cache_socache.c3
-rw-r--r--modules/proxy/proxy_util.c6
-rw-r--r--modules/session/mod_session.c13
-rw-r--r--server/core.c58
-rw-r--r--server/protocol.c76
-rw-r--r--server/util_pcre.c35
12 files changed, 311 insertions, 269 deletions
diff --git a/CHANGES b/CHANGES
index 938c1d5d5c..52abf87f27 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,28 @@ Changes with Apache 2.4.30
*) mpm_queue: Put fdqueue code in common for MPMs event and worker.
[Yann Ylavic]
+ *) mod_session: Strip Session header when SessionEnv is on. [Yann Ylavic]
+
+ *) mod_cache_socache: Fix caching of empty headers up to carriage return.
+ [Yann Ylavic]
+
+ *) core: For consistency, ensure that read lines are NUL terminated on any
+ error, not only on buffer full. [Yann Ylavic]
+
+ *) mod_authnz_ldap: Fix language long names detection as short name.
+ [Yann Ylavic]
+
+ *) mod_proxy: Worker schemes and hostnames which are too large are no
+ longer fatal errors; it is logged and the truncated values are stored.
+ [Jim Jagielski]
+
+ *) regex: Allow to configure global/default options for regexes, like
+ caseless matching or extended format. [Yann Ylavic]
+
+ *) mod_auth_digest: Actually use the secret when generating nonces. This change
+ may cause problems if used with round robin load balancers. PR 54637
+ [Stefan Fritsch]
+
*) mod_proxy: Allow setting options to globally defined balancer from
ProxyPass used in VirtualHost. Balancers are now merged using the new
merge_balancers method which merges the balancers options. [Jan Kaluza]
diff --git a/STATUS b/STATUS
index fdbe6baa1f..ea410dca93 100644
--- a/STATUS
+++ b/STATUS
@@ -118,48 +118,71 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
-
-PATCHES PROPOSED TO BACKPORT FROM TRUNK:
- [ New proposals should be added at the end of the list ]
-
- *) proxy_util: Schemes and hostnames that are "too long" are
- no longer automatically fatal errors but are instead logged
- and truncated, at which point the admin can determine if that
- is OK or not.
- trunk patch: http://svn.apache.org/r1823482
- 2.4.x patch: trunk works
- +1: jim, minfrin
-
*) mod_proxy: Provide an RFC1035 compliant version of the hostname in the
proxy_worker_shared structure. PR62085
trunk patch: http://svn.apache.org/r1824176
- 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/proxy-rfc1035-hostname.diff
- +1: minfrin, jim,
+ +1: minfrin, jim, ylavic
jailletc36: is message 010118 still needed? Or at least mitigated with
something like: "for third party proxy module usage only"?
Also, does it require a ap_mmn.h update?
+ minfrin: message 010118 toned down, MMN bump updated, clash with r1823482 resolved, s/APLOG_NOTICE/APLOG_INFO/
+ http://svn.apache.org/r1824460
+ http://svn.apache.org/r1824482
+ 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/proxy-rfc1035-hostname-v3.diff
- *) core: For consistency, ensure that read lines are NUL terminated on any
- error, not only on buffer full.
- trunk patch: http://svn.apache.org/r1824303
- 2.4.x patch: trunk works (modulo CHANGES)
- +1: ylavic
-
- *) mod_authnz_ldap: Fix language long names detection as short name.
- trunk patch: http://svn.apache.org/r1824336
- 2.4.x patch: trunk works (modulo CHANGES)
- +1: ylavic
- *) regex: Allow to configure global/default options for regexes, like
- caseless matching or extended format.
- trunk patch: http://svn.apache.org/r1824339
- 2.4.x patch: http://home.apache.org/~ylavic/patches/httpd-2.4.x-global_regex_options.patch
- +1: ylavic
+PATCHES PROPOSED TO BACKPORT FROM TRUNK:
+ [ New proposals should be added at the end of the list ]
- *) mod_cache_socache: Fix caching of empty headers up to carriage return.
- trunk patch: http://svn.apache.org/r1824343
- 2.4.x patch: trunk works (modulo CHANGES)
- +1: ylavic
+ *) mpm_queue: Put fdqueue code in common for MPMs event and worker.
+ trunk patch: http://svn.apache.org/r1821624
+ http://svn.apache.org/r1821625
+ http://svn.apache.org/r1821626
+ http://svn.apache.org/r1821627
+ http://svn.apache.org/r1821629
+ http://svn.apache.org/r1821632
+ http://svn.apache.org/r1821635
+ http://svn.apache.org/r1821639
+ http://svn.apache.org/r1821644
+ http://svn.apache.org/r1821647
+ http://svn.apache.org/r1821648
+ http://svn.apache.org/r1821649
+ http://svn.apache.org/r1821650
+ http://svn.apache.org/r1821651
+ http://svn.apache.org/r1821659
+ http://svn.apache.org/r1821660
+ http://svn.apache.org/r1822366
+ http://svn.apache.org/r1822367
+ http://svn.apache.org/r1824381
+ 2.4.x patch: svn merge ^/httpd/httpd/branches/2.4.x-mpm_fdqueue .
+ (http://home.apache.org/~ylavic/patches/httpd-2.4.x-mpm_fdqueue.patch)
+ +1: ylavic, minfrin (with mmn bump for mpm_fdqueue.h)
+ ylavic: The branch merge helps resolve move conflicts since event and
+ worker fdqueue.[ch] differ(ed) between 2.4.x and trunk. The patch
+ is provided only to help review.
+
+ *) mpm_event: Do lingering close in worker(s).
+ trunk patch: http://svn.apache.org/r1823047
+ http://svn.apache.org/r1824454
+ http://svn.apache.org/r1824463
+ http://svn.apache.org/r1824464
+ http://svn.apache.org/r1824497
+ 2.4.x patch: http://home.apache.org/~ylavic/patches/httpd-2.4.x-event-lingering_close_in_worker.patch
+ (trunk works if mpm_queue above is merged first, otherwise
+ the mpm_queue branch can also be synchronized after this
+ merge, YMMV :)
+ +1: ylavic,
+
+ *) mod_ssl: Introduce SSLPolicy/SSLPolicyDefine directives.
+ trunk patch: http://svn.apache.org/r1805182
+ http://svn.apache.org/r1805186
+ http://svn.apache.org/r1808335
+ http://svn.apache.org/r1811475
+ http://svn.apache.org/r1817381
+ http://svn.apache.org/r1817894
+ 2.4.x patch: https://svn.apache.org/repos/asf/httpd/httpd/patches/2.4.x/mod_ssl_policy.diff
+ +1: icing, minfrin
+ minfrin: 2.4.x patch not applying for me, trunk patches work
PATCHES/ISSUES THAT ARE BEING WORKED
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 70b9c621bc..af3a8a5590 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -507,6 +507,9 @@
* semantics
* 20120211.73 (2.4.30-dev) Add failontimeout_set, growth_set and lbmethod_set
* to proxy_balancer struct
+ * 20120211.74 (2.4.30-dev) Add AP_REG_DOLLAR_ENDONLY, ap_regcomp_get_default_cflags
+ * ap_regcomp_set_default_cflags and
+ * ap_regcomp_default_cflag_by_name
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -514,7 +517,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 73 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 74 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/include/ap_regex.h b/include/ap_regex.h
index be41226bee..ec6908cdc9 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 */
+
#define AP_REG_MATCH "MATCH_" /** suggested prefix for ap_regname */
/* Error values: */
@@ -103,6 +105,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
* @param regex The regular expression string
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
index e99cb3b3f1..a8f2cc52aa 100644
--- a/modules/aaa/mod_auth_digest.c
+++ b/modules/aaa/mod_auth_digest.c
@@ -26,20 +26,13 @@
* reports to the Apache bug-database, or send them directly to me
* at ronald@innovation.ch.
*
- * Requires either /dev/random (or equivalent) or the truerand library,
- * available for instance from
- * ftp://research.att.com/dist/mab/librand.shar
- *
* Open Issues:
* - qop=auth-int (when streams and trailer support available)
* - nonce-format configurability
* - Proxy-Authorization-Info header is set by this module, but is
* currently ignored by mod_proxy (needs patch to mod_proxy)
- * - generating the secret takes a while (~ 8 seconds) if using the
- * truerand library
* - The source of the secret should be run-time directive (with server
- * scope: RSRC_CONF). However, that could be tricky when trying to
- * choose truerand vs. file...
+ * scope: RSRC_CONF)
* - shared-mem not completely tested yet. Seems to work ok for me,
* but... (definitely won't work on Windoze)
* - Sharing a realm among multiple servers has following problems:
@@ -52,6 +45,8 @@
* captures a packet sent to one server and sends it to another
* one. Should we add "AuthDigestNcCheck Strict"?
* - expired nonces give amaya fits.
+ * - MD5-sess and auth-int are not yet implemented. An incomplete
+ * implementation has been removed and can be retrieved from svn history.
*/
#include "apr_sha1.h"
@@ -94,7 +89,6 @@ typedef struct digest_config_struct {
apr_array_header_t *qop_list;
apr_sha1_ctx_t nonce_ctx;
apr_time_t nonce_lifetime;
- const char *nonce_format;
int check_nc;
const char *algorithm;
char *uri_list;
@@ -112,7 +106,8 @@ typedef struct digest_config_struct {
#define NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE)
#define NONCE_LEN (int )(NONCE_TIME_LEN + NONCE_HASH_LEN)
-#define SECRET_LEN 20
+#define SECRET_LEN 20
+#define RETAINED_DATA_ID "mod_auth_digest"
/* client list definitions */
@@ -121,7 +116,6 @@ typedef struct hash_entry {
unsigned long key; /* the key for this entry */
struct hash_entry *next; /* next entry in the bucket */
unsigned long nonce_count; /* for nonce-count checking */
- char ha1[2*APR_MD5_DIGESTSIZE+1]; /* for algorithm=MD5-sess */
char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */
} client_entry;
@@ -170,7 +164,7 @@ typedef union time_union {
unsigned char arr[sizeof(apr_time_t)];
} time_rec;
-static unsigned char secret[SECRET_LEN];
+static unsigned char *secret;
/* client-list, opaque, and one-time-nonce stuff */
@@ -228,35 +222,11 @@ static apr_status_t cleanup_tables(void *not_used)
return APR_SUCCESS;
}
-static apr_status_t initialize_secret(server_rec *s)
-{
- apr_status_t status;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01757)
- "generating secret for digest authentication ...");
-
-#if APR_HAS_RANDOM
- status = apr_generate_random_bytes(secret, sizeof(secret));
-#else
-#error APR random number support is missing; you probably need to install the truerand library.
-#endif
-
- if (status != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, status, s, APLOGNO(01758)
- "error generating secret");
- return status;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01759) "done");
-
- return APR_SUCCESS;
-}
-
static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
{
ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01760)
- "%s - all nonce-count checking, one-time nonces, and "
- "MD5-sess algorithm disabled", msg);
+ "%s - all nonce-count checking and one-time nonces"
+ "disabled", msg);
cleanup_tables(NULL);
}
@@ -386,16 +356,32 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx)
static int pre_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
{
apr_status_t rv;
+ void *retained;
rv = ap_mutex_register(pconf, client_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
- if (rv == APR_SUCCESS) {
- rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT,
- 0);
- }
- if (rv != APR_SUCCESS) {
- return rv;
- }
+ if (rv != APR_SUCCESS)
+ return !OK;
+ rv = ap_mutex_register(pconf, opaque_mutex_type, NULL, APR_LOCK_DEFAULT, 0);
+ if (rv != APR_SUCCESS)
+ return !OK;
+ retained = ap_retained_data_get(RETAINED_DATA_ID);
+ if (retained == NULL) {
+ retained = ap_retained_data_create(RETAINED_DATA_ID, SECRET_LEN);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01757)
+ "generating secret for digest authentication");
+#if APR_HAS_RANDOM
+ rv = apr_generate_random_bytes(retained, SECRET_LEN);
+#else
+#error APR random number support is missing
+#endif
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(01758)
+ "error generating secret");
+ return !OK;
+ }
+ }
+ secret = retained;
return OK;
}
@@ -408,10 +394,6 @@ static int initialize_module(apr_pool_t *p, apr_pool_t *plog,
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
return OK;
- if (initialize_secret(s) != APR_SUCCESS) {
- return !OK;
- }
-
#if APR_HAS_SHARED_MEMORY
/* Note: this stuff is currently fixed for the lifetime of the server,
* i.e. even across restarts. This means that A) any shmem-size
@@ -492,6 +474,16 @@ static void *create_digest_dir_config(apr_pool_t *p, char *dir)
static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
{
digest_config_rec *conf = (digest_config_rec *) config;
+#ifdef AP_DEBUG
+ int i;
+
+ /* check that we got random numbers */
+ for (i = 0; i < SECRET_LEN; i++) {
+ if (secret[i] != 0)
+ break;
+ }
+ ap_assert(i < SECRET_LEN);
+#endif
/* The core already handles the realm, but it's just too convenient to
* grab it ourselves too and cache some setups. However, we need to
@@ -505,7 +497,7 @@ static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
* and directives outside a virtual host section)
*/
apr_sha1_init(&conf->nonce_ctx);
- apr_sha1_update_binary(&conf->nonce_ctx, secret, sizeof(secret));
+ apr_sha1_update_binary(&conf->nonce_ctx, secret, SECRET_LEN);
apr_sha1_update_binary(&conf->nonce_ctx, (const unsigned char *) realm,
strlen(realm));
@@ -599,8 +591,7 @@ static const char *set_nonce_lifetime(cmd_parms *cmd, void *config,
static const char *set_nonce_format(cmd_parms *cmd, void *config,
const char *fmt)
{
- ((digest_config_rec *) config)->nonce_format = fmt;
- return "AuthDigestNonceFormat is not implemented (yet)";
+ return "AuthDigestNonceFormat is not implemented";
}
static const char *set_nc_check(cmd_parms *cmd, void *config, int flag)
@@ -621,7 +612,7 @@ static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg)
{
if (!strcasecmp(alg, "MD5-sess")) {
return "AuthDigestAlgorithm: ERROR: algorithm `MD5-sess' "
- "is not fully implemented";
+ "is not implemented";
}
else if (strcasecmp(alg, "MD5")) {
return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL);
@@ -1147,7 +1138,7 @@ static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque,
static client_entry *gen_client(const request_rec *r)
{
unsigned long op;
- client_entry new_entry = { 0, NULL, 0, "", "" }, *entry;
+ client_entry new_entry = { 0, NULL, 0, "" }, *entry;
if (!opaque_cntr) {
return NULL;
@@ -1168,92 +1159,6 @@ static client_entry *gen_client(const request_rec *r)
/*
- * MD5-sess code.
- *
- * If you want to use algorithm=MD5-sess you must write get_userpw_hash()
- * yourself (see below). The dummy provided here just uses the hash from
- * the auth-file, i.e. it is only useful for testing client implementations
- * of MD5-sess .
- */
-
-/*
- * get_userpw_hash() will be called each time a new session needs to be
- * generated and is expected to return the equivalent of
- *
- * h_urp = ap_md5(r->pool,
- * apr_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd))
- * ap_md5(r->pool,
- * (unsigned char *) apr_pstrcat(r->pool, h_urp, ":", resp->nonce, ":",
- * resp->cnonce, NULL));
- *
- * or put differently, it must return
- *
- * MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce)
- *
- * If something goes wrong, the failure must be logged and NULL returned.
- *
- * You must implement this yourself, which will probably consist of code
- * contacting the password server with the necessary information (typically
- * the username, realm, nonce, and cnonce) and receiving the hash from it.
- *
- * TBD: This function should probably be in a separate source file so that
- * people need not modify mod_auth_digest.c each time they install a new
- * version of apache.
- */
-static const char *get_userpw_hash(const request_rec *r,
- const digest_header_rec *resp,
- const digest_config_rec *conf)
-{
- return ap_md5(r->pool,
- (unsigned char *) apr_pstrcat(r->pool, conf->ha1, ":", resp->nonce,
- ":", resp->cnonce, NULL));
-}
-
-
-/* Retrieve current session H(A1). If there is none and "generate" is
- * true then a new session for MD5-sess is generated and stored in the
- * client struct; if generate is false, or a new session could not be
- * generated then NULL is returned (in case of failure to generate the
- * failure reason will have been logged already).
- */
-static const char *get_session_HA1(const request_rec *r,
- digest_header_rec *resp,
- const digest_config_rec *conf,
- int generate)
-{
- const char *ha1 = NULL;
-
- /* return the current sessions if there is one */
- if (resp->opaque && resp->client && resp->client->ha1[0]) {
- return resp->client->ha1;
- }
- else if (!generate) {
- return NULL;
- }
-
- /* generate a new session */
- if (!resp->client) {
- resp->client = gen_client(r);
- }
- if (resp->client) {
- ha1 = get_userpw_hash(r, resp, conf);
- if (ha1) {
- memcpy(resp->client->ha1, ha1, sizeof(resp->client->ha1));
- }
- }
-
- return ha1;
-}
-
-
-static void clear_session(const digest_header_rec *resp)
-{
- if (resp->client) {
- resp->client->ha1[0] = '\0';
- }
-}
-
-/*
* Authorization challenge generation code (for WWW-Authenticate)
*/
@@ -1291,8 +1196,7 @@ static void note_digest_auth_failure(request_rec *r,
if (resp->opaque == NULL) {
/* new client */
- if ((conf->check_nc || conf->nonce_lifetime == 0
- || !strcasecmp(conf->algorithm, "MD5-sess"))
+ if ((conf->check_nc || conf->nonce_lifetime == 0)
&& (resp->client = gen_client(r)) != NULL) {
opaque = ltox(r->pool, resp->client->key);
}
@@ -1332,15 +1236,6 @@ static void note_digest_auth_failure(request_rec *r,
memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
}
- /* Setup MD5-sess stuff. Note that we just clear out the session
- * info here, since we can't generate a new session until the request
- * from the client comes in with the cnonce.
- */
-
- if (!strcasecmp(conf->algorithm, "MD5-sess")) {
- clear_session(resp);
- }
-
/* setup domain attribute. We want to send this attribute wherever
* possible so that the client won't send the Authorization header
* unnecessarily (it's usually > 200 bytes!).
@@ -1606,24 +1501,9 @@ static const char *new_digest(const request_rec *r,
{
const char *ha1, *ha2, *a2;
- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
- ha1 = get_session_HA1(r, resp, conf, 1);
- if (!ha1) {
- return NULL;
- }
- }
- else {
- ha1 = conf->ha1;
- }
+ ha1 = conf->ha1;
- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) {
- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, ":",
- ap_md5(r->pool, (const unsigned char*) ""), NULL);
- /* TBD */
- }
- else {
- a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
- }
+ a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL);
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
return ap_md5(r->pool,
@@ -1871,8 +1751,7 @@ static int authenticate_digest_user(request_rec *r)
}
if (resp->algorithm != NULL
- && strcasecmp(resp->algorithm, "MD5")
- && strcasecmp(resp->algorithm, "MD5-sess")) {
+ && strcasecmp(resp->algorithm, "MD5")) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01789)
"unknown algorithm `%s' received: %s",
resp->algorithm, r->uri);
@@ -2024,27 +1903,9 @@ static int add_auth_info(request_rec *r)
/* calculate rspauth attribute
*/
- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
- ha1 = get_session_HA1(r, resp, conf, 0);
- if (!ha1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01795)
- "internal error: couldn't find session "
- "info for user %s", resp->username);
- return !OK;
- }
- }
- else {
- ha1 = conf->ha1;
- }
+ ha1 = conf->ha1;
- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) {
- a2 = apr_pstrcat(r->pool, ":", resp->uri, ":",
- ap_md5(r->pool,(const unsigned char *) ""), NULL);
- /* TBD */
- }
- else {
- a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
- }
+ a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
ha2 = ap_md5(r->pool, (const unsigned char *)a2);
resp_dig = ap_md5(r->pool,
diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c
index 8cee7d47b1..98c48a8609 100644
--- a/modules/aaa/mod_authnz_ldap.c
+++ b/modules/aaa/mod_authnz_ldap.c
@@ -126,9 +126,13 @@ static char* derive_codepage_from_lang (apr_pool_t *p, char *language)
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) {
diff --git a/modules/cache/mod_cache_socache.c b/modules/cache/mod_cache_socache.c
index 11e950285d..0d76760c5b 100644
--- a/modules/cache/mod_cache_socache.c
+++ b/modules/cache/mod_cache_socache.c
@@ -213,7 +213,8 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r,
"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
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 7b4cb09e08..11cbe9187a 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1691,10 +1691,12 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
"Alert! worker name (%s) too long; truncated to: %s", ptr, wshared->name);
}
if (PROXY_STRNCPY(wshared->scheme, uri.scheme) != APR_SUCCESS) {
- return apr_psprintf(p, "worker scheme (%s) too long", uri.scheme);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(010117)
+ "Alert! worker scheme (%s) too long; truncated to: %s", uri.scheme, wshared->scheme);
}
if (PROXY_STRNCPY(wshared->hostname, uri.hostname) != APR_SUCCESS) {
- return apr_psprintf(p, "worker hostname (%s) too long", uri.hostname);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(010118)
+ "Alert! worker hostname (%s) too long; truncated to: %s", uri.hostname, wshared->hostname);
}
wshared->flush_packets = flush_off;
wshared->flush_wait = PROXY_FLUSH_WAIT;
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
index ff4c9a6f2d..d517020d99 100644
--- a/modules/session/mod_session.c
+++ b/modules/session/mod_session.c
@@ -510,12 +510,15 @@ static int session_fixups(request_rec * r)
*/
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;
diff --git a/server/core.c b/server/core.c
index b52e9b258a..4af08166f6 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 */
@@ -2847,6 +2848,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)
{
@@ -4421,6 +4474,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"),
@@ -4856,6 +4912,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/protocol.c b/server/protocol.c
index a89e2feb24..6994633297 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -225,6 +225,11 @@ 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 */
+ 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
@@ -238,14 +243,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);
@@ -263,7 +269,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) {
@@ -276,17 +282,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? */
@@ -294,7 +291,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 */
@@ -305,7 +302,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);
@@ -329,19 +326,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.
@@ -361,7 +354,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)) {
@@ -378,7 +371,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.
@@ -395,10 +388,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;
@@ -411,7 +402,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;
}
@@ -420,7 +410,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) {
@@ -434,7 +424,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;
}
@@ -447,8 +437,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;
@@ -487,6 +490,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);
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 4d2adef25b..4e707a8b28 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -111,6 +111,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 (ap_cstr_casecmp(name, "ICASE") == 0) {
+ cflag = AP_REG_ICASE;
+ }
+ else if (ap_cstr_casecmp(name, "DOTALL") == 0) {
+ cflag = AP_REG_DOTALL;
+ }
+ else if (ap_cstr_casecmp(name, "DOLLAR_ENDONLY") == 0) {
+ cflag = AP_REG_DOLLAR_ENDONLY;
+ }
+ else if (ap_cstr_casecmp(name, "EXTENDED") == 0) {
+ cflag = AP_REG_EXTENDED;
+ }
+
+ return cflag;
+}
+
/*
* Arguments:
* preg points to a structure for recording the compiled expression
@@ -127,12 +159,15 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags)
int errcode = 0;
int options = PCRE_DUPNAMES;
+ 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);