]> granicus.if.org Git - apache/commitdiff
Actually use the secret when generating nonces.
authorStefan Fritsch <sf@apache.org>
Wed, 12 Jun 2013 19:34:19 +0000 (19:34 +0000)
committerStefan Fritsch <sf@apache.org>
Wed, 12 Jun 2013 19:34:19 +0000 (19:34 +0000)
This change may cause problems if used with round robin load balancers.
Before it is backported, we should add a directive to use a user specified
secret.

PR: 54637

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1492395 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/aaa/mod_auth_digest.c

diff --git a/CHANGES b/CHANGES
index 8bc8e0263b6a4a9e3466b5ce6e528a5a01cc685d..1983db36aa32f919672ba5d39db372ccf652d480 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) 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_cache_socache: Use the name of the socache implementation when performing
      a lookup rather than using the raw arguments. [Martin Ksellmann
      <martin@ksellmann.de>]
index 2420f7ea0c88f9178c5519cc782531f9ca389512..81d1231ab0977c6c68437dd11b25d04ecc4367f7 100644 (file)
@@ -106,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 POOL_USERDATA_ID    "mod_auth_digest"
 
 
 /* client list definitions */
@@ -163,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 */
 
@@ -221,28 +222,43 @@ static apr_status_t cleanup_tables(void *not_used)
     return APR_SUCCESS;
 }
 
-static apr_status_t initialize_secret(server_rec *s)
+/*
+ * @param pool pool for userdata
+ * @param s server rec for logging, may be NULL
+ */
+static apr_status_t initialize_secret(apr_pool_t *pool, server_rec *s)
 {
     apr_status_t status;
+    void *userdata;
+
+    apr_pool_userdata_get(&userdata, POOL_USERDATA_ID, pool);
+    if (userdata != NULL) {
+        secret = userdata;
+        return APR_SUCCESS;
+    }
 
-    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, APLOGNO(01757)
-                 "generating secret for digest authentication ...");
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01757)
+                 "generating secret for digest authentication");
+
+    secret = apr_palloc(pool, SECRET_LEN);
 
 #if APR_HAS_RANDOM
-    status = apr_generate_random_bytes(secret, sizeof(secret));
+    status = apr_generate_random_bytes(secret, SECRET_LEN);
 #else
-#error APR random number support is missing; you probably need to install the truerand library.
+#error APR random number support is missing
 #endif
 
     if (status != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_CRIT, status, s, APLOGNO(01758)
                      "error generating secret");
+        secret = NULL;
         return status;
     }
 
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01759) "done");
+    apr_pool_userdata_set(secret, POOL_USERDATA_ID, apr_pool_cleanup_null,
+                          pool);
 
-    return APR_SUCCESS;
+    return status;
 }
 
 static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
@@ -369,9 +385,13 @@ 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) {
+    /*
+     * If we haven't initialized the secret yet, we need to do it now in case
+     * the module is used in .htaccess.
+     */
+    if (secret == NULL
+        && initialize_secret(s->process->pool, s) != APR_SUCCESS)
         return !OK;
-    }
 
 #if APR_HAS_SHARED_MEMORY
     /* Note: this stuff is currently fixed for the lifetime of the server,
@@ -453,6 +473,21 @@ 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;
+    int i;
+
+    /* pass NULL because cmd->server may not have a valid log config yet */
+    if (secret == NULL
+        && initialize_secret(cmd->server->process->pool, NULL) != APR_SUCCESS)
+        return "Could not get random numbers for secret";
+
+#ifdef AP_DEBUG
+    /* 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
@@ -466,7 +501,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));