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

📄 mod_auth_digest.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* 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 const char *get_hash(request_rec *r, const char *user,                            const char *realm, const char *auth_pwfile){    ap_configfile_t *f;    char l[MAX_STRING_LEN];    const char *rpw;    char *w, *x;    apr_status_t sts;    if ((sts = ap_pcfg_openfile(&f, r->pool, auth_pwfile)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, sts, r,                      "Digest: Could not open password file: %s", auth_pwfile);        return NULL;    }    while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {        if ((l[0] == '#') || (!l[0])) {            continue;        }        rpw = l;        w = ap_getword(r->pool, &rpw, ':');        x = ap_getword(r->pool, &rpw, ':');        if (x && w && !strcmp(user, w) && !strcmp(realm, x)) {            ap_cfg_closefile(f);            return apr_pstrdup(r->pool, rpw);        }    }    ap_cfg_closefile(f);    return NULL;}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. * * 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;    /* 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);

⌨️ 快捷键说明

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