static void authorize(const ChallengeList *challenge, AuthParams &authorization, const URI &uri, const std::string &method, const std::string &scheme, const std::string &realm, const std::string &username, const std::string &password) { if (stricmp(scheme.c_str(), "Basic") == 0) { BasicAuth::authorize(authorization, username, password); } else if (stricmp(scheme.c_str(), "Digest") == 0) { MORDOR_ASSERT(challenge); DigestAuth::authorize( challengeForSchemeAndRealm(*challenge, "Digest", realm), authorization, uri, method, username, password); } }
void authorize(const Response &challenge, Request &nextRequest, const std::string &username, const std::string &password) { MORDOR_ASSERT(challenge.status.status == UNAUTHORIZED || challenge.status.status == PROXY_AUTHENTICATION_REQUIRED); bool proxy = challenge.status.status == PROXY_AUTHENTICATION_REQUIRED; const ChallengeList &authenticate = proxy ? challenge.response.proxyAuthenticate : challenge.response.wwwAuthenticate; AuthParams &authorization = proxy ? nextRequest.request.proxyAuthorization : nextRequest.request.authorization; authorize(challengeForSchemeAndRealm(authenticate, "Digest"), authorization, nextRequest.requestLine.uri, nextRequest.requestLine.method, username, password); }
ClientRequest::ptr AuthRequestBroker::request(Request &requestHeaders, bool forceNewConnection, boost::function<void (ClientRequest::ptr)> bodyDg) { ClientRequest::ptr priorRequest; std::string scheme, realm, username, password; size_t attempts = 0, proxyAttempts = 0; #ifdef WINDOWS boost::scoped_ptr<NegotiateAuth> negotiateAuth, negotiateProxyAuth; #endif while (true) { #ifdef WINDOWS // Reset Negotiate auth sequence if the server didn't continue the // handshake if (negotiateProxyAuth) { const ChallengeList &challenge = priorRequest->response().response.proxyAuthenticate; if (!isAcceptable(challenge, scheme) || !negotiateProxyAuth->authorize( challengeForSchemeAndRealm(challenge, scheme), requestHeaders.request.proxyAuthorization, requestHeaders.requestLine.uri)) negotiateProxyAuth.reset(); } if (negotiateAuth) { const ChallengeList &challenge = priorRequest->response().response.wwwAuthenticate; if (!isAcceptable(challenge, scheme) || !negotiateAuth->authorize( challengeForSchemeAndRealm(challenge, scheme), requestHeaders.request.authorization, requestHeaders.requestLine.uri)) negotiateAuth.reset(); } // Negotiate auth is a multi-request transaction; if we're in the // middle of one, just do the next step, and skip asking for // credentials again if (!negotiateAuth && !negotiateProxyAuth) { #endif // If this is the first try, or the last one failed UNAUTHORIZED, // ask for credentials, and use them if we got them if ((!priorRequest || priorRequest->response().status.status == UNAUTHORIZED) && m_getCredentialsDg && m_getCredentialsDg(requestHeaders.requestLine.uri, priorRequest, scheme, realm, username, password, attempts++)) { #ifdef WINDOWS MORDOR_ASSERT( stricmp(scheme.c_str(), "Negotiate") == 0 || stricmp(scheme.c_str(), "NTLM") == 0 || stricmp(scheme.c_str(), "Digest") == 0 || stricmp(scheme.c_str(), "Basic") == 0); #else MORDOR_ASSERT( stricmp(scheme.c_str(), "Digest") == 0 || stricmp(scheme.c_str(), "Basic") == 0); #endif #ifdef WINDOWS if (scheme == "Negotiate" || scheme == "NTLM") { negotiateAuth.reset(new NegotiateAuth(username, password)); negotiateAuth->authorize( challengeForSchemeAndRealm(priorRequest->response().response.wwwAuthenticate, scheme), requestHeaders.request.authorization, requestHeaders.requestLine.uri); } else #endif authorize(priorRequest ? &priorRequest->response().response.wwwAuthenticate : NULL, requestHeaders.request.authorization, requestHeaders.requestLine.uri, requestHeaders.requestLine.method, scheme, realm, username, password); } else if (priorRequest && priorRequest->response().status.status == UNAUTHORIZED) { // caller didn't want to retry return priorRequest; } // If this is the first try, or the last one failed (for a proxy) // ask for credentials, and use them if we got them if ((!priorRequest || priorRequest->response().status.status == PROXY_AUTHENTICATION_REQUIRED) && m_getProxyCredentialsDg && m_getProxyCredentialsDg(requestHeaders.requestLine.uri, priorRequest, scheme, realm, username, password, proxyAttempts++)) { #ifdef WINDOWS MORDOR_ASSERT( stricmp(scheme.c_str(), "Negotiate") == 0 || stricmp(scheme.c_str(), "NTLM") == 0 || stricmp(scheme.c_str(), "Digest") == 0 || stricmp(scheme.c_str(), "Basic") == 0); #else MORDOR_ASSERT( stricmp(scheme.c_str(), "Digest") == 0 || stricmp(scheme.c_str(), "Basic") == 0); #endif #ifdef WINDOWS if (scheme == "Negotiate" || scheme == "NTLM") { negotiateProxyAuth.reset(new NegotiateAuth(username, password)); negotiateProxyAuth->authorize( challengeForSchemeAndRealm(priorRequest->response().response.proxyAuthenticate, scheme), requestHeaders.request.proxyAuthorization, requestHeaders.requestLine.uri); } else #endif authorize(priorRequest ? &priorRequest->response().response.proxyAuthenticate : NULL, requestHeaders.request.proxyAuthorization, requestHeaders.requestLine.uri, requestHeaders.requestLine.method, scheme, realm, username, password); } else if (priorRequest && priorRequest->response().status.status == PROXY_AUTHENTICATION_REQUIRED) { // Caller didn't want to retry return priorRequest; } #ifdef WINDOWS } #endif if (priorRequest) { priorRequest->finish(); } else { // We're passed our pre-emptive authentication, regardless of what // actually happened attempts = 1; proxyAttempts = 1; } priorRequest = parent()->request(requestHeaders, forceNewConnection, bodyDg); const ChallengeList *challengeList = NULL; if (priorRequest->response().status.status == UNAUTHORIZED) challengeList = &priorRequest->response().response.wwwAuthenticate; if (priorRequest->response().status.status == PROXY_AUTHENTICATION_REQUIRED) challengeList = &priorRequest->response().response.proxyAuthenticate; if (challengeList && (isAcceptable(*challengeList, "Basic") || isAcceptable(*challengeList, "Digest") #ifdef WINDOWS || isAcceptable(*challengeList, "Negotiate") || isAcceptable(*challengeList, "NTLM") #endif )) continue; return priorRequest; } }