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 39 using 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 91 namespace WebCore { 92 93 #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) 94 // There is no constant in headers, but NTLM is supported. 95 NSString * const NSURLAuthenticationMethodNTLM = @"NSURLAuthenticationMethodNTLM"; 96 #endif 97 98 99 AuthenticationChallenge::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 112 AuthenticationChallenge::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 123 void 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 134 AuthenticationClient* 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 142 bool 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 153 NSURLAuthenticationChallenge *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 166 NSURLProtectionSpace *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 241 NSURLCredential *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 275 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge) 276 { 277 return AuthenticationChallenge(macChallenge); 278 } 279 280 ProtectionSpace 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 337 Credential 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