⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_auth_digest.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * If they return DECLINED, and all other modules also decline, that's * treated by the server core as a configuration error, logged and * reported as such. *//* Determine user ID, and check if the attributes are correct, if it * really is that user, if the nonce is correct, etc. */static int authenticate_digest_user(request_rec *r){    digest_config_rec *conf;    digest_header_rec *resp;    request_rec       *mainreq;    const char        *t;    int                res;    authn_status       return_code;    /* do we require Digest auth for this URI? */    if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) {        return DECLINED;    }    if (!ap_auth_name(r)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: need AuthName: %s", r->uri);        return HTTP_INTERNAL_SERVER_ERROR;    }    /* get the client response and mark */    mainreq = r;    while (mainreq->main != NULL) {        mainreq = mainreq->main;    }    while (mainreq->prev != NULL) {        mainreq = mainreq->prev;    }    resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config,                                                      &auth_digest_module);    resp->needed_auth = 1;    /* get our conf */    conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,                                                      &auth_digest_module);    /* check for existence and syntax of Auth header */    if (resp->auth_hdr_sts != VALID) {        if (resp->auth_hdr_sts == NOT_DIGEST) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: client used wrong authentication scheme "                          "`%s': %s", resp->scheme, r->uri);        }        else if (resp->auth_hdr_sts == INVALID) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: missing user, realm, nonce, uri, digest, "                          "cnonce, or nonce_count in authorization header: %s",                          r->uri);        }        /* else (resp->auth_hdr_sts == NO_HEADER) */        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    r->user         = (char *) resp->username;    r->ap_auth_type = (char *) "Digest";    /* check the auth attributes */    if (strcmp(resp->uri, resp->raw_request_uri)) {        /* Hmm, the simple match didn't work (probably a proxy modified the         * request-uri), so lets do a more sophisticated match         */        apr_uri_t r_uri, d_uri;        copy_uri_components(&r_uri, resp->psd_request_uri, r);        if (apr_uri_parse(r->pool, resp->uri, &d_uri) != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: invalid uri <%s> in Authorization header",                          resp->uri);            return HTTP_BAD_REQUEST;        }        if (d_uri.hostname) {            ap_unescape_url(d_uri.hostname);        }        if (d_uri.path) {            ap_unescape_url(d_uri.path);        }        if (d_uri.query) {            ap_unescape_url(d_uri.query);        }        else if (r_uri.query) {            /* MSIE compatibility hack.  MSIE has some RFC issues - doesn't             * include the query string in the uri Authorization component             * or when computing the response component.  the second part             * works out ok, since we can hash the header and get the same             * result.  however, the uri from the request line won't match             * the uri Authorization component since the header lacks the             * query string, leaving us incompatable with a (broken) MSIE.             *             * the workaround is to fake a query string match if in the proper             * environment - BrowserMatch MSIE, for example.  the cool thing             * is that if MSIE ever fixes itself the simple match ought to             * work and this code won't be reached anyway, even if the             * environment is set.             */            if (apr_table_get(r->subprocess_env,                              "AuthDigestEnableQueryStringHack")) {                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Digest: "                              "applying AuthDigestEnableQueryStringHack "                              "to uri <%s>", resp->raw_request_uri);               d_uri.query = r_uri.query;            }        }        if (r->method_number == M_CONNECT) {            if (!r_uri.hostinfo || strcmp(resp->uri, r_uri.hostinfo)) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                              "Digest: uri mismatch - <%s> does not match "                              "request-uri <%s>", resp->uri, r_uri.hostinfo);                return HTTP_BAD_REQUEST;            }        }        else if (            /* check hostname matches, if present */            (d_uri.hostname && d_uri.hostname[0] != '\0'              && strcasecmp(d_uri.hostname, r_uri.hostname))            /* check port matches, if present */            || (d_uri.port_str && d_uri.port != r_uri.port)            /* check that server-port is default port if no port present */            || (d_uri.hostname && d_uri.hostname[0] != '\0'                && !d_uri.port_str && r_uri.port != ap_default_port(r))            /* check that path matches */            || (d_uri.path != r_uri.path                /* either exact match */                && (!d_uri.path || !r_uri.path                    || strcmp(d_uri.path, r_uri.path))                /* or '*' matches empty path in scheme://host */                && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname                    && d_uri.path[0] == '*' && d_uri.path[1] == '\0'))            /* check that query matches */            || (d_uri.query != r_uri.query                && (!d_uri.query || !r_uri.query                    || strcmp(d_uri.query, r_uri.query)))            ) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: uri mismatch - <%s> does not match "                          "request-uri <%s>", resp->uri, resp->raw_request_uri);            return HTTP_BAD_REQUEST;        }    }    if (resp->opaque && resp->opaque_num == 0) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: received invalid opaque - got `%s'",                      resp->opaque);        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    if (strcmp(resp->realm, conf->realm)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: realm mismatch - got `%s' but expected `%s'",                      resp->realm, conf->realm);        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    if (resp->algorithm != NULL        && strcasecmp(resp->algorithm, "MD5")        && strcasecmp(resp->algorithm, "MD5-sess")) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: unknown algorithm `%s' received: %s",                      resp->algorithm, r->uri);        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    return_code = get_hash(r, r->user, conf);    if (return_code == AUTH_USER_NOT_FOUND) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: user `%s' in realm `%s' not found: %s",                      r->user, conf->realm, r->uri);        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    else if (return_code == AUTH_USER_FOUND) {        /* we have a password, so continue */    }    else if (return_code == AUTH_DENIED) {        /* authentication denied in the provider before attempting a match */        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: user `%s' in realm `%s' denied by provider: %s",                      r->user, conf->realm, r->uri);        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    else {        /* AUTH_GENERAL_ERROR (or worse)         * We'll assume that the module has already said what its error         * was in the logs.         */        return HTTP_INTERNAL_SERVER_ERROR;    }    if (resp->message_qop == NULL) {        /* old (rfc-2069) style digest */        if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: user %s: password mismatch: %s", r->user,                          r->uri);            note_digest_auth_failure(r, conf, resp, 0);            return HTTP_UNAUTHORIZED;        }    }    else {        const char *exp_digest;        int match = 0, idx;        for (idx = 0; conf->qop_list[idx] != NULL; idx++) {            if (!strcasecmp(conf->qop_list[idx], resp->message_qop)) {                match = 1;                break;            }        }        if (!match            && !(conf->qop_list[0] == NULL                 && !strcasecmp(resp->message_qop, "auth"))) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: invalid qop `%s' received: %s",                          resp->message_qop, r->uri);            note_digest_auth_failure(r, conf, resp, 0);            return HTTP_UNAUTHORIZED;        }        exp_digest = new_digest(r, resp, conf);        if (!exp_digest) {            /* we failed to allocate a client struct */            return HTTP_INTERNAL_SERVER_ERROR;        }        if (strcmp(resp->digest, exp_digest)) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "Digest: user %s: password mismatch: %s", r->user,                          r->uri);            note_digest_auth_failure(r, conf, resp, 0);            return HTTP_UNAUTHORIZED;        }    }    if (check_nc(r, resp, conf) != OK) {        note_digest_auth_failure(r, conf, resp, 0);        return HTTP_UNAUTHORIZED;    }    /* Note: this check is done last so that a "stale=true" can be       generated if the nonce is old */    if ((res = check_nonce(r, resp, conf))) {        return res;    }    return OK;}/* * Authorization-Info header code */#ifdef SEND_DIGESTstatic const char *hdr(const apr_table_t *tbl, const char *name){    const char *val = apr_table_get(tbl, name);    if (val) {        return val;    }    else {        return "";    }}#endifstatic int add_auth_info(request_rec *r){    const digest_config_rec *conf =                (digest_config_rec *) ap_get_module_config(r->per_dir_config,                                                           &auth_digest_module);    digest_header_rec *resp =                (digest_header_rec *) ap_get_module_config(r->request_config,                                                           &auth_digest_module);    const char *ai = NULL, *digest = NULL, *nextnonce = "";    if (resp == NULL || !resp->needed_auth || conf == NULL) {        return OK;    }    /* rfc-2069 digest     */    if (resp->message_qop == NULL) {        /* old client, so calc rfc-2069 digest */#ifdef SEND_DIGEST        /* most of this totally bogus because the handlers don't set the         * headers until the final handler phase (I wonder why this phase         * is called fixup when there's almost nothing you can fix up...)         *         * Because it's basically impossible to get this right (e.g. the         * Content-length is never set yet when we get here, and we can't         * calc the entity hash) it's best to just leave this #def'd out.         */        char date[APR_RFC822_DATE_LEN];        apr_rfc822_date(date, r->request_time);        char *entity_info =            ap_md5(r->pool,                   (unsigned char *) apr_pstrcat(r->pool, resp->raw_request_uri,                       ":",                       r->content_type ? r->content_type : ap_default_type(r), ":",                       hdr(r->headers_out, "Content-Length"), ":",                       r->content_encoding ? r->content_encoding : "", ":",                       hdr(r->headers_out, "Last-Modified"), ":",                       r->no_cache && !apr_table_get(r->headers_out, "Expires") ?                            date :                            hdr(r->headers_out, "Expires"),                       NULL));        digest =            ap_md5(r->pool,                   (unsigned char *)apr_pstrcat(r->pool, conf->ha1, ":",                                               resp->nonce, ":",                                               r->method, ":",                                               date, ":",                                               entity_info, ":",                                               ap_md5(r->pool, (unsigned char *) ""), /* H(entity) - TBD */                                               NULL));#endif    }    /* setup nextnonce     */    if (conf->nonce_lifetime > 0) {        /* send nextnonce if current nonce will expire in less than 30 secs */        if ((r->request_time - resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) {            nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"",                                   gen_nonce(r->pool, r->request_time,                                             resp->opaque, r->server, conf),                                   "\"", NULL);            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 (conf->qop_list[0] && !strcasecmp(conf->qop_list[0], "none")        && resp->message_qop == NULL) {        /* use only RFC-2069 format */        if (digest) {            ai = apr_pstrcat(r->pool, "digest=\"", digest, "\"", nextnonce,NULL);        }        else {            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,                              "Digest: internal error: 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -