<http://webkit.org/b/91015> Remove BUILDING_ON / TARGETING macros in favor of system...
[WebKit-https.git] / Source / WebCore / platform / network / mac / AuthenticationMac.mm
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 "AuthenticationCF.h"
29 #import "AuthenticationChallenge.h"
30 #import "AuthenticationClient.h"
31 #import "Credential.h"
32 #import "ProtectionSpace.h"
33
34 #import <Foundation/NSURLAuthenticationChallenge.h>
35 #import <Foundation/NSURLCredential.h>
36 #import <Foundation/NSURLProtectionSpace.h>
37
38 #if USE(CFNETWORK)
39
40 @interface NSURLProtectionSpace (Details)
41 - (CFURLProtectionSpaceRef) _cfurlprotectionspace;
42 - (id)_initWithCFURLProtectionSpace:(CFURLProtectionSpaceRef)cfProtSpace;
43 @end
44
45 @interface NSURLAuthenticationChallenge (Details)
46 +(NSURLAuthenticationChallenge *)_authenticationChallengeForCFAuthChallenge:(CFURLAuthChallengeRef)cfChallenge sender:(id <NSURLAuthenticationChallengeSender>)sender;
47 @end
48
49 @interface NSURLCredential (Details)
50 - (id) _initWithCFURLCredential:(CFURLCredentialRef)credential;
51 - (CFURLCredentialRef) _cfurlcredential;
52 @end
53
54 #endif
55
56 using namespace WebCore;
57
58 @interface WebCoreAuthenticationClientAsChallengeSender : NSObject <NSURLAuthenticationChallengeSender>
59 {
60     AuthenticationClient* m_client;
61 #if USE(CFNETWORK)
62     CFURLAuthChallengeRef m_cfChallenge;
63 #endif
64 }
65 - (id)initWithAuthenticationClient:(AuthenticationClient*)client;
66 - (AuthenticationClient*)client;
67 - (void)detachClient;
68 @end
69
70 @implementation WebCoreAuthenticationClientAsChallengeSender
71
72 - (id)initWithAuthenticationClient:(AuthenticationClient*)client
73 {
74     self = [self init];
75     if (!self)
76         return nil;
77     m_client = client;
78     return self;
79 }
80
81 - (AuthenticationClient*)client
82 {
83     return m_client;
84 }
85
86 - (void)detachClient
87 {
88     m_client = 0;
89 }
90
91 - (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
92 {
93     if (m_client)
94         m_client->receivedCredential(core(challenge), core(credential));
95 }
96
97 - (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
98 {
99     if (m_client)
100         m_client->receivedRequestToContinueWithoutCredential(core(challenge));
101 }
102
103 - (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
104 {
105     if (m_client)
106         m_client->receivedCancellation(core(challenge));
107 }
108
109 #if USE(CFNETWORK)
110 - (void)setCFChallenge:(CFURLAuthChallengeRef)challenge
111 {
112     m_cfChallenge = challenge;
113 }
114
115 - (CFURLAuthChallengeRef)cfChallenge
116 {
117     return m_cfChallenge;
118 }
119 #endif
120
121 @end
122
123 namespace WebCore {
124
125 #if USE(CFNETWORK)
126
127 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge)
128 {
129     WebCoreAuthenticationClientAsChallengeSender *challengeSender = (WebCoreAuthenticationClientAsChallengeSender*) [macChallenge sender];
130     return AuthenticationChallenge([challengeSender cfChallenge], [challengeSender client]);
131 }
132
133 Credential core(NSURLCredential *macCredential)
134 {
135     return core([macCredential _cfurlcredential]);
136 }
137
138 ProtectionSpace core(NSURLProtectionSpace *macSpace)
139 {
140     return core([macSpace _cfurlprotectionspace]);
141 }
142
143 NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
144 {
145     RetainPtr<CFURLProtectionSpaceRef> protectionSpace(AdoptCF, createCF(coreSpace));
146     return [[[NSURLProtectionSpace alloc] _initWithCFURLProtectionSpace:protectionSpace.get()] autorelease];
147 }
148
149 NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge)
150 {
151     AuthenticationClient* authClient = coreChallenge.authenticationClient();
152     RetainPtr<WebCoreAuthenticationClientAsChallengeSender> challengeSender(AdoptNS, [[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:authClient]);
153     RetainPtr<CFURLAuthChallengeRef> authChallenge = coreChallenge.cfURLAuthChallengeRef();
154     if (!authChallenge)
155         authChallenge.adoptCF(createCF(coreChallenge));
156     [challengeSender.get() setCFChallenge:authChallenge.get()];
157     return [[NSURLAuthenticationChallenge _authenticationChallengeForCFAuthChallenge:authChallenge.get() sender:challengeSender.get()] autorelease];
158 }
159
160 NSURLCredential *mac(const Credential& coreCredential)
161 {
162     RetainPtr<CFURLCredentialRef> credential(AdoptCF, createCF(coreCredential));
163     return [[[NSURLCredential alloc] _initWithCFURLCredential:credential.get()] autorelease];
164 }
165
166 #else
167
168 #if __MAC_OS_X_VERSION_MIN_REQUIRED == 1050
169 // There is no constant in headers, but NTLM is supported.
170 NSString * const NSURLAuthenticationMethodNTLM = @"NSURLAuthenticationMethodNTLM";
171 #endif
172
173
174 AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
175                                                  const Credential& proposedCredential,
176                                                  unsigned previousFailureCount,
177                                                  const ResourceResponse& response,
178                                                  const ResourceError& error)
179     : AuthenticationChallengeBase(protectionSpace,
180                                   proposedCredential,
181                                   previousFailureCount,
182                                   response,
183                                   error)
184 {
185 }
186
187 AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *challenge)
188     : AuthenticationChallengeBase(core([challenge protectionSpace]),
189                                   core([challenge proposedCredential]),
190                                   [challenge previousFailureCount],
191                                   [challenge failureResponse],
192                                   [challenge error])
193     , m_sender([challenge sender])
194     , m_nsChallenge(challenge)
195 {
196 }
197
198 void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client)
199 {
200     if (client) {
201         m_sender.adoptNS([[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:client]);
202         m_nsChallenge.adoptNS([[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:m_nsChallenge.get() sender:m_sender.get()]);
203     } else {
204         if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
205             [(WebCoreAuthenticationClientAsChallengeSender *)m_sender.get() detachClient];
206     }
207 }
208
209 AuthenticationClient* AuthenticationChallenge::authenticationClient() const
210 {
211     if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
212         return [static_cast<WebCoreAuthenticationClientAsChallengeSender*>(m_sender.get()) client];
213     
214     return 0;
215 }
216
217 bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
218 {
219     if (a.sender() != b.sender())
220         return false;
221         
222     if (a.nsURLAuthenticationChallenge() != b.nsURLAuthenticationChallenge())
223         return false;
224
225     return true;
226 }
227
228 NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge)
229 {
230     if (coreChallenge.nsURLAuthenticationChallenge())
231         return coreChallenge.nsURLAuthenticationChallenge();
232         
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];
239 }
240
241 NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
242 {
243     NSString *proxyType = nil;
244     NSString *protocol = nil;
245     switch (coreSpace.serverType()) {
246         case ProtectionSpaceServerHTTP:
247             protocol = @"http";
248             break;
249         case ProtectionSpaceServerHTTPS:
250             protocol = @"https";
251             break;
252         case ProtectionSpaceServerFTP:
253             protocol = @"ftp";
254             break;
255         case ProtectionSpaceServerFTPS:
256             protocol = @"ftps";
257             break;
258         case ProtectionSpaceProxyHTTP:
259             proxyType = NSURLProtectionSpaceHTTPProxy;
260             break;
261         case ProtectionSpaceProxyHTTPS:
262             proxyType = NSURLProtectionSpaceHTTPSProxy;
263             break;
264         case ProtectionSpaceProxyFTP:
265             proxyType = NSURLProtectionSpaceFTPProxy;
266             break;
267         case ProtectionSpaceProxySOCKS:
268             proxyType = NSURLProtectionSpaceSOCKSProxy;
269             break;
270         default:
271             ASSERT_NOT_REACHED();
272     }
273   
274     NSString *method = nil;
275     switch (coreSpace.authenticationScheme()) {
276         case ProtectionSpaceAuthenticationSchemeDefault:
277             method = NSURLAuthenticationMethodDefault;
278             break;
279         case ProtectionSpaceAuthenticationSchemeHTTPBasic:
280             method = NSURLAuthenticationMethodHTTPBasic;
281             break;
282         case ProtectionSpaceAuthenticationSchemeHTTPDigest:
283             method = NSURLAuthenticationMethodHTTPDigest;
284             break;
285         case ProtectionSpaceAuthenticationSchemeHTMLForm:
286             method = NSURLAuthenticationMethodHTMLForm;
287             break;
288         case ProtectionSpaceAuthenticationSchemeNTLM:
289             method = NSURLAuthenticationMethodNTLM;
290             break;
291 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
292         case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
293             method = NSURLAuthenticationMethodServerTrust;
294             break;
295         case ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
296             method = NSURLAuthenticationMethodClientCertificate;
297             break;
298 #endif
299         default:
300             ASSERT_NOT_REACHED();
301     }
302     
303     if (proxyType)
304         return [[[NSURLProtectionSpace alloc] initWithProxyHost:coreSpace.host()
305                                                            port:coreSpace.port()
306                                                            type:proxyType
307                                                           realm:coreSpace.realm()
308                                            authenticationMethod:method] autorelease];
309     return [[[NSURLProtectionSpace alloc] initWithHost:coreSpace.host()
310                                                   port:coreSpace.port()
311                                               protocol:protocol
312                                                  realm:coreSpace.realm()
313                                   authenticationMethod:method] autorelease];
314 }
315
316 NSURLCredential *mac(const Credential& coreCredential)
317 {
318     if (coreCredential.isEmpty())
319         return nil;
320
321     NSURLCredentialPersistence persistence = NSURLCredentialPersistenceNone;
322     switch (coreCredential.persistence()) {
323         case CredentialPersistenceNone:
324             break;
325         case CredentialPersistenceForSession:
326             persistence = NSURLCredentialPersistenceForSession;
327             break;
328         case CredentialPersistencePermanent:
329             persistence = NSURLCredentialPersistencePermanent;
330             break;
331         default:
332             ASSERT_NOT_REACHED();
333     }
334
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]
340                                               autorelease];
341     }
342 #endif
343
344     return [[[NSURLCredential alloc] initWithUser:coreCredential.user()
345                                         password:coreCredential.password()
346                                      persistence:persistence]
347                                      autorelease];
348 }
349
350 AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge)
351 {
352     return AuthenticationChallenge(macChallenge);
353 }
354
355 ProtectionSpace core(NSURLProtectionSpace *macSpace)
356 {
357     ProtectionSpaceServerType serverType = ProtectionSpaceProxyHTTP;
358     
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;
369         else 
370             ASSERT_NOT_REACHED();
371     } else {
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;
381         else
382             ASSERT_NOT_REACHED();
383     }
384
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;
402 #endif
403     else {
404         scheme = ProtectionSpaceAuthenticationSchemeUnknown;
405         ASSERT_NOT_REACHED();
406     }
407         
408     return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme);
409
410 }
411
412 Credential core(NSURLCredential *macCredential)
413 {
414     CredentialPersistence persistence = CredentialPersistenceNone;
415     switch ([macCredential persistence]) {
416         case NSURLCredentialPersistenceNone:
417             break;
418         case NSURLCredentialPersistenceForSession:
419             persistence = CredentialPersistenceForSession;
420             break;
421         case NSURLCredentialPersistencePermanent:
422             persistence = CredentialPersistencePermanent;
423             break;
424         default:
425             ASSERT_NOT_REACHED();
426     }
427
428 #if CERTIFICATE_CREDENTIALS_SUPPORTED
429     SecIdentityRef identity = [macCredential identity];
430     if (identity)
431         return Credential(identity, (CFArrayRef)[macCredential certificates], persistence);
432 #endif
433     
434     return Credential([macCredential user], [macCredential password], persistence);
435 }
436
437 #endif // USE(CFNETWORK)
438
439 } // namespace WebCore