mod_auth_digest.c 69.1 KB
Newer Older
powelld's avatar
powelld committed
            if (resp->client)
                resp->client->nonce_count = 0;
        }
    }
    else if (conf->nonce_lifetime == 0 && resp->client) {
        const char *nonce = gen_nonce(r->pool, 0, resp->opaque, r->server,
                                      conf);
        nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", nonce, "\"", NULL);
        memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
    }
    /* else nonce never expires, hence no nextnonce */


    /* do rfc-2069 digest
     */
    if (!apr_is_empty_array(conf->qop_list) &&
        !strcasecmp(*(const char **)(conf->qop_list->elts), "none")
        && resp->message_qop == NULL) {
        /* use only RFC-2069 format */
        ai = nextnonce;
    }
    else {
        const char *resp_dig, *ha1, *a2, *ha2;

        /* 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,
                          (unsigned char *)apr_pstrcat(r->pool, ha1, ":",
                                                       resp->nonce, ":",
                                                       resp->nonce_count, ":",
                                                       resp->cnonce, ":",
                                                       resp->message_qop ?
                                                         resp->message_qop : "",
                                                       ":", ha2, NULL));

        /* assemble Authentication-Info header
         */
        ai = apr_pstrcat(r->pool,
                         "rspauth=\"", resp_dig, "\"",
                         nextnonce,
                         resp->cnonce ? ", cnonce=\"" : "",
                         resp->cnonce
                           ? ap_escape_quotes(r->pool, resp->cnonce)
                           : "",
                         resp->cnonce ? "\"" : "",
                         resp->nonce_count ? ", nc=" : "",
                         resp->nonce_count ? resp->nonce_count : "",
                         resp->message_qop ? ", qop=" : "",
                         resp->message_qop ? resp->message_qop : "",
                         NULL);
    }

    if (ai && ai[0]) {
        apr_table_mergen(r->headers_out,
                         (PROXYREQ_PROXY == r->proxyreq)
                             ? "Proxy-Authentication-Info"
                             : "Authentication-Info",
                         ai);
    }

    return OK;
}

static void register_hooks(apr_pool_t *p)
{
    static const char * const cfgPost[]={ "http_core.c", NULL };
    static const char * const parsePre[]={ "mod_proxy.c", NULL };

    ap_hook_pre_config(pre_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_config(initialize_module, NULL, cfgPost, APR_HOOK_MIDDLE);
    ap_hook_child_init(initialize_child, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_read_request(parse_hdr_and_update_nc, parsePre, NULL, APR_HOOK_MIDDLE);
    ap_hook_check_authn(authenticate_digest_user, NULL, NULL, APR_HOOK_MIDDLE,
                        AP_AUTH_INTERNAL_PER_CONF);

    ap_hook_fixups(add_auth_info, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_note_auth_failure(hook_note_digest_auth_failure, NULL, NULL,
                              APR_HOOK_MIDDLE);

}

AP_DECLARE_MODULE(auth_digest) =
{
    STANDARD20_MODULE_STUFF,
    create_digest_dir_config,   /* dir config creater */
    NULL,                       /* dir merger --- default is to override */
    NULL,                       /* server config */
    NULL,                       /* merge server config */
    digest_cmds,                /* command table */
    register_hooks              /* register hooks */
};