webbuilder_pel7ppc64lebuilder0
5 years ago
13 changed files with 1513 additions and 6 deletions
@ -0,0 +1,399 @@ |
|||||||
|
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c |
||||||
|
index cbb4434..b50bcf9 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_NOTICE, 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); |
||||||
|
} |
||||||
|
@@ -377,16 +347,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; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -399,10 +385,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 |
||||||
|
@@ -483,6 +465,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 |
||||||
|
@@ -496,7 +488,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)); |
||||||
|
|
||||||
|
@@ -590,8 +582,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) |
||||||
|
@@ -612,7 +603,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); |
||||||
|
@@ -1138,7 +1129,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; |
||||||
|
@@ -1158,92 +1149,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) |
||||||
|
*/ |
||||||
|
@@ -1282,8 +1187,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); |
||||||
|
} |
||||||
|
@@ -1323,15 +1227,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!). |
||||||
|
@@ -1597,24 +1492,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, |
||||||
|
@@ -1854,8 +1734,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); |
||||||
|
@@ -2007,27 +1886,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, |
@ -0,0 +1,113 @@ |
|||||||
|
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c |
||||||
|
index b50bcf9..5bfec82 100644 |
||||||
|
--- a/modules/aaa/mod_auth_digest.c |
||||||
|
+++ b/modules/aaa/mod_auth_digest.c |
||||||
|
@@ -92,7 +92,6 @@ typedef struct digest_config_struct { |
||||||
|
int check_nc; |
||||||
|
const char *algorithm; |
||||||
|
char *uri_list; |
||||||
|
- const char *ha1; |
||||||
|
} digest_config_rec; |
||||||
|
|
||||||
|
|
||||||
|
@@ -153,6 +152,7 @@ typedef struct digest_header_struct { |
||||||
|
apr_time_t nonce_time; |
||||||
|
enum hdr_sts auth_hdr_sts; |
||||||
|
int needed_auth; |
||||||
|
+ const char *ha1; |
||||||
|
client_entry *client; |
||||||
|
} digest_header_rec; |
||||||
|
|
||||||
|
@@ -1295,7 +1295,7 @@ static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type) |
||||||
|
*/ |
||||||
|
|
||||||
|
static authn_status get_hash(request_rec *r, const char *user, |
||||||
|
- digest_config_rec *conf) |
||||||
|
+ digest_config_rec *conf, const char **rethash) |
||||||
|
{ |
||||||
|
authn_status auth_result; |
||||||
|
char *password; |
||||||
|
@@ -1347,7 +1347,7 @@ static authn_status get_hash(request_rec *r, const char *user, |
||||||
|
} while (current_provider); |
||||||
|
|
||||||
|
if (auth_result == AUTH_USER_FOUND) { |
||||||
|
- conf->ha1 = password; |
||||||
|
+ *rethash = password; |
||||||
|
} |
||||||
|
|
||||||
|
return auth_result; |
||||||
|
@@ -1474,25 +1474,24 @@ static int check_nonce(request_rec *r, digest_header_rec *resp, |
||||||
|
|
||||||
|
/* RFC-2069 */ |
||||||
|
static const char *old_digest(const request_rec *r, |
||||||
|
- const digest_header_rec *resp, const char *ha1) |
||||||
|
+ const digest_header_rec *resp) |
||||||
|
{ |
||||||
|
const char *ha2; |
||||||
|
|
||||||
|
ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":", |
||||||
|
resp->uri, NULL)); |
||||||
|
return ap_md5(r->pool, |
||||||
|
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce, |
||||||
|
- ":", ha2, NULL)); |
||||||
|
+ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":", |
||||||
|
+ resp->nonce, ":", ha2, NULL)); |
||||||
|
} |
||||||
|
|
||||||
|
/* RFC-2617 */ |
||||||
|
static const char *new_digest(const request_rec *r, |
||||||
|
- digest_header_rec *resp, |
||||||
|
- const digest_config_rec *conf) |
||||||
|
+ digest_header_rec *resp) |
||||||
|
{ |
||||||
|
const char *ha1, *ha2, *a2; |
||||||
|
|
||||||
|
- ha1 = conf->ha1; |
||||||
|
+ ha1 = resp->ha1; |
||||||
|
|
||||||
|
a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); |
||||||
|
ha2 = ap_md5(r->pool, (const unsigned char *)a2); |
||||||
|
@@ -1505,7 +1504,6 @@ static const char *new_digest(const request_rec *r, |
||||||
|
NULL)); |
||||||
|
} |
||||||
|
|
||||||
|
- |
||||||
|
static void copy_uri_components(apr_uri_t *dst, |
||||||
|
apr_uri_t *src, request_rec *r) { |
||||||
|
if (src->scheme && src->scheme[0] != '\0') { |
||||||
|
@@ -1742,7 +1740,7 @@ static int authenticate_digest_user(request_rec *r) |
||||||
|
return HTTP_UNAUTHORIZED; |
||||||
|
} |
||||||
|
|
||||||
|
- return_code = get_hash(r, r->user, conf); |
||||||
|
+ return_code = get_hash(r, r->user, conf, &resp->ha1); |
||||||
|
|
||||||
|
if (return_code == AUTH_USER_NOT_FOUND) { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790) |
||||||
|
@@ -1772,7 +1770,7 @@ static int authenticate_digest_user(request_rec *r) |
||||||
|
|
||||||
|
if (resp->message_qop == NULL) { |
||||||
|
/* old (rfc-2069) style digest */ |
||||||
|
- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) { |
||||||
|
+ if (strcmp(resp->digest, old_digest(r, resp))) { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792) |
||||||
|
"user %s: password mismatch: %s", r->user, |
||||||
|
r->uri); |
||||||
|
@@ -1802,7 +1800,7 @@ static int authenticate_digest_user(request_rec *r) |
||||||
|
return HTTP_UNAUTHORIZED; |
||||||
|
} |
||||||
|
|
||||||
|
- exp_digest = new_digest(r, resp, conf); |
||||||
|
+ exp_digest = new_digest(r, resp); |
||||||
|
if (!exp_digest) { |
||||||
|
/* we failed to allocate a client struct */ |
||||||
|
return HTTP_INTERNAL_SERVER_ERROR; |
||||||
|
@@ -1886,7 +1884,7 @@ static int add_auth_info(request_rec *r) |
||||||
|
|
||||||
|
/* calculate rspauth attribute |
||||||
|
*/ |
||||||
|
- ha1 = conf->ha1; |
||||||
|
+ ha1 = resp->ha1; |
||||||
|
|
||||||
|
a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); |
||||||
|
ha2 = ap_md5(r->pool, (const unsigned char *)a2); |
@ -0,0 +1,244 @@ |
|||||||
|
diff --git a/docs/manual/mod/core.html.en b/docs/manual/mod/core.html.en |
||||||
|
index 86d9bee..e08034b 100644 |
||||||
|
--- a/docs/manual/mod/core.html.en |
||||||
|
+++ b/docs/manual/mod/core.html.en |
||||||
|
@@ -90,6 +90,7 @@ available</td></tr> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangeoverlaps">MaxRangeOverlaps</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxrangereversals">MaxRangeReversals</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#maxranges">MaxRanges</a></li> |
||||||
|
+<li><img alt="" src="../images/down.gif" /> <a href="#mergeslashes">MergeSlashes</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#mutex">Mutex</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#namevirtualhost">NameVirtualHost</a></li> |
||||||
|
<li><img alt="" src="../images/down.gif" /> <a href="#options">Options</a></li> |
||||||
|
@@ -3170,6 +3171,30 @@ resource </td></tr> |
||||||
|
|
||||||
|
</div> |
||||||
|
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> |
||||||
|
+<div class="directive-section"><h2><a name="MergeSlashes" id="MergeSlashes">MergeSlashes</a> <a name="mergeslashes" id="mergeslashes">Directive</a></h2> |
||||||
|
+<table class="directive"> |
||||||
|
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Controls whether the server merges consecutive slashes in URLs. </td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>MergeSlashes ON | OFF</code></td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>MergeSlashes ON</code></td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr> |
||||||
|
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available in Apache HTTP Server 2.4.6 in Red Hat Enterprise Linux 7</td></tr> |
||||||
|
+</table> |
||||||
|
+ <p>By default, the server merges (or collapses) multiple consecutive slash |
||||||
|
+ ('/') characters in the path component of the request URL.</p> |
||||||
|
+ |
||||||
|
+ <p>When mapping URL's to the filesystem, these multiple slashes are not |
||||||
|
+ significant. However, URL's handled other ways, such as by CGI or proxy, |
||||||
|
+ might prefer to retain the significance of multiple consecutive slashes. |
||||||
|
+ In these cases <code class="directive">MergeSlashes</code> can be set to |
||||||
|
+ <em>OFF</em> to retain the multiple consecutive slashes. In these |
||||||
|
+ configurations, regular expressions used in the configuration file that match |
||||||
|
+ the path component of the URL (<code class="directive">LocationMatch</code>, |
||||||
|
+ <code class="directive">RewriteRule</code>, ...) need to take into account multiple |
||||||
|
+ consecutive slashes.</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="Mutex" id="Mutex">Mutex</a> <a name="mutex" id="mutex">Directive</a></h2> |
||||||
|
<table class="directive"> |
||||||
|
<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Configures mutex mechanism and lock file directory for all |
||||||
|
diff --git a/include/http_core.h b/include/http_core.h |
||||||
|
index c05d06e..76bf5a4 100644 |
||||||
|
--- a/include/http_core.h |
||||||
|
+++ b/include/http_core.h |
||||||
|
@@ -465,6 +465,17 @@ typedef unsigned long etag_components_t; |
||||||
|
/* This is the default value used */ |
||||||
|
#define ETAG_BACKWARD (ETAG_MTIME | ETAG_SIZE) |
||||||
|
|
||||||
|
+/* Generic ON/OFF/UNSET for unsigned int foo :2 */ |
||||||
|
+#define AP_CORE_CONFIG_OFF (0) |
||||||
|
+#define AP_CORE_CONFIG_ON (1) |
||||||
|
+#define AP_CORE_CONFIG_UNSET (2) |
||||||
|
+ |
||||||
|
+/* Generic merge of flag */ |
||||||
|
+#define AP_CORE_MERGE_FLAG(field, to, base, over) to->field = \ |
||||||
|
+ over->field != AP_CORE_CONFIG_UNSET \ |
||||||
|
+ ? over->field \ |
||||||
|
+ : base->field |
||||||
|
+ |
||||||
|
/** |
||||||
|
* @brief Server Signature Enumeration |
||||||
|
*/ |
||||||
|
@@ -682,7 +693,7 @@ typedef struct { |
||||||
|
#define AP_HTTP_METHODS_LENIENT 1 |
||||||
|
#define AP_HTTP_METHODS_REGISTERED 2 |
||||||
|
char http_methods; |
||||||
|
- |
||||||
|
+ unsigned int merge_slashes; |
||||||
|
} core_server_config; |
||||||
|
|
||||||
|
/* for AddOutputFiltersByType in core.c */ |
||||||
|
diff --git a/include/httpd.h b/include/httpd.h |
||||||
|
index 176ef5e..a552358 100644 |
||||||
|
--- a/include/httpd.h |
||||||
|
+++ b/include/httpd.h |
||||||
|
@@ -1622,11 +1622,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes); |
||||||
|
AP_DECLARE(int) ap_unescape_urlencoded(char *query); |
||||||
|
|
||||||
|
/** |
||||||
|
- * Convert all double slashes to single slashes |
||||||
|
- * @param name The string to convert |
||||||
|
+ * Convert all double slashes to single slashes, except where significant |
||||||
|
+ * to the filesystem on the current platform. |
||||||
|
+ * @param name The string to convert, assumed to be a filesystem path |
||||||
|
*/ |
||||||
|
AP_DECLARE(void) ap_no2slash(char *name); |
||||||
|
|
||||||
|
+/** |
||||||
|
+ * Convert all double slashes to single slashes, except where significant |
||||||
|
+ * to the filesystem on the current platform. |
||||||
|
+ * @param name The string to convert |
||||||
|
+ * @param is_fs_path if set to 0, the significance of any double-slashes is |
||||||
|
+ * ignored. |
||||||
|
+ */ |
||||||
|
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path); |
||||||
|
+ |
||||||
|
/** |
||||||
|
* Remove all ./ and xx/../ substrings from a file name. Also remove |
||||||
|
* any leading ../ or /../ substrings. |
||||||
|
diff --git a/server/core.c b/server/core.c |
||||||
|
index 0e69f8c..67efd7e 100644 |
||||||
|
--- a/server/core.c |
||||||
|
+++ b/server/core.c |
||||||
|
@@ -476,6 +476,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) |
||||||
|
*/ |
||||||
|
|
||||||
|
conf->trace_enable = AP_TRACE_UNSET; |
||||||
|
+ conf->merge_slashes = AP_CORE_CONFIG_UNSET; |
||||||
|
|
||||||
|
return (void *)conf; |
||||||
|
} |
||||||
|
@@ -536,6 +537,8 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) |
||||||
|
? virt->merge_trailers |
||||||
|
: base->merge_trailers; |
||||||
|
|
||||||
|
+ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt); |
||||||
|
+ |
||||||
|
return conf; |
||||||
|
} |
||||||
|
|
||||||
|
@@ -1673,6 +1676,13 @@ static const char *set_override(cmd_parms *cmd, void *d_, const char *l) |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
+static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag) |
||||||
|
+{ |
||||||
|
+ core_server_config *conf = |
||||||
|
+ ap_get_core_module_config(cmd->server->module_config); |
||||||
|
+ return ap_set_flag_slot(cmd, conf, flag); |
||||||
|
+} |
||||||
|
+ |
||||||
|
static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) |
||||||
|
{ |
||||||
|
core_dir_config *d = d_; |
||||||
|
@@ -4216,6 +4226,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON |
||||||
|
, |
||||||
|
AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF, |
||||||
|
"Registers non-standard HTTP methods"), |
||||||
|
+AP_INIT_FLAG("MergeSlashes", set_core_server_flag, |
||||||
|
+ (void *)APR_OFFSETOF(core_server_config, merge_slashes), |
||||||
|
+ RSRC_CONF, |
||||||
|
+ "Controls whether consecutive slashes in the URI path are merged"), |
||||||
|
{ NULL } |
||||||
|
}; |
||||||
|
|
||||||
|
diff --git a/server/request.c b/server/request.c |
||||||
|
index 4eef097..cba3891 100644 |
||||||
|
--- a/server/request.c |
||||||
|
+++ b/server/request.c |
||||||
|
@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) |
||||||
|
int file_req = (r->main && r->filename); |
||||||
|
int access_status; |
||||||
|
core_dir_config *d; |
||||||
|
+ core_server_config *sconf = |
||||||
|
+ ap_get_core_module_config(r->server->module_config); |
||||||
|
|
||||||
|
/* Ignore embedded %2F's in path for proxy requests */ |
||||||
|
if (!r->proxyreq && r->parsed_uri.path) { |
||||||
|
@@ -191,6 +193,12 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) |
||||||
|
} |
||||||
|
|
||||||
|
ap_getparents(r->uri); /* OK --- shrinking transformations... */ |
||||||
|
+ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { |
||||||
|
+ ap_no2slash(r->uri); |
||||||
|
+ if (r->parsed_uri.path) { |
||||||
|
+ ap_no2slash(r->parsed_uri.path); |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
|
||||||
|
/* All file subrequests are a huge pain... they cannot bubble through the |
||||||
|
* next several steps. Only file subrequests are allowed an empty uri, |
||||||
|
@@ -1383,20 +1391,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) |
||||||
|
|
||||||
|
cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); |
||||||
|
cached = (cache->cached != NULL); |
||||||
|
- |
||||||
|
- /* Location and LocationMatch differ on their behaviour w.r.t. multiple |
||||||
|
- * slashes. Location matches multiple slashes with a single slash, |
||||||
|
- * LocationMatch doesn't. An exception, for backwards brokenness is |
||||||
|
- * absoluteURIs... in which case neither match multiple slashes. |
||||||
|
- */ |
||||||
|
- if (r->uri[0] != '/') { |
||||||
|
- entry_uri = r->uri; |
||||||
|
- } |
||||||
|
- else { |
||||||
|
- char *uri = apr_pstrdup(r->pool, r->uri); |
||||||
|
- ap_no2slash(uri); |
||||||
|
- entry_uri = uri; |
||||||
|
- } |
||||||
|
+ entry_uri = r->uri; |
||||||
|
|
||||||
|
/* If we have an cache->cached location that matches r->uri, |
||||||
|
* and the vhost's list of locations hasn't changed, we can skip |
||||||
|
@@ -1449,7 +1444,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) |
||||||
|
* terminated (or at the end of the string) to match. |
||||||
|
*/ |
||||||
|
if (entry_core->r |
||||||
|
- ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0) |
||||||
|
+ ? ap_regexec(entry_core->r, entry_uri, 0, NULL, 0) |
||||||
|
: (entry_core->d_is_fnmatch |
||||||
|
? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME) |
||||||
|
: (strncmp(entry_core->d, cache->cached, len) |
||||||
|
diff --git a/server/util.c b/server/util.c |
||||||
|
index f9e3b51..4eac462 100644 |
||||||
|
--- a/server/util.c |
||||||
|
+++ b/server/util.c |
||||||
|
@@ -561,16 +561,20 @@ AP_DECLARE(void) ap_getparents(char *name) |
||||||
|
name[l] = '\0'; |
||||||
|
} |
||||||
|
} |
||||||
|
- |
||||||
|
-AP_DECLARE(void) ap_no2slash(char *name) |
||||||
|
+AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) |
||||||
|
{ |
||||||
|
+ |
||||||
|
char *d, *s; |
||||||
|
|
||||||
|
+ if (!*name) { |
||||||
|
+ return; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
s = d = name; |
||||||
|
|
||||||
|
#ifdef HAVE_UNC_PATHS |
||||||
|
/* Check for UNC names. Leave leading two slashes. */ |
||||||
|
- if (s[0] == '/' && s[1] == '/') |
||||||
|
+ if (is_fs_path && s[0] == '/' && s[1] == '/') |
||||||
|
*d++ = *s++; |
||||||
|
#endif |
||||||
|
|
||||||
|
@@ -587,6 +591,10 @@ AP_DECLARE(void) ap_no2slash(char *name) |
||||||
|
*d = '\0'; |
||||||
|
} |
||||||
|
|
||||||
|
+AP_DECLARE(void) ap_no2slash(char *name) |
||||||
|
+{ |
||||||
|
+ ap_no2slash_ex(name, 1); |
||||||
|
+} |
||||||
|
|
||||||
|
/* |
||||||
|
* copy at most n leading directories of s into d |
@ -0,0 +1,13 @@ |
|||||||
|
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c |
||||||
|
index e672e4a..8be833a 100644 |
||||||
|
--- a/modules/proxy/proxy_util.c |
||||||
|
+++ b/modules/proxy/proxy_util.c |
||||||
|
@@ -3557,6 +3557,8 @@ static proxy_schemes_t pschemes[] = |
||||||
|
{"fcgi", 8000}, |
||||||
|
{"ajp", AJP13_DEF_PORT}, |
||||||
|
{"scgi", 4000}, |
||||||
|
+ {"ws", 80}, |
||||||
|
+ {"wss", 443}, |
||||||
|
{ NULL, 0xFFFF } /* unknown port */ |
||||||
|
}; |
||||||
|
|
@ -0,0 +1,11 @@ |
|||||||
|
--- a/modules/ldap/util_ldap_cache.c 2013/08/19 11:41:29 1515371 |
||||||
|
+++ b/modules/ldap/util_ldap_cache.c 2013/08/19 11:45:19 1515372 |
||||||
|
@@ -52,7 +52,7 @@ |
||||||
|
|
||||||
|
if (node) { |
||||||
|
if (!(node->url = util_ald_strdup(cache, n->url))) { |
||||||
|
- util_ald_free(cache, node->url); |
||||||
|
+ util_ald_free(cache, node); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
node->search_cache = n->search_cache; |
@ -0,0 +1,265 @@ |
|||||||
|
diff --git a/docs/manual/expr.html.en b/docs/manual/expr.html.en |
||||||
|
index 5c3ae45..8bd941a 100644 |
||||||
|
--- a/docs/manual/expr.html.en |
||||||
|
+++ b/docs/manual/expr.html.en |
||||||
|
@@ -46,7 +46,7 @@ |
||||||
|
<li><img alt="" src="./images/down.gif" /> <a href="#other">Other</a></li> |
||||||
|
<li><img alt="" src="./images/down.gif" /> <a href="#sslrequire">Comparison with SSLRequire</a></li> |
||||||
|
<li><img alt="" src="./images/down.gif" /> <a href="#compatibility">Version History</a></li> |
||||||
|
-</ul><h3>See also</h3><ul class="seealso"><li><code class="directive"><a href="./mod/core.html#if"><If></a></code></li><li><code class="directive"><a href="./mod/core.html#elseif"><ElseIf></a></code></li><li><code class="directive"><a href="./mod/core.html#else"><Else></a></code></li><li><code class="directive"><a href="./mod/mod_auth_basic.html#authbasicfake">AuthBasicFake</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformloginrequiredlocation">AuthFormLoginRequiredLocation</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformloginsuccesslocation">AuthFormLoginSuccessLocation</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformlogoutlocation">AuthFormLogoutLocation</a></code></li><li><code class="directive"><a href="./mod/mod_rewrite.html#rewritecond">RewriteCond</a></code></li><li><code class="directive"><a href="./mod/mod_setenvif.html#setenvifexpr">SetEnvIfExpr</a></code></li><li><code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code></li><li><code class="directive"><a href="./mod/mod_headers.html#requestheader">RequestHeader</a></code></li><li><code class="directive"><a href="./mod/mod_filter.html#filterprovider">FilterProvider</a></code></li><li><a href="mod/mod_authz_core.html#reqexpr">Require expr</a></li><li><code class="directive"><a href="./mod/mod_ssl.html#sslrequire">SSLRequire</a></code></li><li><code class="directive"><a href="./mod/mod_log_debug.html#logmessage">LogMessage</a></code></li><li><code class="module"><a href="./mod/mod_include.html">mod_include</a></code></li></ul><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div> |
||||||
|
+</ul><h3>See also</h3><ul class="seealso"><li><code class="directive"><a href="./mod/core.html#if"><If></a></code></li><li><code class="directive"><a href="./mod/core.html#elseif"><ElseIf></a></code></li><li><code class="directive"><a href="./mod/core.html#else"><Else></a></code></li><li><code class="directive"><a href="./mod/mod_auth_basic.html#authbasicfake">AuthBasicFake</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformloginrequiredlocation">AuthFormLoginRequiredLocation</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformloginsuccesslocation">AuthFormLoginSuccessLocation</a></code></li><li><code class="directive"><a href="./mod/mod_auth_form.html#authformlogoutlocation">AuthFormLogoutLocation</a></code></li><li><code class="directive"><a href="./mod/mod_rewrite.html#rewritecond">RewriteCond</a></code></li><li><code class="directive"><a href="./mod/mod_setenvif.html#setenvifexpr">SetEnvIfExpr</a></code></li><li><code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code></li><li><code class="directive"><a href="./mod/mod_headers.html#requestheader">RequestHeader</a></code></li><li><code class="directive"><a href="./mod/mod_filter.html#filterprovider">FilterProvider</a></code></li><li><a href="mod/mod_authz_core.html#reqexpr">Require expr</a></li><li><code class="directive"><a href="mod/mod_authnz_ldap.html#requser">Require ldap-user</a></code></li><li><code class="directive"><a href="mod/mod_authnz_ldap.html#reqgroup">Require ldap-group</a></code></li><li><code class="directive"><a href="mod/mod_authnz_ldap.html#reqdn">Require ldap-dn</a></code></li><li><code class="directive"><a href="mod/mod_authnz_ldap.html#reqattribute">Require ldap-attribute</a></code></li><li><code class="directive"><a href="mod/mod_authnz_ldap.html#reqfilter">Require ldap-filter</a></code></li><li><code class="directive"><a href="./mod/mod_ssl.html#sslrequire">SSLRequire</a></code></li><li><code class="directive"><a href="./mod/mod_log_debug.html#logmessage">LogMessage</a></code></li><li><code class="module"><a href="./mod/mod_include.html">mod_include</a></code></li></ul><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div> |
||||||
|
<div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div> |
||||||
|
<div class="section"> |
||||||
|
<h2><a name="grammar" id="grammar">Grammar in Backus-Naur Form notation</a></h2> |
||||||
|
diff --git a/docs/manual/mod/mod_authnz_ldap.html.en b/docs/manual/mod/mod_authnz_ldap.html.en |
||||||
|
index 7199052..c86dc8a 100644 |
||||||
|
--- a/docs/manual/mod/mod_authnz_ldap.html.en |
||||||
|
+++ b/docs/manual/mod/mod_authnz_ldap.html.en |
||||||
|
@@ -350,6 +350,9 @@ for HTTP Basic authentication.</td></tr> |
||||||
|
<code>ldap-filter</code>. Other authorization types may also be |
||||||
|
used but may require that additional authorization modules be loaded.</p> |
||||||
|
|
||||||
|
+ <p>Since v2.5.0, <a href="../expr.html">expressions</a> are supported |
||||||
|
+ within the LDAP require directives.</p> |
||||||
|
+ |
||||||
|
<h3><a name="requser" id="requser">Require ldap-user</a></h3> |
||||||
|
|
||||||
|
<p>The <code>Require ldap-user</code> directive specifies what |
||||||
|
@@ -576,6 +579,16 @@ Require ldap-group cn=Administrators, o=Example |
||||||
|
</li> |
||||||
|
|
||||||
|
<li> |
||||||
|
+ Grant access to anybody in the group whose name matches the |
||||||
|
+ hostname of the virtual host. In this example an |
||||||
|
+ <a href="../expr.html">expression</a> is used to build the filter. |
||||||
|
+<highlight language="config"> |
||||||
|
+AuthLDAPURL ldap://ldap.example.com/o=Example?uid |
||||||
|
+Require ldap-group cn=%{SERVER_NAME}, o=Example |
||||||
|
+</highlight> |
||||||
|
+ </li> |
||||||
|
+ |
||||||
|
+ <li> |
||||||
|
The next example assumes that everyone at Example who |
||||||
|
carries an alphanumeric pager will have an LDAP attribute |
||||||
|
of <code>qpagePagerID</code>. The example will grant access |
||||||
|
diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c |
||||||
|
index 2c25dbc..063debe 100644 |
||||||
|
--- a/modules/aaa/mod_authnz_ldap.c |
||||||
|
+++ b/modules/aaa/mod_authnz_ldap.c |
||||||
|
@@ -607,6 +607,10 @@ static authz_status ldapuser_check_authorization(request_rec *r, |
||||||
|
|
||||||
|
util_ldap_connection_t *ldc = NULL; |
||||||
|
|
||||||
|
+ const char *err = NULL; |
||||||
|
+ const ap_expr_info_t *expr = parsed_require_args; |
||||||
|
+ const char *require; |
||||||
|
+ |
||||||
|
const char *t; |
||||||
|
char *w; |
||||||
|
|
||||||
|
@@ -680,11 +684,19 @@ static authz_status ldapuser_check_authorization(request_rec *r, |
||||||
|
return AUTHZ_DENIED; |
||||||
|
} |
||||||
|
|
||||||
|
+ require = ap_expr_str_exec(r, expr, &err); |
||||||
|
+ if (err) { |
||||||
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02585) |
||||||
|
+ "auth_ldap authorize: require user: Can't evaluate expression: %s", |
||||||
|
+ err); |
||||||
|
+ return AUTHZ_DENIED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* |
||||||
|
* First do a whole-line compare, in case it's something like |
||||||
|
* require user Babs Jensen |
||||||
|
*/ |
||||||
|
- result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require_args); |
||||||
|
+ result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require); |
||||||
|
switch(result) { |
||||||
|
case LDAP_COMPARE_TRUE: { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01703) |
||||||
|
@@ -704,7 +716,7 @@ static authz_status ldapuser_check_authorization(request_rec *r, |
||||||
|
/* |
||||||
|
* Now break apart the line and compare each word on it |
||||||
|
*/ |
||||||
|
- t = require_args; |
||||||
|
+ t = require; |
||||||
|
while ((w = ap_getword_conf(r->pool, &t)) && w[0]) { |
||||||
|
result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w); |
||||||
|
switch(result) { |
||||||
|
@@ -744,6 +756,10 @@ static authz_status ldapgroup_check_authorization(request_rec *r, |
||||||
|
|
||||||
|
util_ldap_connection_t *ldc = NULL; |
||||||
|
|
||||||
|
+ const char *err = NULL; |
||||||
|
+ const ap_expr_info_t *expr = parsed_require_args; |
||||||
|
+ const char *require; |
||||||
|
+ |
||||||
|
const char *t; |
||||||
|
|
||||||
|
char filtbuf[FILTER_LENGTH]; |
||||||
|
@@ -863,7 +879,15 @@ static authz_status ldapgroup_check_authorization(request_rec *r, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- t = require_args; |
||||||
|
+ require = ap_expr_str_exec(r, expr, &err); |
||||||
|
+ if (err) { |
||||||
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02586) |
||||||
|
+ "auth_ldap authorize: require group: Can't evaluate expression: %s", |
||||||
|
+ err); |
||||||
|
+ return AUTHZ_DENIED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ t = require; |
||||||
|
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01713) |
||||||
|
"auth_ldap authorize: require group: testing for group " |
||||||
|
@@ -959,6 +983,10 @@ static authz_status ldapdn_check_authorization(request_rec *r, |
||||||
|
|
||||||
|
util_ldap_connection_t *ldc = NULL; |
||||||
|
|
||||||
|
+ const char *err = NULL; |
||||||
|
+ const ap_expr_info_t *expr = parsed_require_args; |
||||||
|
+ const char *require; |
||||||
|
+ |
||||||
|
const char *t; |
||||||
|
|
||||||
|
char filtbuf[FILTER_LENGTH]; |
||||||
|
@@ -1021,7 +1049,15 @@ static authz_status ldapdn_check_authorization(request_rec *r, |
||||||
|
req->user = r->user; |
||||||
|
} |
||||||
|
|
||||||
|
- t = require_args; |
||||||
|
+ require = ap_expr_str_exec(r, expr, &err); |
||||||
|
+ if (err) { |
||||||
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02587) |
||||||
|
+ "auth_ldap authorize: require dn: Can't evaluate expression: %s", |
||||||
|
+ err); |
||||||
|
+ return AUTHZ_DENIED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ t = require; |
||||||
|
|
||||||
|
if (req->dn == NULL || strlen(req->dn) == 0) { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01725) |
||||||
|
@@ -1068,6 +1104,10 @@ static authz_status ldapattribute_check_authorization(request_rec *r, |
||||||
|
|
||||||
|
util_ldap_connection_t *ldc = NULL; |
||||||
|
|
||||||
|
+ const char *err = NULL; |
||||||
|
+ const ap_expr_info_t *expr = parsed_require_args; |
||||||
|
+ const char *require; |
||||||
|
+ |
||||||
|
const char *t; |
||||||
|
char *w, *value; |
||||||
|
|
||||||
|
@@ -1138,7 +1178,16 @@ static authz_status ldapattribute_check_authorization(request_rec *r, |
||||||
|
return AUTHZ_DENIED; |
||||||
|
} |
||||||
|
|
||||||
|
- t = require_args; |
||||||
|
+ require = ap_expr_str_exec(r, expr, &err); |
||||||
|
+ if (err) { |
||||||
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02588) |
||||||
|
+ "auth_ldap authorize: require ldap-attribute: Can't " |
||||||
|
+ "evaluate expression: %s", err); |
||||||
|
+ return AUTHZ_DENIED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ t = require; |
||||||
|
+ |
||||||
|
while (t[0]) { |
||||||
|
w = ap_getword(r->pool, &t, '='); |
||||||
|
value = ap_getword_conf(r->pool, &t); |
||||||
|
@@ -1183,6 +1232,11 @@ static authz_status ldapfilter_check_authorization(request_rec *r, |
||||||
|
(authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module); |
||||||
|
|
||||||
|
util_ldap_connection_t *ldc = NULL; |
||||||
|
+ |
||||||
|
+ const char *err = NULL; |
||||||
|
+ const ap_expr_info_t *expr = parsed_require_args; |
||||||
|
+ const char *require; |
||||||
|
+ |
||||||
|
const char *t; |
||||||
|
|
||||||
|
char filtbuf[FILTER_LENGTH]; |
||||||
|
@@ -1252,7 +1306,15 @@ static authz_status ldapfilter_check_authorization(request_rec *r, |
||||||
|
return AUTHZ_DENIED; |
||||||
|
} |
||||||
|
|
||||||
|
- t = require_args; |
||||||
|
+ require = ap_expr_str_exec(r, expr, &err); |
||||||
|
+ if (err) { |
||||||
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02589) |
||||||
|
+ "auth_ldap authorize: require ldap-filter: Can't " |
||||||
|
+ "evaluate require expression: %s", err); |
||||||
|
+ return AUTHZ_DENIED; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ t = require; |
||||||
|
|
||||||
|
if (t[0]) { |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01743) |
||||||
|
@@ -1311,6 +1373,25 @@ static authz_status ldapfilter_check_authorization(request_rec *r, |
||||||
|
return AUTHZ_DENIED; |
||||||
|
} |
||||||
|
|
||||||
|
+static const char *ldap_parse_config(cmd_parms *cmd, const char *require_line, |
||||||
|
+ const void **parsed_require_line) |
||||||
|
+{ |
||||||
|
+ const char *expr_err = NULL; |
||||||
|
+ ap_expr_info_t *expr; |
||||||
|
+ |
||||||
|
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT, |
||||||
|
+ &expr_err, NULL); |
||||||
|
+ |
||||||
|
+ if (expr_err) |
||||||
|
+ return apr_pstrcat(cmd->temp_pool, |
||||||
|
+ "Cannot parse expression in require line: ", |
||||||
|
+ expr_err, NULL); |
||||||
|
+ |
||||||
|
+ *parsed_require_line = expr; |
||||||
|
+ |
||||||
|
+ return NULL; |
||||||
|
+} |
||||||
|
+ |
||||||
|
|
||||||
|
/* |
||||||
|
* Use the ldap url parsing routines to break up the ldap url into |
||||||
|
@@ -1769,30 +1850,30 @@ static const authn_provider authn_ldap_provider = |
||||||
|
static const authz_provider authz_ldapuser_provider = |
||||||
|
{ |
||||||
|
&ldapuser_check_authorization, |
||||||
|
- NULL, |
||||||
|
+ &ldap_parse_config, |
||||||
|
}; |
||||||
|
static const authz_provider authz_ldapgroup_provider = |
||||||
|
{ |
||||||
|
&ldapgroup_check_authorization, |
||||||
|
- NULL, |
||||||
|
+ &ldap_parse_config, |
||||||
|
}; |
||||||
|
|
||||||
|
static const authz_provider authz_ldapdn_provider = |
||||||
|
{ |
||||||
|
&ldapdn_check_authorization, |
||||||
|
- NULL, |
||||||
|
+ &ldap_parse_config, |
||||||
|
}; |
||||||
|
|
||||||
|
static const authz_provider authz_ldapattribute_provider = |
||||||
|
{ |
||||||
|
&ldapattribute_check_authorization, |
||||||
|
- NULL, |
||||||
|
+ &ldap_parse_config, |
||||||
|
}; |
||||||
|
|
||||||
|
static const authz_provider authz_ldapfilter_provider = |
||||||
|
{ |
||||||
|
&ldapfilter_check_authorization, |
||||||
|
- NULL, |
||||||
|
+ &ldap_parse_config, |
||||||
|
}; |
||||||
|
|
||||||
|
static void ImportULDAPOptFn(void) |
@ -0,0 +1,26 @@ |
|||||||
|
# ./pullrev.sh 1737363 |
||||||
|
http://svn.apache.org/viewvc?view=revision&revision=1737363 |
||||||
|
|
||||||
|
--- httpd-2.4.6/modules/proxy/mod_proxy_express.c |
||||||
|
+++ httpd-2.4.6/modules/proxy/mod_proxy_express.c |
||||||
|
@@ -145,16 +145,14 @@ |
||||||
|
key.dsize = strlen(key.dptr); |
||||||
|
|
||||||
|
rv = apr_dbm_fetch(db, key, &val); |
||||||
|
+ if (rv == APR_SUCCESS) { |
||||||
|
+ backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); |
||||||
|
+ } |
||||||
|
apr_dbm_close(db); |
||||||
|
- if (rv != APR_SUCCESS) { |
||||||
|
+ if (rv != APR_SUCCESS || !backend) { |
||||||
|
return DECLINED; |
||||||
|
} |
||||||
|
|
||||||
|
- backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); |
||||||
|
- if (!backend) { |
||||||
|
- return DECLINED; |
||||||
|
- } |
||||||
|
- |
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01004) |
||||||
|
"proxy_express: found %s -> %s", name, backend); |
||||||
|
r->filename = apr_pstrcat(r->pool, "proxy:", backend, r->uri, NULL); |
@ -0,0 +1,25 @@ |
|||||||
|
--- a/modules/ldap/util_ldap.c 2018/02/20 13:00:39 1824871 |
||||||
|
+++ b/modules/ldap/util_ldap.c 2018/02/20 13:02:54 1824872 |
||||||
|
@@ -2858,7 +2858,6 @@ |
||||||
|
st->search_cache_size = base->search_cache_size; |
||||||
|
st->compare_cache_ttl = base->compare_cache_ttl; |
||||||
|
st->compare_cache_size = base->compare_cache_size; |
||||||
|
- st->util_ldap_cache_lock = base->util_ldap_cache_lock; |
||||||
|
|
||||||
|
st->connections = NULL; |
||||||
|
st->ssl_supported = 0; /* not known until post-config and re-merged */ |
||||||
|
@@ -2977,12 +2976,12 @@ |
||||||
|
st_vhost = (util_ldap_state_t *) |
||||||
|
ap_get_module_config(s_vhost->module_config, |
||||||
|
&ldap_module); |
||||||
|
- |
||||||
|
+ st_vhost->util_ldap_cache = st->util_ldap_cache; |
||||||
|
+ st_vhost->util_ldap_cache_lock = st->util_ldap_cache_lock; |
||||||
|
#if APR_HAS_SHARED_MEMORY |
||||||
|
st_vhost->cache_shm = st->cache_shm; |
||||||
|
st_vhost->cache_rmm = st->cache_rmm; |
||||||
|
st_vhost->cache_file = st->cache_file; |
||||||
|
- st_vhost->util_ldap_cache = st->util_ldap_cache; |
||||||
|
ap_log_error(APLOG_MARK, APLOG_DEBUG, result, s, APLOGNO(01316) |
||||||
|
"LDAP merging Shared Cache conf: shm=0x%pp rmm=0x%pp " |
||||||
|
"for VHOST: %s", st->cache_shm, st->cache_rmm, |
@ -0,0 +1,96 @@ |
|||||||
|
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c |
||||||
|
index 57b76c0..814ec4f 100644 |
||||||
|
--- a/modules/ssl/ssl_engine_init.c |
||||||
|
+++ b/modules/ssl/ssl_engine_init.c |
||||||
|
@@ -1522,70 +1522,18 @@ void ssl_init_CheckServers(SSLModConfigRec *mc, server_rec *base_server, apr_poo |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
-static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a, |
||||||
|
- const X509_NAME * const *b) |
||||||
|
-{ |
||||||
|
- return(X509_NAME_cmp(*a, *b)); |
||||||
|
-} |
||||||
|
- |
||||||
|
-static void ssl_init_PushCAList(STACK_OF(X509_NAME) *ca_list, |
||||||
|
- server_rec *s, apr_pool_t *ptemp, |
||||||
|
- const char *file) |
||||||
|
-{ |
||||||
|
- int n; |
||||||
|
- STACK_OF(X509_NAME) *sk; |
||||||
|
- |
||||||
|
- sk = (STACK_OF(X509_NAME) *) |
||||||
|
- SSL_load_client_CA_file(file); |
||||||
|
- |
||||||
|
- if (!sk) { |
||||||
|
- return; |
||||||
|
- } |
||||||
|
- |
||||||
|
- for (n = 0; n < sk_X509_NAME_num(sk); n++) { |
||||||
|
- X509_NAME *name = sk_X509_NAME_value(sk, n); |
||||||
|
- |
||||||
|
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02209) |
||||||
|
- "CA certificate: %s", |
||||||
|
- SSL_X509_NAME_to_string(ptemp, name, 0)); |
||||||
|
- |
||||||
|
- /* |
||||||
|
- * note that SSL_load_client_CA_file() checks for duplicates, |
||||||
|
- * but since we call it multiple times when reading a directory |
||||||
|
- * we must also check for duplicates ourselves. |
||||||
|
- */ |
||||||
|
- |
||||||
|
- if (sk_X509_NAME_find(ca_list, name) < 0) { |
||||||
|
- /* this will be freed when ca_list is */ |
||||||
|
- sk_X509_NAME_push(ca_list, name); |
||||||
|
- } |
||||||
|
- else { |
||||||
|
- /* need to free this ourselves, else it will leak */ |
||||||
|
- X509_NAME_free(name); |
||||||
|
- } |
||||||
|
- } |
||||||
|
- |
||||||
|
- sk_X509_NAME_free(sk); |
||||||
|
-} |
||||||
|
- |
||||||
|
STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, |
||||||
|
apr_pool_t *ptemp, |
||||||
|
const char *ca_file, |
||||||
|
const char *ca_path) |
||||||
|
{ |
||||||
|
- STACK_OF(X509_NAME) *ca_list; |
||||||
|
- |
||||||
|
- /* |
||||||
|
- * Start with a empty stack/list where new |
||||||
|
- * entries get added in sorted order. |
||||||
|
- */ |
||||||
|
- ca_list = sk_X509_NAME_new(ssl_init_FindCAList_X509NameCmp); |
||||||
|
+ STACK_OF(X509_NAME) *ca_list = sk_X509_NAME_new_null();; |
||||||
|
|
||||||
|
/* |
||||||
|
* Process CA certificate bundle file |
||||||
|
*/ |
||||||
|
if (ca_file) { |
||||||
|
- ssl_init_PushCAList(ca_list, s, ptemp, ca_file); |
||||||
|
+ SSL_add_file_cert_subjects_to_stack(ca_list, ca_file); |
||||||
|
/* |
||||||
|
* If ca_list is still empty after trying to load ca_file |
||||||
|
* then the file failed to load, and users should hear about that. |
||||||
|
@@ -1619,17 +1567,12 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, |
||||||
|
continue; /* don't try to load directories */ |
||||||
|
} |
||||||
|
file = apr_pstrcat(ptemp, ca_path, "/", direntry.name, NULL); |
||||||
|
- ssl_init_PushCAList(ca_list, s, ptemp, file); |
||||||
|
+ SSL_add_file_cert_subjects_to_stack(ca_list, file); |
||||||
|
} |
||||||
|
|
||||||
|
apr_dir_close(dir); |
||||||
|
} |
||||||
|
|
||||||
|
- /* |
||||||
|
- * Cleanup |
||||||
|
- */ |
||||||
|
- (void) sk_X509_NAME_set_cmp_func(ca_list, NULL); |
||||||
|
- |
||||||
|
return ca_list; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,198 @@ |
|||||||
|
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en |
||||||
|
index 4580f1c..fb8202e 100644 |
||||||
|
--- a/docs/manual/mod/mod_ssl.html.en |
||||||
|
+++ b/docs/manual/mod/mod_ssl.html.en |
||||||
|
@@ -991,7 +991,8 @@ the certificate being verified.</p> |
||||||
|
<p>This option enables OCSP validation of the client certificate |
||||||
|
chain. If this option is enabled, certificates in the client's |
||||||
|
certificate chain will be validated against an OCSP responder after |
||||||
|
-normal verification (including CRL checks) have taken place.</p> |
||||||
|
+normal verification (including CRL checks) have taken place. In |
||||||
|
+mode 'leaf', only the client certificate itself will be validated.</p> |
||||||
|
|
||||||
|
<p>The OCSP responder used is either extracted from the certificate |
||||||
|
itself, or derived by configuration; see the |
||||||
|
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c |
||||||
|
index 4a8b661..e637a9d 100644 |
||||||
|
--- a/modules/ssl/mod_ssl.c |
||||||
|
+++ b/modules/ssl/mod_ssl.c |
||||||
|
@@ -227,8 +227,8 @@ static const command_rec ssl_config_cmds[] = { |
||||||
|
"request body if a per-location SSL renegotiation is required due to " |
||||||
|
"changed access control requirements") |
||||||
|
|
||||||
|
- SSL_CMD_SRV(OCSPEnable, FLAG, |
||||||
|
- "Enable use of OCSP to verify certificate revocation ('on', 'off')") |
||||||
|
+ SSL_CMD_SRV(OCSPEnable, RAW_ARGS, |
||||||
|
+ "Enable use of OCSP to verify certificate revocation mode ('on', 'leaf', 'off')") |
||||||
|
SSL_CMD_SRV(OCSPDefaultResponder, TAKE1, |
||||||
|
"URL of the default OCSP Responder") |
||||||
|
SSL_CMD_SRV(OCSPOverrideResponder, FLAG, |
||||||
|
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c |
||||||
|
index 86a7f0f..714aee9 100644 |
||||||
|
--- a/modules/ssl/ssl_engine_config.c |
||||||
|
+++ b/modules/ssl/ssl_engine_config.c |
||||||
|
@@ -130,7 +130,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx) |
||||||
|
mctx->auth.verify_depth = UNSET; |
||||||
|
mctx->auth.verify_mode = SSL_CVERIFY_UNSET; |
||||||
|
|
||||||
|
- mctx->ocsp_enabled = FALSE; |
||||||
|
+ mctx->ocsp_mask = UNSET; |
||||||
|
mctx->ocsp_force_default = FALSE; |
||||||
|
mctx->ocsp_responder = NULL; |
||||||
|
mctx->ocsp_resptime_skew = UNSET; |
||||||
|
@@ -264,7 +264,7 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base, |
||||||
|
cfgMergeInt(auth.verify_depth); |
||||||
|
cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET); |
||||||
|
|
||||||
|
- cfgMergeBool(ocsp_enabled); |
||||||
|
+ cfgMergeInt(ocsp_mask); |
||||||
|
cfgMergeBool(ocsp_force_default); |
||||||
|
cfgMerge(ocsp_responder, NULL); |
||||||
|
cfgMergeInt(ocsp_resptime_skew); |
||||||
|
@@ -1575,11 +1575,46 @@ const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) |
||||||
|
+static const char *ssl_cmd_ocspcheck_parse(cmd_parms *parms, |
||||||
|
+ const char *arg, |
||||||
|
+ int *mask) |
||||||
|
{ |
||||||
|
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server); |
||||||
|
+ const char *w; |
||||||
|
+ |
||||||
|
+ w = ap_getword_conf(parms->temp_pool, &arg); |
||||||
|
+ if (strcEQ(w, "off")) { |
||||||
|
+ *mask = SSL_OCSPCHECK_NONE; |
||||||
|
+ } |
||||||
|
+ else if (strcEQ(w, "leaf")) { |
||||||
|
+ *mask = SSL_OCSPCHECK_LEAF; |
||||||
|
+ } |
||||||
|
+ else if (strcEQ(w, "on")) { |
||||||
|
+ *mask = SSL_OCSPCHECK_CHAIN; |
||||||
|
+ } |
||||||
|
+ else { |
||||||
|
+ return apr_pstrcat(parms->temp_pool, parms->cmd->name, |
||||||
|
+ ": Invalid argument '", w, "'", |
||||||
|
+ NULL); |
||||||
|
+ } |
||||||
|
+ |
||||||
|
+ while (*arg) { |
||||||
|
+ w = ap_getword_conf(parms->temp_pool, &arg); |
||||||
|
+ if (strcEQ(w, "no_ocsp_for_cert_ok")) { |
||||||
|
+ *mask |= SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK; |
||||||
|
+ } |
||||||
|
+ else { |
||||||
|
+ return apr_pstrcat(parms->temp_pool, parms->cmd->name, |
||||||
|
+ ": Invalid argument '", w, "'", |
||||||
|
+ NULL); |
||||||
|
+ } |
||||||
|
+ } |
||||||
|
|
||||||
|
- sc->server->ocsp_enabled = flag ? TRUE : FALSE; |
||||||
|
+ return NULL; |
||||||
|
+} |
||||||
|
+ |
||||||
|
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg) |
||||||
|
+{ |
||||||
|
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server); |
||||||
|
|
||||||
|
#ifdef OPENSSL_NO_OCSP |
||||||
|
if (flag) { |
||||||
|
@@ -1588,7 +1623,7 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
- return NULL; |
||||||
|
+ return ssl_cmd_ocspcheck_parse(cmd, arg, &sc->server->ocsp_mask); |
||||||
|
} |
||||||
|
|
||||||
|
const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag) |
||||||
|
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c |
||||||
|
index 672760c..57b76c0 100644 |
||||||
|
--- a/modules/ssl/ssl_engine_init.c |
||||||
|
+++ b/modules/ssl/ssl_engine_init.c |
||||||
|
@@ -762,6 +762,10 @@ static void ssl_init_ctx_crl(server_rec *s, |
||||||
|
unsigned long crlflags = 0; |
||||||
|
char *cfgp = mctx->pkp ? "SSLProxy" : "SSL"; |
||||||
|
|
||||||
|
+ if (mctx->ocsp_mask == UNSET) { |
||||||
|
+ mctx->ocsp_mask = SSL_OCSPCHECK_NONE; |
||||||
|
+ } |
||||||
|
+ |
||||||
|
/* |
||||||
|
* Configure Certificate Revocation List (CRL) Details |
||||||
|
*/ |
||||||
|
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c |
||||||
|
index 5ff35f5..9dc236c 100644 |
||||||
|
--- a/modules/ssl/ssl_engine_kernel.c |
||||||
|
+++ b/modules/ssl/ssl_engine_kernel.c |
||||||
|
@@ -1416,7 +1416,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) |
||||||
|
/* |
||||||
|
* Perform OCSP-based revocation checks |
||||||
|
*/ |
||||||
|
- if (ok && sc->server->ocsp_enabled) { |
||||||
|
+ if (ok && ((sc->server->ocsp_mask & SSL_OCSPCHECK_CHAIN) || |
||||||
|
+ (errdepth == 0 && (sc->server->ocsp_mask & SSL_OCSPCHECK_LEAF)))) { |
||||||
|
/* If there was an optional verification error, it's not |
||||||
|
* possible to perform OCSP validation since the issuer may be |
||||||
|
* missing/untrusted. Fail in that case. */ |
||||||
|
diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c |
||||||
|
index 90da5c2..58d267b 100644 |
||||||
|
--- a/modules/ssl/ssl_engine_ocsp.c |
||||||
|
+++ b/modules/ssl/ssl_engine_ocsp.c |
||||||
|
@@ -136,7 +136,14 @@ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, |
||||||
|
|
||||||
|
ruri = determine_responder_uri(sc, cert, c, pool); |
||||||
|
if (!ruri) { |
||||||
|
- return V_OCSP_CERTSTATUS_UNKNOWN; |
||||||
|
+ if (sc->server->ocsp_mask & SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK) { |
||||||
|
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, |
||||||
|
+ "Skipping OCSP check for certificate cos no OCSP URL" |
||||||
|
+ " found and no_ocsp_for_cert_ok is set"); |
||||||
|
+ return V_OCSP_CERTSTATUS_GOOD; |
||||||
|
+ } else { |
||||||
|
+ return V_OCSP_CERTSTATUS_UNKNOWN; |
||||||
|
+ } |
||||||
|
} |
||||||
|
|
||||||
|
request = create_request(ctx, cert, &certID, s, pool); |
||||||
|
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h |
||||||
|
index b601316..2d505f9 100644 |
||||||
|
--- a/modules/ssl/ssl_private.h |
||||||
|
+++ b/modules/ssl/ssl_private.h |
||||||
|
@@ -379,6 +379,16 @@ typedef enum { |
||||||
|
} ssl_crlcheck_t; |
||||||
|
|
||||||
|
/** |
||||||
|
+ * OCSP checking mask (mode | flags) |
||||||
|
+ */ |
||||||
|
+typedef enum { |
||||||
|
+ SSL_OCSPCHECK_NONE = (0), |
||||||
|
+ SSL_OCSPCHECK_LEAF = (1 << 0), |
||||||
|
+ SSL_OCSPCHECK_CHAIN = (1 << 1), |
||||||
|
+ SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK = (1 << 2) |
||||||
|
+} ssl_ocspcheck_t; |
||||||
|
+ |
||||||
|
+/** |
||||||
|
* Define the SSL pass phrase dialog types |
||||||
|
*/ |
||||||
|
typedef enum { |
||||||
|
@@ -668,7 +678,7 @@ typedef struct { |
||||||
|
|
||||||
|
modssl_auth_ctx_t auth; |
||||||
|
|
||||||
|
- BOOL ocsp_enabled; /* true if OCSP verification enabled */ |
||||||
|
+ int ocsp_mask; |
||||||
|
BOOL ocsp_force_default; /* true if the default responder URL is |
||||||
|
* used regardless of per-cert URL */ |
||||||
|
const char *ocsp_responder; /* default responder URL */ |
||||||
|
@@ -796,7 +806,7 @@ const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const ch |
||||||
|
const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg); |
||||||
|
const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg); |
||||||
|
const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); |
||||||
|
-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); |
||||||
|
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *flag); |
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_SRP |
||||||
|
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg); |
@ -0,0 +1,83 @@ |
|||||||
|
diff --git a/modules/http/http_request.c b/modules/http/http_request.c |
||||||
|
index c97dc77..9885de4 100644 |
||||||
|
--- a/modules/http/http_request.c |
||||||
|
+++ b/modules/http/http_request.c |
||||||
|
@@ -227,11 +227,21 @@ AP_DECLARE(void) ap_die(int type, request_rec *r) |
||||||
|
ap_die_r(type, r, r->status); |
||||||
|
} |
||||||
|
|
||||||
|
-static void check_pipeline(conn_rec *c) |
||||||
|
+#define RETRIEVE_BRIGADE_FROM_POOL(bb, key, pool, allocator) do { \ |
||||||
|
+ apr_pool_userdata_get((void **)&bb, key, pool); \ |
||||||
|
+ if (bb == NULL) { \ |
||||||
|
+ bb = apr_brigade_create(pool, allocator); \ |
||||||
|
+ apr_pool_userdata_setn((const void *)bb, key, NULL, pool); \ |
||||||
|
+ } \ |
||||||
|
+ else { \ |
||||||
|
+ apr_brigade_cleanup(bb); \ |
||||||
|
+ } \ |
||||||
|
+} while(0) |
||||||
|
+ |
||||||
|
+static void check_pipeline(conn_rec *c, apr_bucket_brigade *bb) |
||||||
|
{ |
||||||
|
if (c->keepalive != AP_CONN_CLOSE) { |
||||||
|
apr_status_t rv; |
||||||
|
- apr_bucket_brigade *bb = apr_brigade_create(c->pool, c->bucket_alloc); |
||||||
|
|
||||||
|
rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE, |
||||||
|
APR_NONBLOCK_READ, 1); |
||||||
|
@@ -245,11 +255,10 @@ static void check_pipeline(conn_rec *c) |
||||||
|
else { |
||||||
|
c->data_in_input_filters = 1; |
||||||
|
} |
||||||
|
- apr_brigade_destroy(bb); |
||||||
|
+ apr_brigade_cleanup(bb); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- |
||||||
|
AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) |
||||||
|
{ |
||||||
|
apr_bucket_brigade *bb; |
||||||
|
@@ -260,11 +269,13 @@ AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) |
||||||
|
* this bucket is destroyed, the request will be logged and |
||||||
|
* its pool will be freed |
||||||
|
*/ |
||||||
|
- bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc); |
||||||
|
+ RETRIEVE_BRIGADE_FROM_POOL(bb, "ap_process_request_after_handler_brigade", |
||||||
|
+ c->pool, c->bucket_alloc); |
||||||
|
b = ap_bucket_eor_create(r->connection->bucket_alloc, r); |
||||||
|
APR_BRIGADE_INSERT_HEAD(bb, b); |
||||||
|
|
||||||
|
ap_pass_brigade(r->connection->output_filters, bb); |
||||||
|
+ apr_brigade_cleanup(bb); |
||||||
|
|
||||||
|
/* From here onward, it is no longer safe to reference r |
||||||
|
* or r->pool, because r->pool may have been destroyed |
||||||
|
@@ -273,7 +284,7 @@ AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) |
||||||
|
|
||||||
|
if (c->cs) |
||||||
|
c->cs->state = CONN_STATE_WRITE_COMPLETION; |
||||||
|
- check_pipeline(c); |
||||||
|
+ check_pipeline(c, bb); |
||||||
|
AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, r->status); |
||||||
|
if (ap_extended_status) { |
||||||
|
ap_time_process_request(c->sbh, STOP_PREQUEST); |
||||||
|
@@ -363,7 +374,8 @@ void ap_process_request(request_rec *r) |
||||||
|
ap_process_async_request(r); |
||||||
|
|
||||||
|
if (!c->data_in_input_filters) { |
||||||
|
- bb = apr_brigade_create(c->pool, c->bucket_alloc); |
||||||
|
+ RETRIEVE_BRIGADE_FROM_POOL(bb, "ap_process_request_after_handler_brigade", |
||||||
|
+ c->pool, c->bucket_alloc); |
||||||
|
b = apr_bucket_flush_create(c->bucket_alloc); |
||||||
|
APR_BRIGADE_INSERT_HEAD(bb, b); |
||||||
|
rv = ap_pass_brigade(c->output_filters, bb); |
||||||
|
@@ -380,6 +392,7 @@ void ap_process_request(request_rec *r) |
||||||
|
"Timeout while writing data for URI %s to the" |
||||||
|
" client", r->unparsed_uri); |
||||||
|
} |
||||||
|
+ apr_brigade_cleanup(bb); |
||||||
|
} |
||||||
|
if (ap_extended_status) { |
||||||
|
ap_time_process_request(c->sbh, STOP_PREQUEST); |
Loading…
Reference in new issue