📄 htaabrow.c
字号:
HTDigest_update (&MdCtx, ":", 1); } HTDigest_update (&MdCtx, HA2Hex, HASHHEXLEN); HTDigest_final (RespHash, &MdCtx); CvtHex (RespHash, Response);} /*** Code derived from draft-ietf-http-authentication-03 ends here*//*** Make digest authentication scheme credentials and register this** information in the request object as credentials. They will then** be included in the request header. An example is**** "Digest nonce:cnonce:blahblahblhah:digest-response"**** The function can both create normal and proxy credentials** Returns HT_OK or HT_ERROR*/PRIVATE BOOL digest_credentials (HTRequest * request, HTDigest * digest){ if (request && digest && digest->realm) { char * realm = (char *) digest->realm; char * uri; char * method = (char *) HTMethod_name (HTRequest_method (request)); char * cleartext = NULL; char nc[9]; HASHHEX HA1; HASHHEX HA2; HASHHEX response; /* @@ maybe optimize all my reallocs by preallocating the memory */ if (digest->proxy) uri = HTRequest_proxy(request); else uri = HTAnchor_address( (HTAnchor*)HTRequest_anchor(request)); /* increment the nonce counter */ digest->nc++; sprintf (nc, "%08lx", digest->nc); add_param (&cleartext, "username", digest->uid, YES); add_param (&cleartext, "realm", realm, YES); add_param (&cleartext, "nonce", digest->nonce, YES); add_param (&cleartext, "uri", uri, YES); /* @@@ no support for auth-int yet */ if (digest->qop) { add_param (&cleartext, "qop", "auth", NO); add_param (&cleartext, "nc", nc, NO); add_param (&cleartext, "cnonce", digest->cnonce, YES); } /* compute the response digest */ /* @@@ md5 hard coded, change it to something from the answer, md5-sess, etc */ DigestCalcHA1 (digest->algorithm, "md5", digest->uid, realm, digest->pw, digest->nonce, digest->cnonce, HA1); DigestCalcResponse (digest->algorithm, HA1, digest->nonce, nc, digest->cnonce, digest->qop, method, uri, HA2, response); add_param (&cleartext, "response", response, NO); add_param (&cleartext, "opaque", digest->opaque, NO); /* Create the credentials and assign them to the request object */ { int cr_len = strlen ("Digest") + strlen (cleartext) + 3; char * cookie = (char *) HT_MALLOC(cr_len+1); if (!cookie) HT_OUTOFMEM("digest_credentials"); strcpy(cookie, "Digest "); strcat (cookie, cleartext); HTTRACE(AUTH_TRACE, "Digest Cookie `%s\'\n" _ cookie); /* Check whether it is proxy or normal credentials */ if (digest->proxy) HTRequest_addCredentials(request, "Proxy-Authorization", cookie); else HTRequest_addCredentials(request, "Authorization", cookie); HT_FREE(cookie); } HT_FREE(cleartext); return HT_OK; } return HT_ERROR;}/* HTDigest_generate** ----------------** This function generates "digest" credentials for the challenge found in** the authentication information base for this request. The result is** stored as an association list in the request object.** This is a callback function for the AA handler.*/PUBLIC int HTDigest_generate (HTRequest * request, void * context, int mode){ HTDigest * digest = (HTDigest *) context; BOOL proxy = mode==HT_NO_PROXY_ACCESS ? YES : NO; if (request) { const char * realm = HTRequest_realm(request); /* ** If we were asked to explicitly ask the user again */ if (mode == HT_REAUTH || mode == HT_PROXY_REAUTH) digest->retry = YES; /* ** If we don't have a digest context then add a new one to the tree. ** We use different trees for normal and proxy authentication */ if (!digest) { digest = HTDigest_new(); if (proxy) { char * url = HTRequest_proxy(request); digest->proxy = YES; HTAA_updateNode(proxy, DIGEST_AUTH, realm, url, digest); } else { char * url = HTAnchor_address((HTAnchor*)HTRequest_anchor(request)); HTAA_updateNode(proxy, DIGEST_AUTH, realm, url, digest); HT_FREE(url); } } /* ** If we have a set of credentials (or the user provides a new set) ** then store it in the request object as the credentials */ if ((digest->retry && prompt_digest_user(request, realm, digest) == HT_OK) || (!digest->retry && digest->uid)) { /* @@@ here we should generate a new cnonce value */ digest->cnonce = "012345678"; digest->retry = NO; return digest_credentials(request, digest); } else { char * url = HTAnchor_address((HTAnchor*)HTRequest_anchor(request)); if (proxy) HTAA_deleteNode(proxy, DIGEST_AUTH, realm, url); else HTAA_deleteNode(proxy, DIGEST_AUTH, realm, url); HT_FREE(url); return HT_ERROR; } } return HT_OK;}/* HTDigest_parse** -------------** This function parses the contents of a "digest" challenge ** and stores the challenge in our authentication information datebase.** We also store the realm in the request object which will help finding** the right set of credentials to generate.** The function is a callback function for the AA handler.*/PUBLIC int HTDigest_parse (HTRequest * request, HTResponse * response, void * context, int status){ HTAssocList * challenge = HTResponse_challenge(response); HTDigest * digest = NULL; BOOL proxy = status==HT_NO_PROXY_ACCESS ? YES : NO; if (request && challenge) { char * p = HTAssocList_findObject(challenge, DIGEST_AUTH); char * realm = HTNextField(&p); char * rm = HTNextField(&p); char * value = NULL; char * token = NULL; char * uris = NULL; /* ** If valid challenge then make a template for the resource and ** store this information in our authentication URL Tree */ if (realm && !strcasecomp(realm, "realm") && rm) { HTTRACE(AUTH_TRACE, "Digest Parse. Realm `%s\' found\n" _ rm); HTRequest_setRealm(request, rm); /* ** If we are in proxy mode then add the proxy - not the final URL */ if (proxy) { char * url = HTRequest_proxy(request); HTTRACE(AUTH_TRACE, "Digest Parse. Proxy authentication\n"); digest = (HTDigest *) HTAA_updateNode(proxy, DIGEST_AUTH, rm, url, NULL); /* if the previous authentication failed, then try again */ if (HTRequest_AAretrys (request) > 1 && status == HT_NO_ACCESS && digest) digest->retry = YES; } else { char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); char * tmplate = make_template(url); digest = (HTDigest *) HTAA_updateNode(proxy, DIGEST_AUTH, rm, tmplate, NULL); /* if the previous authentication failed, then try again */ if (HTRequest_AAretrys (request) > 1 && status == HT_NO_ACCESS && digest) digest->retry = YES; HT_FREE(tmplate); HT_FREE(url); } } else { HTTRACE(AUTH_TRACE, "Digest Parse. Missing or incomplete realm\n"); return HT_ERROR; } /* if we get here it's because there's no digest */ /* we parse the digest parameters from the challenge */ if (digest) { /* it's an old digest, so we clean all in it except for the uid and the password, hoping that the server send back that data */ HTDigest_reset (digest); } else { /* it's a brand new digest */ digest = HTDigest_new(); StrAllocCopy (digest->realm, rm); } /* ** Search through the set of parameters in the digest header. ** If valid challenge then make a template for the resource and ** store this information in our authentication URL Tree */ while ((token = HTNextField(&p))) { if (!strcasecomp(token, "domain")) { if ((value = HTNextField(&p))) uris = value; } else if (!strcasecomp(token, "nonce")) { if ((value = HTNextField(&p))) StrAllocCopy(digest->nonce, value); } else if (!strcasecomp(token, "opaque")) { if ((value = HTNextField(&p))) StrAllocCopy(digest->opaque, value); } else if (!strcasecomp(token, "qop")) { /* split the qop */ if ((value = HTNextField(&p))) StrAllocCopy(digest->qop, value); } else if (!strcasecomp(token, "stale")) { if ((value = HTNextField(&p)) && !strcasecomp(value, "true")) { /* only true if we already had a digest with uid and pw info */ if (digest->uid && digest->pw) { digest->stale = YES; digest->retry = NO; } } } else if (!strcasecomp(token, "algorithm")) { if ((value = HTNextField(&p)) && strcasecomp(value, "md5")) { /* ** We only support MD5 for the moment */ HTTRACE(AUTH_TRACE, "Digest Parse Unknown algorithm `%s\'\n" _ value); HTDigest_delete(digest); return HT_ERROR; } else digest->algorithm = HTDaMD5; } } if (digest->stale) return HT_OK; else if (digest->uid || digest->pw) { /* ** For some reason there was no stale nonce header and the ** authentication failed so we have to ask the user if we should ** try again. It may be because the user typed the wrong user name ** and password */ HTAlertCallback * prompt = HTAlert_find(HT_A_CONFIRM); /* ** Do we have a method registered for prompting the user whether ** we should retry */ if (prompt) { int code = proxy ? HT_MSG_RETRY_PROXY_AUTH : HT_MSG_RETRY_AUTHENTICATION; if ((*prompt)(request, HT_A_CONFIRM, code, NULL, NULL, NULL) != YES) return HT_ERROR; return HT_OK; } return HT_ERROR; } /* ** It's the first time we go this way, so we check the domain field to ** create the digest node entries for each URI. */ if (!uris) { if (proxy) { /* we ignore the domain */ char * location = HTRequest_proxy(request); HTTRACE(AUTH_TRACE, "Digest Parse Proxy authentication\n"); HTAA_updateNode(proxy, DIGEST_AUTH, rm, location, digest); } else { char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); char * tmplate = make_template(url); HTAA_updateNode(proxy, DIGEST_AUTH, rm, tmplate, digest); HT_FREE(url); HT_FREE(tmplate); } } else { char * base_url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); char * domain_url; char * full_url; while ((domain_url = HTNextField (&uris))) { /* complete the URL if it's an absolute one */ full_url = HTParse (domain_url, base_url, PARSE_ALL); digest->references++; if (proxy) { HTTRACE(AUTH_TRACE, "Digest Parse Proxy authentication\n"); HTAA_updateNode(proxy, DIGEST_AUTH, rm, full_url, digest); } else { char * tmplate = make_template(full_url); HTAA_updateNode (proxy, DIGEST_AUTH, rm, tmplate, digest); HT_FREE (tmplate); } HT_FREE (full_url); } HT_FREE (base_url); } return HT_OK; } HTTRACE(AUTH_TRACE, "Auth........ No challenges found\n"); return HT_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -