Commit e22b7e81 authored by Yann Ylavic's avatar Yann Ylavic
Browse files

Follow up to r1821624: sync with 2.4.x.

parents 91f92d79 94cc4673
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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]
+56 −33
Original line number Diff line number Diff line
@@ -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
+4 −1
Original line number Diff line number Diff line
@@ -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
+22 −0
Original line number Diff line number Diff line
@@ -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: */
@@ -102,6 +104,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
+51 −190
Original line number Diff line number Diff line
@@ -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;
@@ -113,6 +107,7 @@ typedef struct digest_config_struct {
#define NONCE_LEN       (int )(NONCE_TIME_LEN + NONCE_HASH_LEN)

#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 !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) {
        return rv;
            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;
@@ -1167,92 +1158,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;
    }

    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);
    }
    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;
        }

        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);
        }
        ha2 = ap_md5(r->pool, (const unsigned char *)a2);

        resp_dig = ap_md5(r->pool,
Loading