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 static uint64_t generateUniqueIdentifier()
175 static uint64_t uniqueIdentifier;
176 return ++uniqueIdentifier;
179 AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
180 const Credential& proposedCredential,
181 unsigned previousFailureCount,
182 const ResourceResponse& response,
183 const ResourceError& error,
185 : AuthenticationChallengeBase(protectionSpace,
187 previousFailureCount,
191 m_identifier = identifier;
194 AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *challenge)
195 : AuthenticationChallengeBase(core([challenge protectionSpace]),
196 core([challenge proposedCredential]),
197 [challenge previousFailureCount],
198 [challenge failureResponse],
200 , m_sender([challenge sender])
201 , m_nsChallenge(challenge)
203 m_identifier = generateUniqueIdentifier();
206 void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client)
209 m_sender.adoptNS([[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:client]);
211 m_nsChallenge.adoptNS([[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:m_nsChallenge.get() sender:m_sender.get()]);
213 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
214 [(WebCoreAuthenticationClientAsChallengeSender *)m_sender.get() detachClient];
218 AuthenticationClient* AuthenticationChallenge::authenticationClient() const
220 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
221 return [static_cast<WebCoreAuthenticationClientAsChallengeSender*>(m_sender.get()) client];
226 bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
228 if (a.sender() != b.sender())
231 if (a.nsURLAuthenticationChallenge() != b.nsURLAuthenticationChallenge())
237 NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge)
239 if (coreChallenge.nsURLAuthenticationChallenge())
240 return coreChallenge.nsURLAuthenticationChallenge();
242 return [[[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:mac(coreChallenge.protectionSpace())
243 proposedCredential:mac(coreChallenge.proposedCredential())
244 previousFailureCount:coreChallenge.previousFailureCount()
245 failureResponse:coreChallenge.failureResponse().nsURLResponse()
246 error:coreChallenge.error()
247 sender:coreChallenge.sender()] autorelease];
250 NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
252 NSString *proxyType = nil;
253 NSString *protocol = nil;
254 switch (coreSpace.serverType()) {
255 case ProtectionSpaceServerHTTP:
258 case ProtectionSpaceServerHTTPS:
261 case ProtectionSpaceServerFTP:
264 case ProtectionSpaceServerFTPS:
267 case ProtectionSpaceProxyHTTP:
268 proxyType = NSURLProtectionSpaceHTTPProxy;
270 case ProtectionSpaceProxyHTTPS:
271 proxyType = NSURLProtectionSpaceHTTPSProxy;
273 case ProtectionSpaceProxyFTP:
274 proxyType = NSURLProtectionSpaceFTPProxy;
276 case ProtectionSpaceProxySOCKS:
277 proxyType = NSURLProtectionSpaceSOCKSProxy;
280 ASSERT_NOT_REACHED();
283 NSString *method = nil;
284 switch (coreSpace.authenticationScheme()) {
285 case ProtectionSpaceAuthenticationSchemeDefault:
286 method = NSURLAuthenticationMethodDefault;
288 case ProtectionSpaceAuthenticationSchemeHTTPBasic:
289 method = NSURLAuthenticationMethodHTTPBasic;
291 case ProtectionSpaceAuthenticationSchemeHTTPDigest:
292 method = NSURLAuthenticationMethodHTTPDigest;
294 case ProtectionSpaceAuthenticationSchemeHTMLForm:
295 method = NSURLAuthenticationMethodHTMLForm;
297 case ProtectionSpaceAuthenticationSchemeNTLM:
298 method = NSURLAuthenticationMethodNTLM;
300 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
301 case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
302 method = NSURLAuthenticationMethodServerTrust;
304 case ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
305 method = NSURLAuthenticationMethodClientCertificate;
309 ASSERT_NOT_REACHED();
313 return [[[NSURLProtectionSpace alloc] initWithProxyHost:coreSpace.host()
314 port:coreSpace.port()
316 realm:coreSpace.realm()
317 authenticationMethod:method] autorelease];
318 return [[[NSURLProtectionSpace alloc] initWithHost:coreSpace.host()
319 port:coreSpace.port()
321 realm:coreSpace.realm()
322 authenticationMethod:method] autorelease];
325 NSURLCredential *mac(const Credential& coreCredential)
327 if (coreCredential.isEmpty())
330 NSURLCredentialPersistence persistence = NSURLCredentialPersistenceNone;
331 switch (coreCredential.persistence()) {
332 case CredentialPersistenceNone:
334 case CredentialPersistenceForSession:
335 persistence = NSURLCredentialPersistenceForSession;
337 case CredentialPersistencePermanent:
338 persistence = NSURLCredentialPersistencePermanent;
341 ASSERT_NOT_REACHED();
344 #if CERTIFICATE_CREDENTIALS_SUPPORTED
345 if (coreCredential.type() == CredentialTypeClientCertificate) {
346 return [[[NSURLCredential alloc] initWithIdentity:coreCredential.identity()
347 certificates:(NSArray *)coreCredential.certificates()
348 persistence:persistence]
353 return [[[NSURLCredential alloc] initWithUser:coreCredential.user()
354 password:coreCredential.password()
355 persistence:persistence]
359 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge)
361 return AuthenticationChallenge(macChallenge);
364 ProtectionSpace core(NSURLProtectionSpace *macSpace)
366 ProtectionSpaceServerType serverType = ProtectionSpaceProxyHTTP;
368 if ([macSpace isProxy]) {
369 NSString *proxyType = [macSpace proxyType];
370 if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPProxy])
371 serverType = ProtectionSpaceProxyHTTP;
372 else if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPSProxy])
373 serverType = ProtectionSpaceProxyHTTPS;
374 else if ([proxyType isEqualToString:NSURLProtectionSpaceFTPProxy])
375 serverType = ProtectionSpaceProxyFTP;
376 else if ([proxyType isEqualToString:NSURLProtectionSpaceSOCKSProxy])
377 serverType = ProtectionSpaceProxySOCKS;
379 ASSERT_NOT_REACHED();
381 NSString *protocol = [macSpace protocol];
382 if ([protocol caseInsensitiveCompare:@"http"] == NSOrderedSame)
383 serverType = ProtectionSpaceServerHTTP;
384 else if ([protocol caseInsensitiveCompare:@"https"] == NSOrderedSame)
385 serverType = ProtectionSpaceServerHTTPS;
386 else if ([protocol caseInsensitiveCompare:@"ftp"] == NSOrderedSame)
387 serverType = ProtectionSpaceServerFTP;
388 else if ([protocol caseInsensitiveCompare:@"ftps"] == NSOrderedSame)
389 serverType = ProtectionSpaceServerFTPS;
391 ASSERT_NOT_REACHED();
394 ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault;
395 NSString *method = [macSpace authenticationMethod];
396 if ([method isEqualToString:NSURLAuthenticationMethodDefault])
397 scheme = ProtectionSpaceAuthenticationSchemeDefault;
398 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPBasic])
399 scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
400 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPDigest])
401 scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
402 else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm])
403 scheme = ProtectionSpaceAuthenticationSchemeHTMLForm;
404 else if ([method isEqualToString:NSURLAuthenticationMethodNTLM])
405 scheme = ProtectionSpaceAuthenticationSchemeNTLM;
406 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
407 else if ([method isEqualToString:NSURLAuthenticationMethodClientCertificate])
408 scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested;
409 else if ([method isEqualToString:NSURLAuthenticationMethodServerTrust])
410 scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
413 scheme = ProtectionSpaceAuthenticationSchemeUnknown;
414 ASSERT_NOT_REACHED();
417 return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme);
421 Credential core(NSURLCredential *macCredential)
423 CredentialPersistence persistence = CredentialPersistenceNone;
424 switch ([macCredential persistence]) {
425 case NSURLCredentialPersistenceNone:
427 case NSURLCredentialPersistenceForSession:
428 persistence = CredentialPersistenceForSession;
430 case NSURLCredentialPersistencePermanent:
431 persistence = CredentialPersistencePermanent;
434 ASSERT_NOT_REACHED();
437 #if CERTIFICATE_CREDENTIALS_SUPPORTED
438 SecIdentityRef identity = [macCredential identity];
440 return Credential(identity, (CFArrayRef)[macCredential certificates], persistence);
443 return Credential([macCredential user], [macCredential password], persistence);
446 #endif // USE(CFNETWORK)
448 } // namespace WebCore