2 * Copyright (C) 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #import "AuthenticationMac.h"
28 #import "AuthenticationCF.h"
29 #import "AuthenticationChallenge.h"
30 #import "AuthenticationClient.h"
31 #import "Credential.h"
32 #import "ProtectionSpace.h"
34 #import <Foundation/NSURLAuthenticationChallenge.h>
35 #import <Foundation/NSURLCredential.h>
36 #import <Foundation/NSURLProtectionSpace.h>
40 @interface NSURLProtectionSpace (Details)
41 - (CFURLProtectionSpaceRef) _cfurlprotectionspace;
42 - (id)_initWithCFURLProtectionSpace:(CFURLProtectionSpaceRef)cfProtSpace;
45 @interface NSURLAuthenticationChallenge (Details)
46 +(NSURLAuthenticationChallenge *)_authenticationChallengeForCFAuthChallenge:(CFURLAuthChallengeRef)cfChallenge sender:(id <NSURLAuthenticationChallengeSender>)sender;
49 @interface NSURLCredential (Details)
50 - (id) _initWithCFURLCredential:(CFURLCredentialRef)credential;
51 - (CFURLCredentialRef) _cfurlcredential;
56 using namespace WebCore;
58 @interface WebCoreAuthenticationClientAsChallengeSender : NSObject <NSURLAuthenticationChallengeSender>
60 AuthenticationClient* m_client;
62 CFURLAuthChallengeRef m_cfChallenge;
65 - (id)initWithAuthenticationClient:(AuthenticationClient*)client;
66 - (AuthenticationClient*)client;
70 @implementation WebCoreAuthenticationClientAsChallengeSender
72 - (id)initWithAuthenticationClient:(AuthenticationClient*)client
81 - (AuthenticationClient*)client
91 - (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
94 m_client->receivedCredential(core(challenge), core(credential));
97 - (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
100 m_client->receivedRequestToContinueWithoutCredential(core(challenge));
103 - (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
106 m_client->receivedCancellation(core(challenge));
110 - (void)setCFChallenge:(CFURLAuthChallengeRef)challenge
112 m_cfChallenge = challenge;
115 - (CFURLAuthChallengeRef)cfChallenge
117 return m_cfChallenge;
127 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge)
129 WebCoreAuthenticationClientAsChallengeSender *challengeSender = (WebCoreAuthenticationClientAsChallengeSender*) [macChallenge sender];
130 return AuthenticationChallenge([challengeSender cfChallenge], [challengeSender client]);
133 Credential core(NSURLCredential *macCredential)
135 return core([macCredential _cfurlcredential]);
138 ProtectionSpace core(NSURLProtectionSpace *macSpace)
140 return core([macSpace _cfurlprotectionspace]);
143 NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
145 RetainPtr<CFURLProtectionSpaceRef> protectionSpace(AdoptCF, createCF(coreSpace));
146 return [[[NSURLProtectionSpace alloc] _initWithCFURLProtectionSpace:protectionSpace.get()] autorelease];
149 NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge)
151 AuthenticationClient* authClient = coreChallenge.authenticationClient();
152 RetainPtr<WebCoreAuthenticationClientAsChallengeSender> challengeSender(AdoptNS, [[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:authClient]);
153 RetainPtr<CFURLAuthChallengeRef> authChallenge = coreChallenge.cfURLAuthChallengeRef();
155 authChallenge.adoptCF(createCF(coreChallenge));
156 [challengeSender.get() setCFChallenge:authChallenge.get()];
157 return [[NSURLAuthenticationChallenge _authenticationChallengeForCFAuthChallenge:authChallenge.get() sender:challengeSender.get()] autorelease];
160 NSURLCredential *mac(const Credential& coreCredential)
162 RetainPtr<CFURLCredentialRef> credential(AdoptCF, createCF(coreCredential));
163 return [[[NSURLCredential alloc] _initWithCFURLCredential:credential.get()] autorelease];
168 #if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED == 1050
169 // There is no constant in headers, but NTLM is supported.
170 NSString * const NSURLAuthenticationMethodNTLM = @"NSURLAuthenticationMethodNTLM";
173 AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
174 const Credential& proposedCredential,
175 unsigned previousFailureCount,
176 const ResourceResponse& response,
177 const ResourceError& error)
178 : AuthenticationChallengeBase(protectionSpace,
180 previousFailureCount,
186 AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *challenge)
187 : AuthenticationChallengeBase(core([challenge protectionSpace]),
188 core([challenge proposedCredential]),
189 [challenge previousFailureCount],
190 [challenge failureResponse],
192 , m_sender([challenge sender])
193 , m_nsChallenge(challenge)
197 void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client)
200 m_sender.adoptNS([[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:client]);
202 m_nsChallenge.adoptNS([[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:m_nsChallenge.get() sender:m_sender.get()]);
204 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
205 [(WebCoreAuthenticationClientAsChallengeSender *)m_sender.get() detachClient];
209 AuthenticationClient* AuthenticationChallenge::authenticationClient() const
211 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
212 return [static_cast<WebCoreAuthenticationClientAsChallengeSender*>(m_sender.get()) client];
217 bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
219 if (a.sender() != b.sender())
222 if (a.nsURLAuthenticationChallenge() != b.nsURLAuthenticationChallenge())
228 NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge)
230 if (coreChallenge.nsURLAuthenticationChallenge())
231 return coreChallenge.nsURLAuthenticationChallenge();
233 return [[[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:mac(coreChallenge.protectionSpace())
234 proposedCredential:mac(coreChallenge.proposedCredential())
235 previousFailureCount:coreChallenge.previousFailureCount()
236 failureResponse:coreChallenge.failureResponse().nsURLResponse()
237 error:coreChallenge.error()
238 sender:coreChallenge.sender()] autorelease];
241 NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
243 NSString *proxyType = nil;
244 NSString *protocol = nil;
245 switch (coreSpace.serverType()) {
246 case ProtectionSpaceServerHTTP:
249 case ProtectionSpaceServerHTTPS:
252 case ProtectionSpaceServerFTP:
255 case ProtectionSpaceServerFTPS:
258 case ProtectionSpaceProxyHTTP:
259 proxyType = NSURLProtectionSpaceHTTPProxy;
261 case ProtectionSpaceProxyHTTPS:
262 proxyType = NSURLProtectionSpaceHTTPSProxy;
264 case ProtectionSpaceProxyFTP:
265 proxyType = NSURLProtectionSpaceFTPProxy;
267 case ProtectionSpaceProxySOCKS:
268 proxyType = NSURLProtectionSpaceSOCKSProxy;
271 ASSERT_NOT_REACHED();
274 NSString *method = nil;
275 switch (coreSpace.authenticationScheme()) {
276 case ProtectionSpaceAuthenticationSchemeDefault:
277 method = NSURLAuthenticationMethodDefault;
279 case ProtectionSpaceAuthenticationSchemeHTTPBasic:
280 method = NSURLAuthenticationMethodHTTPBasic;
282 case ProtectionSpaceAuthenticationSchemeHTTPDigest:
283 method = NSURLAuthenticationMethodHTTPDigest;
285 case ProtectionSpaceAuthenticationSchemeHTMLForm:
286 method = NSURLAuthenticationMethodHTMLForm;
288 case ProtectionSpaceAuthenticationSchemeNTLM:
289 method = NSURLAuthenticationMethodNTLM;
291 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
292 case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
293 method = NSURLAuthenticationMethodServerTrust;
295 case ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
296 method = NSURLAuthenticationMethodClientCertificate;
300 ASSERT_NOT_REACHED();
304 return [[[NSURLProtectionSpace alloc] initWithProxyHost:coreSpace.host()
305 port:coreSpace.port()
307 realm:coreSpace.realm()
308 authenticationMethod:method] autorelease];
309 return [[[NSURLProtectionSpace alloc] initWithHost:coreSpace.host()
310 port:coreSpace.port()
312 realm:coreSpace.realm()
313 authenticationMethod:method] autorelease];
316 NSURLCredential *mac(const Credential& coreCredential)
318 if (coreCredential.isEmpty())
321 NSURLCredentialPersistence persistence = NSURLCredentialPersistenceNone;
322 switch (coreCredential.persistence()) {
323 case CredentialPersistenceNone:
325 case CredentialPersistenceForSession:
326 persistence = NSURLCredentialPersistenceForSession;
328 case CredentialPersistencePermanent:
329 persistence = NSURLCredentialPersistencePermanent;
332 ASSERT_NOT_REACHED();
335 #if CERTIFICATE_CREDENTIALS_SUPPORTED
336 if (coreCredential.type() == CredentialTypeClientCertificate) {
337 return [[[NSURLCredential alloc] initWithIdentity:coreCredential.identity()
338 certificates:(NSArray *)coreCredential.certificates()
339 persistence:persistence]
344 return [[[NSURLCredential alloc] initWithUser:coreCredential.user()
345 password:coreCredential.password()
346 persistence:persistence]
350 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge)
352 return AuthenticationChallenge(macChallenge);
355 ProtectionSpace core(NSURLProtectionSpace *macSpace)
357 ProtectionSpaceServerType serverType = ProtectionSpaceProxyHTTP;
359 if ([macSpace isProxy]) {
360 NSString *proxyType = [macSpace proxyType];
361 if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPProxy])
362 serverType = ProtectionSpaceProxyHTTP;
363 else if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPSProxy])
364 serverType = ProtectionSpaceProxyHTTPS;
365 else if ([proxyType isEqualToString:NSURLProtectionSpaceFTPProxy])
366 serverType = ProtectionSpaceProxyFTP;
367 else if ([proxyType isEqualToString:NSURLProtectionSpaceSOCKSProxy])
368 serverType = ProtectionSpaceProxySOCKS;
370 ASSERT_NOT_REACHED();
372 NSString *protocol = [macSpace protocol];
373 if ([protocol caseInsensitiveCompare:@"http"] == NSOrderedSame)
374 serverType = ProtectionSpaceServerHTTP;
375 else if ([protocol caseInsensitiveCompare:@"https"] == NSOrderedSame)
376 serverType = ProtectionSpaceServerHTTPS;
377 else if ([protocol caseInsensitiveCompare:@"ftp"] == NSOrderedSame)
378 serverType = ProtectionSpaceServerFTP;
379 else if ([protocol caseInsensitiveCompare:@"ftps"] == NSOrderedSame)
380 serverType = ProtectionSpaceServerFTPS;
382 ASSERT_NOT_REACHED();
385 ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault;
386 NSString *method = [macSpace authenticationMethod];
387 if ([method isEqualToString:NSURLAuthenticationMethodDefault])
388 scheme = ProtectionSpaceAuthenticationSchemeDefault;
389 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPBasic])
390 scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
391 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPDigest])
392 scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
393 else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm])
394 scheme = ProtectionSpaceAuthenticationSchemeHTMLForm;
395 else if ([method isEqualToString:NSURLAuthenticationMethodNTLM])
396 scheme = ProtectionSpaceAuthenticationSchemeNTLM;
397 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
398 else if ([method isEqualToString:NSURLAuthenticationMethodClientCertificate])
399 scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested;
400 else if ([method isEqualToString:NSURLAuthenticationMethodServerTrust])
401 scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
404 scheme = ProtectionSpaceAuthenticationSchemeUnknown;
405 ASSERT_NOT_REACHED();
408 return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme);
412 Credential core(NSURLCredential *macCredential)
414 CredentialPersistence persistence = CredentialPersistenceNone;
415 switch ([macCredential persistence]) {
416 case NSURLCredentialPersistenceNone:
418 case NSURLCredentialPersistenceForSession:
419 persistence = CredentialPersistenceForSession;
421 case NSURLCredentialPersistencePermanent:
422 persistence = CredentialPersistencePermanent;
425 ASSERT_NOT_REACHED();
428 #if CERTIFICATE_CREDENTIALS_SUPPORTED
429 SecIdentityRef identity = [macCredential identity];
431 return Credential(identity, (CFArrayRef)[macCredential certificates], persistence);
434 return Credential([macCredential user], [macCredential password], persistence);
437 #endif // USE(CFNETWORK)
439 } // namespace WebCore