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