Example #1
0
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
    LOG(Network, "CFNet - didReceiveAuthenticationChallenge()");
    ASSERT(d->m_currentWebChallenge.isNull());
    // Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef,
    // we make sure that is actually present
    ASSERT(challenge.cfURLAuthChallengeRef());
    ASSERT(challenge.authenticationClient() == this); // Should be already set.

#if !PLATFORM(WIN)
    // Proxy authentication is handled by CFNetwork internally. We can get here if the user cancels
    // CFNetwork authentication dialog, and we shouldn't ask the client to display another one in that case.
    if (challenge.protectionSpace().isProxy()) {
        // Cannot use receivedRequestToContinueWithoutCredential(), because current challenge is not yet set.
        CFURLConnectionUseCredential(d->m_connection.get(), 0, challenge.cfURLAuthChallengeRef());
        return;
    }
#endif

    if (tryHandlePasswordBasedAuthentication(challenge))
        return;

    d->m_currentWebChallenge = challenge;
    
    if (client())
        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
    else {
        clearAuthentication();
        CFURLConnectionPerformDefaultHandlingForChallenge(d->m_connection.get(), challenge.cfURLAuthChallengeRef());
    }
}
Example #2
0
void NetworkLoad::didReceiveChallenge(const AuthenticationChallenge& challenge, ChallengeCompletionHandler&& completionHandler)
{
    // NetworkResourceLoader does not know whether the request is cross origin, so Web process computes an applicable credential policy for it.
    ASSERT(m_parameters.clientCredentialPolicy != DoNotAskClientForCrossOriginCredentials);

    // Handle server trust evaluation at platform-level if requested, for performance reasons.
    if (challenge.protectionSpace().authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested
        && !NetworkProcess::singleton().canHandleHTTPSServerTrustEvaluation()) {
        if (m_task && m_task->allowsSpecificHTTPSCertificateForHost(challenge))
            completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(challenge));
        else
            completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, { });
        return;
    }

    m_challengeCompletionHandler = WTFMove(completionHandler);
    m_challenge = challenge;

    if (m_client.isSynchronous()) {
        // FIXME: We should ask the WebProcess like the asynchronous case below does.
        // This is currently impossible as the WebProcess is blocked waiting on this synchronous load.
        // It's possible that we can jump straight to the UI process to resolve this.
        continueCanAuthenticateAgainstProtectionSpace(true);
        return;
    } else
        m_client.canAuthenticateAgainstProtectionSpaceAsync(challenge.protectionSpace());
}
void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
{
    ASSERT(!challenge.isNull());
    if (challenge != d->m_currentWebChallenge)
        return;

    if (credential.isEmpty()) {
        receivedRequestToContinueWithoutCredential(challenge);
        return;
    }

    KURL urlToStore;
    urlToStore = d->m_request.url();

    CredentialStorage::set(credential, challenge.protectionSpace(), urlToStore);

    clearAuthentication();
    // Clone our ResourceHandle and add it so that it is send with the credential.
    // FIXME: We should have a way of cloning an handle.
    RefPtr<ResourceHandle> newHandle = ResourceHandle::create(request(), client(), 0, d->m_defersLoading, shouldContentSniff());
    setClient(0); // Clear the client to avoid it being cleared by WebCore.
    AuthenticationChallenge newAuthenticationChallenge(challenge.protectionSpace(), credential, challenge.previousFailureCount() + 1, challenge.failureResponse(), challenge.error());

    // Store the new authentication challenge.
    newHandle->getInternal()->m_currentWebChallenge = newAuthenticationChallenge;
    d->m_cancelled = true;
}
Example #4
0
void ArgumentCoder<AuthenticationChallenge>::encode(ArgumentEncoder* encoder, const AuthenticationChallenge& challenge)
{
    encoder->encode(challenge.protectionSpace());
    encoder->encode(challenge.proposedCredential());
    encoder->encode(challenge.previousFailureCount());
    encoder->encode(challenge.failureResponse());
    encoder->encode(challenge.error());
}
Example #5
0
bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
{
    if (a.authenticationClient() != b.authenticationClient())
        return false;

    if (a.cfURLAuthChallengeRef() != b.cfURLAuthChallengeRef())
        return false;
        
    return true;
}
Example #6
0
void ResourceHandle::receivedRequestToPerformDefaultHandling(const AuthenticationChallenge& challenge)
{
    LOG(Network, "CFNet - receivedRequestToPerformDefaultHandling()");
    ASSERT(!challenge.isNull());
    ASSERT(challenge.cfURLAuthChallengeRef());
    if (challenge != d->m_currentWebChallenge)
        return;

    CFURLConnectionPerformDefaultHandlingForChallenge(d->m_connection.get(), challenge.cfURLAuthChallengeRef());

    clearAuthentication();
}
Example #7
0
void ResourceHandle::receivedChallengeRejection(const AuthenticationChallenge& challenge)
{
    LOG(Network, "CFNet - receivedChallengeRejection()");
    ASSERT(!challenge.isNull());
    ASSERT(challenge.cfURLAuthChallengeRef());
    if (challenge != d->m_currentWebChallenge)
        return;

    CFURLConnectionRejectChallenge(d->m_connection.get(), challenge.cfURLAuthChallengeRef());

    clearAuthentication();
}
Example #8
0
void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge)
{
    LOG(Network, "CFNet - receivedRequestToContinueWithoutCredential()");
    ASSERT(!challenge.isNull());
    ASSERT(challenge.cfURLAuthChallengeRef());
    if (challenge != d->m_currentWebChallenge)
        return;

    CFURLConnectionUseCredential(d->m_connection.get(), 0, challenge.cfURLAuthChallengeRef());

    clearAuthentication();
}
Example #9
0
CFURLAuthChallengeRef createCF(const AuthenticationChallenge& coreChallenge)
{  
    CFURLProtectionSpaceRef protectionSpace = createCF(coreChallenge.protectionSpace());
    CFURLCredentialRef credential = createCF(coreChallenge.proposedCredential());
    
    CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, protectionSpace, credential,
                                        coreChallenge.previousFailureCount(),
                                        coreChallenge.failureResponse().cfURLResponse(),
                                        coreChallenge.error());
    CFRelease(protectionSpace);
    CFRelease(credential);
    return result;
}
Example #10
0
void AuthenticationManager::cancelChallenge(uint64_t challengeID)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // This authentication challenge comes from a download.
        Download::receivedCancellation(challenge);
        return;
    }

    coreClient->receivedCancellation(challenge);
}
Example #11
0
void AuthenticationManager::continueWithoutCredentialForChallenge(uint64_t challengeID)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // This authentication challenge comes from a download.
        Download::receivedRequestToContinueWithoutCredential(challenge);
        return;
    }

    coreClient->receivedRequestToContinueWithoutCredential(challenge);
}
Example #12
0
void AuthenticationManager::rejectProtectionSpaceAndContinueForSingleChallenge(uint64_t challengeID)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // FIXME: The authentication client is null for downloads, but it can also be null for canceled loads.
        // We should not call Download::receivedCredential in the latter case.
        Download::receivedChallengeRejection(challenge);
        return;
    }

    coreClient->receivedChallengeRejection(challenge);
}
Example #13
0
void AuthenticationManager::performDefaultHandlingForSingleChallenge(uint64_t challengeID)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // FIXME: The authentication client is null for downloads, but it can also be null for canceled loads.
        // We should not call Download::receivedCredential in the latter case.
        Download::receivedRequestToPerformDefaultHandling(challenge);
        return;
    }

    coreClient->receivedRequestToPerformDefaultHandling(challenge);
}
void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
{
    LOG(Network, "CFNet - receivedCredential()");
    ASSERT(!challenge.isNull());
    ASSERT(challenge.cfURLAuthChallengeRef());
    if (challenge != d->m_currentWebChallenge)
        return;

    CFURLCredentialRef cfCredential = createCF(credential);
    CFURLConnectionUseCredential(d->m_connection.get(), cfCredential, challenge.cfURLAuthChallengeRef());
    CFRelease(cfCredential);

    clearAuthentication();
}
Example #15
0
bool ResourceHandle::tryHandlePasswordBasedAuthentication(const AuthenticationChallenge& challenge)
{
    if (!challenge.protectionSpace().isPasswordBased())
        return false;

    if (!d->m_user.isNull() && !d->m_pass.isNull()) {
        RetainPtr<CFURLCredentialRef> cfCredential = adoptCF(CFURLCredentialCreate(kCFAllocatorDefault, d->m_user.createCFString().get(), d->m_pass.createCFString().get(), 0, kCFURLCredentialPersistenceNone));
#if PLATFORM(COCOA)
        Credential credential = Credential(cfCredential.get());
#else
        Credential credential = core(cfCredential.get());
#endif
        
        URL urlToStore;
        if (challenge.failureResponse().httpStatusCode() == 401)
            urlToStore = challenge.failureResponse().url();
        d->m_context->storageSession().credentialStorage().set(credential, challenge.protectionSpace(), urlToStore);
        
        CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
        d->m_user = String();
        d->m_pass = String();
        // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
        return true;
    }

    if (!client() || client()->shouldUseCredentialStorage(this)) {
        if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) {
            // The stored credential wasn't accepted, stop using it.
            // There is a race condition here, since a different credential might have already been stored by another ResourceHandle,
            // but the observable effect should be very minor, if any.
            d->m_context->storageSession().credentialStorage().remove(challenge.protectionSpace());
        }

        if (!challenge.previousFailureCount()) {
            Credential credential = d->m_context->storageSession().credentialStorage().get(challenge.protectionSpace());
            if (!credential.isEmpty() && credential != d->m_initialCredential) {
                ASSERT(credential.persistence() == CredentialPersistenceNone);
                if (challenge.failureResponse().httpStatusCode() == 401) {
                    // Store the credential back, possibly adding it as a default for this directory.
                    d->m_context->storageSession().credentialStorage().set(credential, challenge.protectionSpace(), challenge.failureResponse().url());
                }
#if PLATFORM(COCOA)
                CFURLConnectionUseCredential(d->m_connection.get(), credential.cfCredential(), challenge.cfURLAuthChallengeRef());
#else
                RetainPtr<CFURLCredentialRef> cfCredential = adoptCF(createCF(credential));
                CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
#endif
                return true;
            }
        }
    }

    return false;
}
CFURLAuthChallengeRef createCF(const AuthenticationChallenge& coreChallenge)
{
    // FIXME: Why not cache CFURLAuthChallengeRef in m_cfChallenge? Foundation counterpart does that.

    CFURLProtectionSpaceRef protectionSpace = createCF(coreChallenge.protectionSpace());
    CFURLCredentialRef credential = createCF(coreChallenge.proposedCredential());
    
    CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, protectionSpace, credential,
                                        coreChallenge.previousFailureCount(),
                                        coreChallenge.failureResponse().cfURLResponse(),
                                        coreChallenge.error());
    CFRelease(protectionSpace);
    CFRelease(credential);
    return result;
}
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
    LOG(Network, "CFNet - didReceiveAuthenticationChallenge()");
    ASSERT(!d->m_currentCFChallenge);
    ASSERT(d->m_currentWebChallenge.isNull());
    // Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef,
    // we make sure that is actually present
    ASSERT(challenge.cfURLAuthChallengeRef());

    d->m_currentCFChallenge = challenge.cfURLAuthChallengeRef();
    d->m_currentWebChallenge = AuthenticationChallenge(d->m_currentCFChallenge, this);

    if (client())
        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
}
Example #18
0
void NetworkLoad::didReceiveChallenge(const AuthenticationChallenge& challenge, std::function<void(AuthenticationChallengeDisposition, const Credential&)> completionHandler)
{
    // NetworkResourceLoader does not know whether the request is cross origin, so Web process computes an applicable credential policy for it.
    ASSERT(m_parameters.clientCredentialPolicy != DoNotAskClientForCrossOriginCredentials);

    // Handle server trust evaluation at platform-level if requested, for performance reasons.
    if (challenge.protectionSpace().authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested
        && !NetworkProcess::singleton().canHandleHTTPSServerTrustEvaluation()) {
        completionHandler(AuthenticationChallengeDisposition::PerformDefaultHandling, Credential());
        return;
    }

    if (m_client.isSynchronous()) {
        // FIXME: We should ask the WebProcess like the asynchronous case below does.
        // This is currently impossible as the WebProcess is blocked waiting on this synchronous load.
        // It's possible that we can jump straight to the UI process to resolve this.
        completionHandler(AuthenticationChallengeDisposition::PerformDefaultHandling, Credential());
        return;
    }

    if (m_parameters.clientCredentialPolicy == DoNotAskClientForAnyCredentials) {
        completionHandler(AuthenticationChallengeDisposition::UseCredential, Credential());
        return;
    }

    NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(m_parameters.webPageID, m_parameters.webFrameID, challenge, completionHandler);
}
void AuthenticationManager::cancelChallenge(uint64_t challengeID)
{
    ASSERT(RunLoop::isMain());

    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // FIXME: The authentication client is null for downloads, but it can also be null for canceled loads.
        // We should not call Download::receivedCredential in the latter case.
        Download::receivedCancellation(challenge);
        return;
    }

    coreClient->receivedCancellation(challenge);
}
Example #20
0
void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
{
    ASSERT(challenge.authenticationClient());

    WebView* webView = m_webFrame->webView();
    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
    if (SUCCEEDED(webView->resourceLoadDelegate(&resourceLoadDelegate))) {
        COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
        if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader))))
            return;
    }

    // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle
    // to continue without credential - this is the best approximation of Mac behavior
    challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
}
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
    if (!d->m_user.isNull() && !d->m_pass.isNull()) {
        Credential credential(d->m_user, d->m_pass, CredentialPersistenceNone);

        URL urlToStore;
        if (challenge.failureResponse().httpStatusCode() == 401)
            urlToStore = challenge.failureResponse().url();
        CredentialStorage::set(credential, challenge.protectionSpace(), urlToStore);
        
        String userpass = credential.user() + ":" + credential.password();
        curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());

        d->m_user = String();
        d->m_pass = String();
        // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
        return;
    }

    if (shouldUseCredentialStorage()) {
        if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) {
            // The stored credential wasn't accepted, stop using it.
            // There is a race condition here, since a different credential might have already been stored by another ResourceHandle,
            // but the observable effect should be very minor, if any.
            CredentialStorage::remove(challenge.protectionSpace());
        }

        if (!challenge.previousFailureCount()) {
            Credential credential = CredentialStorage::get(challenge.protectionSpace());
            if (!credential.isEmpty() && credential != d->m_initialCredential) {
                ASSERT(credential.persistence() == CredentialPersistenceNone);
                if (challenge.failureResponse().httpStatusCode() == 401) {
                    // Store the credential back, possibly adding it as a default for this directory.
                    CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url());
                }
                String userpass = credential.user() + ":" + credential.password();
                curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
                return;
            }
        }
    }

    d->m_currentWebChallenge = challenge;
    
    if (client())
        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
}
Example #22
0
void AuthenticationManager::useCredentialForChallenge(uint64_t challengeID, const Credential& credential, const PlatformCertificateInfo& certificateInfo)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    
    if (tryUsePlatformCertificateInfoForChallenge(challenge, certificateInfo))
        return;
    
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // This authentication challenge comes from a download.
        Download::receivedCredential(challenge, credential);
        return;
    }

    coreClient->receivedCredential(challenge, credential);
}
Example #23
0
void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
{
    LOG(Network, "CFNet - receivedCredential()");
    ASSERT(!challenge.isNull());
    ASSERT(challenge.cfURLAuthChallengeRef());
    if (challenge != d->m_currentWebChallenge)
        return;

    // FIXME: Support empty credentials. Currently, an empty credential cannot be stored in WebCore credential storage, as that's empty value for its map.
    if (credential.isEmpty()) {
        receivedRequestToContinueWithoutCredential(challenge);
        return;
    }

    if (credential.persistence() == CredentialPersistenceForSession) {
        // Manage per-session credentials internally, because once NSURLCredentialPersistencePerSession is used, there is no way
        // to ignore it for a particular request (short of removing it altogether).
        Credential webCredential(credential.user(), credential.password(), CredentialPersistenceNone);
        RetainPtr<CFURLCredentialRef> cfCredential = adoptCF(createCF(webCredential));

        URL urlToStore;
        if (challenge.failureResponse().httpStatusCode() == 401)
            urlToStore = challenge.failureResponse().url();
        CredentialStorage::set(webCredential, challenge.protectionSpace(), urlToStore);

        CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
    } else {
        RetainPtr<CFURLCredentialRef> cfCredential = adoptCF(createCF(credential));
        CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef());
    }

    clearAuthentication();
}
Example #24
0
Vector<uint64_t> AuthenticationManager::coalesceChallengesMatching(uint64_t challengeID) const
{
    AuthenticationChallenge challenge = m_challenges.get(challengeID);
    ASSERT(!challenge.isNull());

    Vector<uint64_t> challengesToCoalesce;
    challengesToCoalesce.append(challengeID);

    if (!canCoalesceChallenge(challenge))
        return challengesToCoalesce;

    for (auto& item : m_challenges) {
        if (item.key != challengeID && ProtectionSpace::compare(challenge.protectionSpace(), item.value.protectionSpace()))
            challengesToCoalesce.append(item.key);
    }

    return challengesToCoalesce;
}
Example #25
0
void AuthenticationManager::useCredentialForSingleChallenge(uint64_t challengeID, const Credential& credential, const CertificateInfo& certificateInfo)
{
    AuthenticationChallenge challenge = m_challenges.take(challengeID);
    ASSERT(!challenge.isNull());
    
    if (tryUseCertificateInfoForChallenge(challenge, certificateInfo))
        return;
    
    AuthenticationClient* coreClient = challenge.authenticationClient();
    if (!coreClient) {
        // FIXME: The authentication client is null for downloads, but it can also be null for canceled loads.
        // We should not call Download::receivedCredential in the latter case.
        Download::receivedCredential(challenge, credential);
        return;
    }

    coreClient->receivedCredential(challenge, credential);
}
Example #26
0
void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) 
{
    // Do nothing as curl will automatically continue its transfer.
    ASSERT(!challenge.isNull());
    if (challenge != d->m_currentWebChallenge)
        return;
    
    clearAuthentication();
}
Example #27
0
void WebResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
    if (m_currentAuthenticationChallenge->identifier() != challenge.identifier())
        return;

    LOG(Network, "(WebProcess) WebResourceLoader::didCancelAuthenticationChallenge for '%s'", m_coreLoader->url().string().utf8().data());

    m_coreLoader->didCancelAuthenticationChallenge(*m_currentAuthenticationChallenge);
    m_currentAuthenticationChallenge.clear();
}
static void setAuthCredentials(NetworkRequest& platformRequest, const AuthenticationChallenge& challenge)
{
    if (challenge.isNull())
        return;

    Credential credential = challenge.proposedCredential();
    const ProtectionSpace& protectionSpace = challenge.protectionSpace();

    String username = credential.user();
    String password = credential.password();

    NetworkRequest::AuthType authType;
    NetworkRequest::AuthProtocol authProtocol;
    NetworkRequest::AuthScheme authScheme;
    protectionSpaceToPlatformAuth(protectionSpace, authType, authProtocol, authScheme);

    if (authType != NetworkRequest::AuthTypeNone && authProtocol != NetworkRequest::AuthProtocolNone && authScheme != NetworkRequest::AuthSchemeNone)
        platformRequest.setCredentials(authType, authProtocol, authScheme, username.utf8().data(), password.utf8().data());
}
Example #29
0
bool AuthenticationManager::shouldCoalesceChallenge(uint64_t challengeID, const AuthenticationChallenge& challenge) const
{
    if (!canCoalesceChallenge(challenge))
        return false;

    for (auto& item : m_challenges) {
        if (item.key != challengeID && ProtectionSpace::compare(challenge.protectionSpace(), item.value.challenge.protectionSpace()))
            return true;
    }
    return false;
}
void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
{
#if USE(CURL)
    ASSERT(challenge.authenticationClient());
#endif

    WebView* webView = m_webFrame->webView();
    SharedPtr<WebResourceLoadDelegate> resourceLoadDelegate = webView->webResourceLoadDelegate();
    if (resourceLoadDelegate) {
        WebURLAuthenticationChallenge* webChallenge = WebURLAuthenticationChallenge::createInstance(challenge);
        resourceLoadDelegate->didReceiveAuthenticationChallenge(webView, identifier, webChallenge, getWebDataSource(loader));
        delete webChallenge;
    }

#if USE(CURL)
    // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle
    // to continue without credential - this is the best approximation of Mac behavior
    challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
#endif
}