1/* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 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. 12 * 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. 24 */ 25#import "config.h" 26#import "AuthenticationMac.h" 27 28#if !USE(CFNETWORK) 29 30#import "AuthenticationChallenge.h" 31#import "AuthenticationClient.h" 32#import "Credential.h" 33#import "ProtectionSpace.h" 34 35#import <Foundation/NSURLAuthenticationChallenge.h> 36#import <Foundation/NSURLCredential.h> 37#import <Foundation/NSURLProtectionSpace.h> 38 39using namespace WebCore; 40 41@interface WebCoreAuthenticationClientAsChallengeSender : NSObject <NSURLAuthenticationChallengeSender> 42{ 43 AuthenticationClient* m_client; 44} 45- (id)initWithAuthenticationClient:(AuthenticationClient*)client; 46- (AuthenticationClient*)client; 47- (void)detachClient; 48@end 49 50@implementation WebCoreAuthenticationClientAsChallengeSender 51 52- (id)initWithAuthenticationClient:(AuthenticationClient*)client 53{ 54 self = [self init]; 55 if (!self) 56 return nil; 57 m_client = client; 58 return self; 59} 60 61- (AuthenticationClient*)client 62{ 63 return m_client; 64} 65 66- (void)detachClient 67{ 68 m_client = 0; 69} 70 71- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 72{ 73 if (m_client) 74 m_client->receivedCredential(core(challenge), core(credential)); 75} 76 77- (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 78{ 79 if (m_client) 80 m_client->receivedRequestToContinueWithoutCredential(core(challenge)); 81} 82 83- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 84{ 85 if (m_client) 86 m_client->receivedCancellation(core(challenge)); 87} 88 89@end 90 91namespace WebCore { 92 93#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) 94// There is no constant in headers, but NTLM is supported. 95NSString * const NSURLAuthenticationMethodNTLM = @"NSURLAuthenticationMethodNTLM"; 96#endif 97 98 99AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace, 100 const Credential& proposedCredential, 101 unsigned previousFailureCount, 102 const ResourceResponse& response, 103 const ResourceError& error) 104 : AuthenticationChallengeBase(protectionSpace, 105 proposedCredential, 106 previousFailureCount, 107 response, 108 error) 109{ 110} 111 112AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *challenge) 113 : AuthenticationChallengeBase(core([challenge protectionSpace]), 114 core([challenge proposedCredential]), 115 [challenge previousFailureCount], 116 [challenge failureResponse], 117 [challenge error]) 118 , m_sender([challenge sender]) 119 , m_nsChallenge(challenge) 120{ 121} 122 123void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client) 124{ 125 if (client) { 126 m_sender.adoptNS([[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:client]); 127 m_nsChallenge.adoptNS([[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:m_nsChallenge.get() sender:m_sender.get()]); 128 } else { 129 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]]) 130 [(WebCoreAuthenticationClientAsChallengeSender *)m_sender.get() detachClient]; 131 } 132} 133 134AuthenticationClient* AuthenticationChallenge::authenticationClient() const 135{ 136 if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]]) 137 return [static_cast<WebCoreAuthenticationClientAsChallengeSender*>(m_sender.get()) client]; 138 139 return 0; 140} 141 142bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b) 143{ 144 if (a.sender() != b.sender()) 145 return false; 146 147 if (a.nsURLAuthenticationChallenge() != b.nsURLAuthenticationChallenge()) 148 return false; 149 150 return true; 151} 152 153NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge) 154{ 155 if (coreChallenge.nsURLAuthenticationChallenge()) 156 return coreChallenge.nsURLAuthenticationChallenge(); 157 158 return [[[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:mac(coreChallenge.protectionSpace()) 159 proposedCredential:mac(coreChallenge.proposedCredential()) 160 previousFailureCount:coreChallenge.previousFailureCount() 161 failureResponse:coreChallenge.failureResponse().nsURLResponse() 162 error:coreChallenge.error() 163 sender:coreChallenge.sender()] autorelease]; 164} 165 166NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace) 167{ 168 NSString *proxyType = nil; 169 NSString *protocol = nil; 170 switch (coreSpace.serverType()) { 171 case ProtectionSpaceServerHTTP: 172 protocol = @"http"; 173 break; 174 case ProtectionSpaceServerHTTPS: 175 protocol = @"https"; 176 break; 177 case ProtectionSpaceServerFTP: 178 protocol = @"ftp"; 179 break; 180 case ProtectionSpaceServerFTPS: 181 protocol = @"ftps"; 182 break; 183 case ProtectionSpaceProxyHTTP: 184 proxyType = NSURLProtectionSpaceHTTPProxy; 185 break; 186 case ProtectionSpaceProxyHTTPS: 187 proxyType = NSURLProtectionSpaceHTTPSProxy; 188 break; 189 case ProtectionSpaceProxyFTP: 190 proxyType = NSURLProtectionSpaceFTPProxy; 191 break; 192 case ProtectionSpaceProxySOCKS: 193 proxyType = NSURLProtectionSpaceSOCKSProxy; 194 break; 195 default: 196 ASSERT_NOT_REACHED(); 197 } 198 199 NSString *method = nil; 200 switch (coreSpace.authenticationScheme()) { 201 case ProtectionSpaceAuthenticationSchemeDefault: 202 method = NSURLAuthenticationMethodDefault; 203 break; 204 case ProtectionSpaceAuthenticationSchemeHTTPBasic: 205 method = NSURLAuthenticationMethodHTTPBasic; 206 break; 207 case ProtectionSpaceAuthenticationSchemeHTTPDigest: 208 method = NSURLAuthenticationMethodHTTPDigest; 209 break; 210 case ProtectionSpaceAuthenticationSchemeHTMLForm: 211 method = NSURLAuthenticationMethodHTMLForm; 212 break; 213 case ProtectionSpaceAuthenticationSchemeNTLM: 214 method = NSURLAuthenticationMethodNTLM; 215 break; 216#if USE(PROTECTION_SPACE_AUTH_CALLBACK) 217 case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested: 218 method = NSURLAuthenticationMethodServerTrust; 219 break; 220 case ProtectionSpaceAuthenticationSchemeClientCertificateRequested: 221 method = NSURLAuthenticationMethodClientCertificate; 222 break; 223#endif 224 default: 225 ASSERT_NOT_REACHED(); 226 } 227 228 if (proxyType) 229 return [[[NSURLProtectionSpace alloc] initWithProxyHost:coreSpace.host() 230 port:coreSpace.port() 231 type:proxyType 232 realm:coreSpace.realm() 233 authenticationMethod:method] autorelease]; 234 return [[[NSURLProtectionSpace alloc] initWithHost:coreSpace.host() 235 port:coreSpace.port() 236 protocol:protocol 237 realm:coreSpace.realm() 238 authenticationMethod:method] autorelease]; 239} 240 241NSURLCredential *mac(const Credential& coreCredential) 242{ 243 if (coreCredential.isEmpty()) 244 return nil; 245 246 NSURLCredentialPersistence persistence = NSURLCredentialPersistenceNone; 247 switch (coreCredential.persistence()) { 248 case CredentialPersistenceNone: 249 break; 250 case CredentialPersistenceForSession: 251 persistence = NSURLCredentialPersistenceForSession; 252 break; 253 case CredentialPersistencePermanent: 254 persistence = NSURLCredentialPersistencePermanent; 255 break; 256 default: 257 ASSERT_NOT_REACHED(); 258 } 259 260#if CERTIFICATE_CREDENTIALS_SUPPORTED 261 if (coreCredential.type() == CredentialTypeClientCertificate) { 262 return [[[NSURLCredential alloc] initWithIdentity:coreCredential.identity() 263 certificates:(NSArray *)coreCredential.certificates() 264 persistence:persistence] 265 autorelease]; 266 } 267#endif 268 269 return [[[NSURLCredential alloc] initWithUser:coreCredential.user() 270 password:coreCredential.password() 271 persistence:persistence] 272 autorelease]; 273} 274 275AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge) 276{ 277 return AuthenticationChallenge(macChallenge); 278} 279 280ProtectionSpace core(NSURLProtectionSpace *macSpace) 281{ 282 ProtectionSpaceServerType serverType = ProtectionSpaceProxyHTTP; 283 284 if ([macSpace isProxy]) { 285 NSString *proxyType = [macSpace proxyType]; 286 if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPProxy]) 287 serverType = ProtectionSpaceProxyHTTP; 288 else if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPSProxy]) 289 serverType = ProtectionSpaceProxyHTTPS; 290 else if ([proxyType isEqualToString:NSURLProtectionSpaceFTPProxy]) 291 serverType = ProtectionSpaceProxyFTP; 292 else if ([proxyType isEqualToString:NSURLProtectionSpaceSOCKSProxy]) 293 serverType = ProtectionSpaceProxySOCKS; 294 else 295 ASSERT_NOT_REACHED(); 296 } else { 297 NSString *protocol = [macSpace protocol]; 298 if ([protocol caseInsensitiveCompare:@"http"] == NSOrderedSame) 299 serverType = ProtectionSpaceServerHTTP; 300 else if ([protocol caseInsensitiveCompare:@"https"] == NSOrderedSame) 301 serverType = ProtectionSpaceServerHTTPS; 302 else if ([protocol caseInsensitiveCompare:@"ftp"] == NSOrderedSame) 303 serverType = ProtectionSpaceServerFTP; 304 else if ([protocol caseInsensitiveCompare:@"ftps"] == NSOrderedSame) 305 serverType = ProtectionSpaceServerFTPS; 306 else 307 ASSERT_NOT_REACHED(); 308 } 309 310 ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault; 311 NSString *method = [macSpace authenticationMethod]; 312 if ([method isEqualToString:NSURLAuthenticationMethodDefault]) 313 scheme = ProtectionSpaceAuthenticationSchemeDefault; 314 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPBasic]) 315 scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; 316 else if ([method isEqualToString:NSURLAuthenticationMethodHTTPDigest]) 317 scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; 318 else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm]) 319 scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; 320 else if ([method isEqualToString:NSURLAuthenticationMethodNTLM]) 321 scheme = ProtectionSpaceAuthenticationSchemeNTLM; 322#if USE(PROTECTION_SPACE_AUTH_CALLBACK) 323 else if ([method isEqualToString:NSURLAuthenticationMethodClientCertificate]) 324 scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested; 325 else if ([method isEqualToString:NSURLAuthenticationMethodServerTrust]) 326 scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested; 327#endif 328 else { 329 scheme = ProtectionSpaceAuthenticationSchemeUnknown; 330 ASSERT_NOT_REACHED(); 331 } 332 333 return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme); 334 335} 336 337Credential core(NSURLCredential *macCredential) 338{ 339 CredentialPersistence persistence = CredentialPersistenceNone; 340 switch ([macCredential persistence]) { 341 case NSURLCredentialPersistenceNone: 342 break; 343 case NSURLCredentialPersistenceForSession: 344 persistence = CredentialPersistenceForSession; 345 break; 346 case NSURLCredentialPersistencePermanent: 347 persistence = CredentialPersistencePermanent; 348 break; 349 default: 350 ASSERT_NOT_REACHED(); 351 } 352 353#if CERTIFICATE_CREDENTIALS_SUPPORTED 354 SecIdentityRef identity = [macCredential identity]; 355 if (identity) 356 return Credential(identity, (CFArrayRef)[macCredential certificates], persistence); 357#endif 358 359 return Credential([macCredential user], [macCredential password], persistence); 360} 361 362} // namespace WebCore 363 364#endif // !USE(CFNETWORK) 365