📄 htaabrow.c
字号:
char * tmplate = make_template(url); basic = (HTBasic *) HTAA_updateNode(proxy, BASIC_AUTH, rm, tmplate, NULL); /* if the previous authentication failed, then try again */ if (HTRequest_AAretrys (request) > 1 && status == HT_NO_ACCESS && basic) basic->retry = YES; HT_FREE(url); HT_FREE(tmplate); } } /* ** For some reason 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 */ if (basic && basic->retry) { 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; } HTTRACE(AUTH_TRACE, "Auth........ No challenges found\n"); return HT_ERROR;}/* ------------------------------------------------------------------------- *//* Digest Authentication *//* ------------------------------------------------------------------------- *//*** Prompt the user for username and password.** Returns YES if user name was typed in, else NO*/PRIVATE int prompt_digest_user (HTRequest * request, const char * realm, HTDigest * digest){ HTAlertCallback * cbf = HTAlert_find(HT_A_USER_PW); /* If no method for prompting the user then we might as well give up */ if (!cbf) return HT_ERROR; /* Otherwise go ahead and ask the user */ if (request) { HTAlertPar * reply = HTAlert_newReply(); int msg = digest->proxy ? HT_MSG_PROXY_UID : HT_MSG_UID; BOOL res = (*cbf)(request, HT_A_USER_PW, msg, digest->uid, (char *) realm, reply); if (res) { HT_FREE(digest->uid); HT_FREE(digest->pw); digest->uid = HTAlert_replyMessage(reply); digest->pw = HTAlert_replySecret(reply); } HTAlert_deleteReply(reply); return res ? HT_OK : HT_ERROR; } return HT_OK;}PRIVATE HTDigest * HTDigest_new(){ HTDigest * me = NULL; if ((me = (HTDigest *) HT_CALLOC(1, sizeof(HTDigest))) == NULL) HT_OUTOFMEM("HTDigest_new"); me->algorithm = HTDaMD5; /* use md5 as a default value */ me->retry = YES; /* Ask the first time through */ return me;}/* HTDigest_delete** --------------** Deletes a "digest" information object** A single object may be registered multiple places in the URL tree.** We keep a simple reference count on the object so that we know** when to delete the object.*/PUBLIC int HTDigest_delete (void * context){ HTDigest * digest = (HTDigest *) context; if (digest) { if (digest->references <= 0) { HT_FREE(digest->uid); HT_FREE(digest->pw); HT_FREE(digest->realm); HT_FREE(digest->cnonce); HT_FREE(digest->nonce); HT_FREE(digest->opaque); HT_FREE(digest->qop); HT_FREE(digest); return YES; } else digest->references--; } return NO;}/* HTDigest_reset** --------------** When digest authentication fails, we simulate a new digest by** erasing the old one, but keeping the uid and the password. This is** so that we can take into account the stale nonce protocol, without** prompting the user for a new password.*/PRIVATE int HTDigest_reset (HTDigest *digest){ if (digest) { digest->nc = 0l; digest->stale = 0; digest->retry = YES; HT_FREE(digest->cnonce); HT_FREE(digest->nonce); HT_FREE(digest->opaque); HT_FREE(digest->qop); return YES; } else return NO;}/* HTDigest_updateInfo** --------------** This function updates the digest with whatever new ** authentification information the server sent back.*/PUBLIC int HTDigest_updateInfo (HTRequest *request, HTResponse *response, void * context, int status){ HTAssocList * challenge = HTResponse_challenge(response); const char * realm = HTRequest_realm (request); if (request && challenge && realm) { BOOL proxy = 0; char * value = NULL; char * token = NULL; char * auth_info = NULL; HTDigest *digest; char *url; /* ** try to find the magic string in the challenge */ HTTRACE(AUTH_TRACE, "Digest Update.. Processing authentication-info\n"); if ((auth_info = HTAssocList_findObject(challenge, DIGEST_AI))) proxy = 0; else if ((auth_info = HTAssocList_findObject(challenge, PROXY_DIGEST_AI))) proxy = 1; else { HTTRACE(AUTH_TRACE, "Digest Update.. Didn't find any authentication-info\n"); return HT_OK; } /* ** find the digest credentials */ if (proxy) { url = HTRequest_proxy(request); digest = (HTDigest *) HTAA_updateNode (proxy, DIGEST_AUTH, realm, url, NULL); } else { url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); digest = (HTDigest *) HTAA_updateNode (proxy, DIGEST_AUTH, realm, url, NULL); HT_FREE(url); } if (!digest) { HTTRACE(AUTH_TRACE, "Digest Update.. Error: received authentication-info without having a local digest\n"); return HT_ERROR; } /* ** Search through the set of parameters in the Authentication-info ** header. */ while ((token = HTNextField(&auth_info))) { if (!strcasecomp(token, "nextnonce")) { if ((value = HTNextField(&auth_info))) { HT_FREE (digest->nonce); StrAllocCopy(digest->nonce, value); } else if (!strcasecomp(token, "qop")) { value = HTNextField(&auth_info); /* split, process the qop, report errors */ } else if (!strcasecomp(token, "rspauth")) { value = HTNextField(&auth_info); /* process rspauth */ } else if (!strcasecomp(token, "cnonce")) { value = HTNextField (&auth_info); if (value && strcmp (digest->cnonce, value)) { /* print an alert?, bad cnonce? */ } } else if (!strcasecomp(token, "nc")) { value = HTNextField(&auth_info); /* compare and printo some error? */ } } } } return HT_OK;} /*** Simple function to add a parameter/value pair to a string***/PRIVATE BOOL add_param (char ** dest, char *param, char * value, BOOL quoted){ char *tmp = *dest; if (!param || *param == '\0' || !value || *value == '\0') return NO; /* if there was a previous parameter, we add the next one in the following line */ if (tmp) StrAllocCat(tmp, ","); /* copy the new parameter and value */ StrAllocCat(tmp, param); StrAllocCat(tmp, "="); if (quoted) { StrAllocCat(tmp, "\""); StrAllocCat(tmp, value); StrAllocCat(tmp, "\""); } else StrAllocCat(tmp, value); *dest = tmp; return YES;}/*** Code derived from draft-ietf-http-authentication-03 starts here*/PRIVATE void CvtHex (HASH Bin, HASHHEX Hex){ unsigned short i; unsigned char j; for (i = 0; i < HASHLEN; i++) { j = (Bin[i] >> 4) & 0xf; if (j <= 9) Hex[i*2] = (j + '0'); else Hex[i*2] = (j + 'a' - 10); j = Bin[i] & 0xf; if (j <= 9) Hex[i*2+1] = (j + '0'); else Hex[i*2+1] = (j + 'a' - 10); } Hex[HASHHEXLEN] = '\0';}/* calculate H(A1) as per spec */PRIVATE void DigestCalcHA1 (int algorithm, char * pszAlg, char * pszUserName, char * pszRealm, char * pszPassword, char * pszNonce, char * pszCNonce, HASHHEX SessionKey){ HTDigestContext MdCtx; HASH HA1; HTDigest_init (&MdCtx, algorithm); HTDigest_update (&MdCtx, pszUserName, strlen(pszUserName)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszRealm, strlen(pszRealm)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszPassword, strlen(pszPassword)); HTDigest_final (HA1, &MdCtx); if (strcasecomp (pszAlg, "md5-sess") == 0) { HTDigest_init (&MdCtx, algorithm); HTDigest_update (&MdCtx, HA1, strlen (HA1)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszNonce, strlen(pszNonce)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszCNonce, strlen(pszCNonce)); HTDigest_final (HA1, &MdCtx); } CvtHex (HA1, SessionKey);}/* calculate request-digest/response-digest as per HTTP Digest spec */PRIVATE void DigestCalcResponse ( int algorithm, /* message digest algorithm */ HASHHEX HA1, /* H(A1) */ char * pszNonce, /* nonce from server */ char * pszNonceCount, /* 8 hex digits */ char * pszCNonce, /* client nonce */ char * pszQop, /* qop-value: "", "auth", "auth-int" */ char * pszMethod, /* method from the request */ char * pszDigestUri, /* requested URL */ char * HEntity, /* H(entity body) if qop="auth-int" */ char * Response /* request-digest or response-digest */ ){ HTDigestContext MdCtx; HASH HA2; HASH RespHash; HASHHEX HA2Hex; /* calculate H(A2) */ HTDigest_init (&MdCtx, algorithm); HTDigest_update (&MdCtx, pszMethod, strlen(pszMethod)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszDigestUri, strlen(pszDigestUri)); if (pszQop && strcasecomp (pszQop, "auth-int") == 0) { HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, HEntity, HASHHEXLEN); } HTDigest_final (HA2, &MdCtx); CvtHex (HA2, HA2Hex); /* calculate response */ HTDigest_init (&MdCtx, algorithm); HTDigest_update (&MdCtx, HA1, HASHHEXLEN); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszNonce, strlen(pszNonce)); HTDigest_update (&MdCtx, ":", 1); if (pszQop && *pszQop) { HTDigest_update (&MdCtx, pszNonceCount, strlen(pszNonceCount)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszCNonce, strlen(pszCNonce)); HTDigest_update (&MdCtx, ":", 1); HTDigest_update (&MdCtx, pszQop, strlen(pszQop)); 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*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -