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

📄 mod_auth_digest.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }    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) */static const char *ltox(apr_pool_t *p, unsigned long num){    if (num != 0) {        return apr_psprintf(p, "%lx", num);    }    else {        return "";    }}static void note_digest_auth_failure(request_rec *r,                                     const digest_config_rec *conf,                                     digest_header_rec *resp, int stale){    const char   *qop, *opaque, *opaque_param, *domain, *nonce;    int           cnt;    /* Setup qop */    if (conf->qop_list[0] == NULL) {        qop = ", qop=\"auth\"";    }    else if (!strcasecmp(conf->qop_list[0], "none")) {        qop = "";    }    else {        qop = apr_pstrcat(r->pool, ", qop=\"", conf->qop_list[0], NULL);        for (cnt = 1; conf->qop_list[cnt] != NULL; cnt++) {            qop = apr_pstrcat(r->pool, qop, ",", conf->qop_list[cnt], NULL);        }        qop = apr_pstrcat(r->pool, qop, "\"", NULL);    }    /* Setup opaque */    if (resp->opaque == NULL) {        /* new client */        if ((conf->check_nc || conf->nonce_lifetime == 0             || !strcasecmp(conf->algorithm, "MD5-sess"))            && (resp->client = gen_client(r)) != NULL) {            opaque = ltox(r->pool, resp->client->key);        }        else {            opaque = "";                /* opaque not needed */        }    }    else if (resp->client == NULL) {        /* client info was gc'd */        resp->client = gen_client(r);        if (resp->client != NULL) {            opaque = ltox(r->pool, resp->client->key);            stale = 1;            client_list->num_renewed++;        }        else {            opaque = "";                /* ??? */        }    }    else {        opaque = resp->opaque;        /* we're generating a new nonce, so reset the nonce-count */        resp->client->nonce_count = 0;    }    if (opaque[0]) {        opaque_param = apr_pstrcat(r->pool, ", opaque=\"", opaque, "\"", NULL);    }    else {        opaque_param = NULL;    }    /* Setup nonce */    nonce = gen_nonce(r->pool, r->request_time, opaque, r->server, conf);    if (resp->client && conf->nonce_lifetime == 0) {        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     * unneccessarily (it's usually > 200 bytes!).     */    /* don't send domain     * - for proxy requests     * - if it's no specified     */    if (r->proxyreq || !conf->uri_list) {        domain = NULL;    }    else {        domain = conf->uri_list;    }    apr_table_mergen(r->err_headers_out,                     (PROXYREQ_PROXY == r->proxyreq)                         ? "Proxy-Authenticate" : "WWW-Authenticate",                     apr_psprintf(r->pool, "Digest realm=\"%s\", "                                  "nonce=\"%s\", algorithm=%s%s%s%s%s",                                  ap_auth_name(r), nonce, conf->algorithm,                                  opaque_param ? opaque_param : "",                                  domain ? domain : "",                                  stale ? ", stale=true" : "", qop));}/* * Authorization header verification code */static authn_status get_hash(request_rec *r, const char *user,                             digest_config_rec *conf){    authn_status auth_result;    char *password;    authn_provider_list *current_provider;    current_provider = conf->providers;    do {        const authn_provider *provider;        /* For now, if a provider isn't set, we'll be nice and use the file         * provider.         */        if (!current_provider) {            provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP,                                          AUTHN_DEFAULT_PROVIDER, "0");            if (!provider || !provider->get_realm_hash) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                              "No Authn provider configured");                auth_result = AUTH_GENERAL_ERROR;                break;            }            apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER);        }        else {            provider = current_provider->provider;            apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name);        }        /* We expect the password to be md5 hash of user:realm:password */        auth_result = provider->get_realm_hash(r, user, conf->realm,                                               &password);        apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);        /* Something occured.  Stop checking. */        if (auth_result != AUTH_USER_NOT_FOUND) {            break;        }        /* If we're not really configured for providers, stop now. */        if (!conf->providers) {           break;        }        current_provider = current_provider->next;    } while (current_provider);    if (auth_result == AUTH_USER_FOUND) {        conf->ha1 = password;    }    return auth_result;}static int check_nc(const request_rec *r, const digest_header_rec *resp,                    const digest_config_rec *conf){    unsigned long nc;    const char *snc = resp->nonce_count;    char *endptr;    if (!conf->check_nc || !client_shm) {        return OK;    }    nc = strtol(snc, &endptr, 16);    if (endptr < (snc+strlen(snc)) && !apr_isspace(*endptr)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: invalid nc %s received - not a number", snc);        return !OK;    }    if (!resp->client) {        return !OK;    }    if (nc != resp->client->nonce_count) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: Warning, possible replay attack: nonce-count "                      "check failed: %lu != %lu", nc,                      resp->client->nonce_count);        return !OK;    }    return OK;}static int check_nonce(request_rec *r, digest_header_rec *resp,                       const digest_config_rec *conf){    apr_time_t dt;    int len;    time_rec nonce_time;    char tmp, hash[NONCE_HASH_LEN+1];    if (strlen(resp->nonce) != NONCE_LEN) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: invalid nonce %s received - length is not %d",                      resp->nonce, NONCE_LEN);        note_digest_auth_failure(r, conf, resp, 1);        return HTTP_UNAUTHORIZED;    }    tmp = resp->nonce[NONCE_TIME_LEN];    resp->nonce[NONCE_TIME_LEN] = '\0';    len = apr_base64_decode_binary(nonce_time.arr, resp->nonce);    gen_nonce_hash(hash, resp->nonce, resp->opaque, r->server, conf);    resp->nonce[NONCE_TIME_LEN] = tmp;    resp->nonce_time = nonce_time.time;    if (strcmp(hash, resp->nonce+NONCE_TIME_LEN)) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: invalid nonce %s received - hash is not %s",                      resp->nonce, hash);        note_digest_auth_failure(r, conf, resp, 1);        return HTTP_UNAUTHORIZED;    }    dt = r->request_time - nonce_time.time;    if (conf->nonce_lifetime > 0 && dt < 0) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Digest: invalid nonce %s received - user attempted "                      "time travel", resp->nonce);        note_digest_auth_failure(r, conf, resp, 1);        return HTTP_UNAUTHORIZED;    }    if (conf->nonce_lifetime > 0) {        if (dt > conf->nonce_lifetime) {            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0,r,                          "Digest: user %s: nonce expired (%.2f seconds old "                          "- max lifetime %.2f) - sending new nonce",                          r->user, (double)apr_time_sec(dt),                          (double)apr_time_sec(conf->nonce_lifetime));            note_digest_auth_failure(r, conf, resp, 1);            return HTTP_UNAUTHORIZED;        }    }    else if (conf->nonce_lifetime == 0 && resp->client) {        if (memcmp(resp->client->last_nonce, resp->nonce, NONCE_LEN)) {            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,                          "Digest: user %s: one-time-nonce mismatch - sending "                          "new nonce", r->user);            note_digest_auth_failure(r, conf, resp, 1);            return HTTP_UNAUTHORIZED;        }    }    /* else (lifetime < 0) => never expires */    return OK;}/* The actual MD5 code... whee *//* RFC-2069 */static const char *old_digest(const request_rec *r,                              const digest_header_rec *resp, const char *ha1){    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));}/* RFC-2617 */static const char *new_digest(const request_rec *r,                              digest_header_rec *resp,                              const digest_config_rec *conf){    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,                  (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,                                               ":", resp->nonce_count, ":",                                               resp->cnonce, ":",                                               resp->message_qop, ":", ha2,                                               NULL));}static void copy_uri_components(apr_uri_t *dst,                                apr_uri_t *src, request_rec *r) {    if (src->scheme && src->scheme[0] != '\0') {        dst->scheme = src->scheme;    }    else {        dst->scheme = (char *) "http";    }    if (src->hostname && src->hostname[0] != '\0') {        dst->hostname = apr_pstrdup(r->pool, src->hostname);        ap_unescape_url(dst->hostname);    }    else {        dst->hostname = (char *) ap_get_server_name(r);    }    if (src->port_str && src->port_str[0] != '\0') {        dst->port = src->port;    }    else {        dst->port = ap_get_server_port(r);    }    if (src->path && src->path[0] != '\0') {        dst->path = apr_pstrdup(r->pool, src->path);        ap_unescape_url(dst->path);    }    else {        dst->path = src->path;    }    if (src->query && src->query[0] != '\0') {        dst->query = apr_pstrdup(r->pool, src->query);        ap_unescape_url(dst->query);    }    else {        dst->query = src->query;    }    dst->hostinfo = src->hostinfo;}/* These functions return 0 if client is OK, and proper error status * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we * couldn't figure out how to tell if the client is authorized or not.

⌨️ 快捷键说明

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