c1f7711bc3624044d240dc7d9423667bba0599d7
[WebKit-https.git] / Source / WebCore / platform / network / cf / AuthenticationCF.cpp
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
26 #include "config.h"
27 #include "AuthenticationCF.h"
28
29 #if USE(CFNETWORK)
30
31 #include "AuthenticationChallenge.h"
32 #include "AuthenticationClient.h"
33 #include "Credential.h"
34 #include "ProtectionSpace.h"
35
36 // This header must come before all other CFNetwork headers to work around a CFNetwork bug. It can
37 // be removed entirely once <rdar://problem/9042114> is fixed.
38 #include <CFNetwork/CFURLConnectionPriv.h>
39
40 #include <CFNetwork/CFURLAuthChallengePriv.h>
41 #include <CFNetwork/CFURLCredentialPriv.h>
42 #include <CFNetwork/CFURLProtectionSpacePriv.h>
43
44 namespace WebCore {
45
46 static uint64_t generateUniqueIdentifier()
47 {
48     static uint64_t uniqueIdentifier;
49     return ++uniqueIdentifier;
50 }
51
52 AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
53                                                  const Credential& proposedCredential,
54                                                  unsigned previousFailureCount,
55                                                  const ResourceResponse& response,
56                                                  const ResourceError& error,
57                                                  uint64_t identifier)
58     : AuthenticationChallengeBase(protectionSpace,
59                                   proposedCredential,
60                                   previousFailureCount,
61                                   response,
62                                   error)
63 {
64     m_identifier = identifier;
65 }
66
67 AuthenticationChallenge::AuthenticationChallenge(CFURLAuthChallengeRef cfChallenge,
68                                                  AuthenticationClient* authenticationClient)
69     : AuthenticationChallengeBase(core(CFURLAuthChallengeGetProtectionSpace(cfChallenge)),
70                                   core(CFURLAuthChallengeGetProposedCredential(cfChallenge)),
71                                   CFURLAuthChallengeGetPreviousFailureCount(cfChallenge),
72                                   (CFURLResponseRef)CFURLAuthChallengeGetFailureResponse(cfChallenge),
73                                   CFURLAuthChallengeGetError(cfChallenge))
74     , m_authenticationClient(authenticationClient)
75     , m_cfChallenge(cfChallenge)
76 {
77     m_identifier = generateUniqueIdentifier();
78 }
79
80 AuthenticationClient* AuthenticationChallenge::authenticationClient() const
81 {
82     return m_authenticationClient.get();
83 }
84
85 bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
86 {
87     if (a.authenticationClient() != b.authenticationClient())
88         return false;
89
90     if (a.cfURLAuthChallengeRef() != b.cfURLAuthChallengeRef())
91         return false;
92         
93     return true;
94 }
95
96 CFURLAuthChallengeRef createCF(const AuthenticationChallenge& coreChallenge)
97 {
98     // FIXME: Why not cache CFURLAuthChallengeRef in m_cfChallenge? Foundation counterpart does that.
99
100     CFURLProtectionSpaceRef protectionSpace = createCF(coreChallenge.protectionSpace());
101     CFURLCredentialRef credential = createCF(coreChallenge.proposedCredential());
102     
103     CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, protectionSpace, credential,
104                                         coreChallenge.previousFailureCount(),
105                                         coreChallenge.failureResponse().cfURLResponse(),
106                                         coreChallenge.error());
107     CFRelease(protectionSpace);
108     CFRelease(credential);
109     return result;
110 }
111
112 CFURLCredentialRef createCF(const Credential& coreCredential)
113 {
114     CFURLCredentialPersistence persistence = kCFURLCredentialPersistenceNone;
115     switch (coreCredential.persistence()) {
116     case CredentialPersistenceNone:
117         break;
118     case CredentialPersistenceForSession:
119         persistence = kCFURLCredentialPersistenceForSession;
120         break;
121     case CredentialPersistencePermanent:
122         persistence = kCFURLCredentialPersistencePermanent;
123         break;
124     default:
125         ASSERT_NOT_REACHED();
126     }
127     
128 #if CERTIFICATE_CREDENTIALS_SUPPORTED
129     if (coreCredential.type() == CredentialTypeClientCertificate)
130         return CFURLCredentialCreateWithIdentityAndCertificateArray(kCFAllocatorDefault, coreCredential.identity(), coreCredential.certificates(), persistence);
131 #endif
132
133     return CFURLCredentialCreate(0, coreCredential.user().createCFString().get(), coreCredential.password().createCFString().get(), 0, persistence);
134 }
135
136 CFURLProtectionSpaceRef createCF(const ProtectionSpace& coreSpace)
137 {
138     CFURLProtectionSpaceServerType serverType = kCFURLProtectionSpaceServerHTTP;
139     switch (coreSpace.serverType()) {
140     case ProtectionSpaceServerHTTP:
141         serverType = kCFURLProtectionSpaceServerHTTP;
142         break;
143     case ProtectionSpaceServerHTTPS:
144         serverType = kCFURLProtectionSpaceServerHTTPS;
145         break;
146     case ProtectionSpaceServerFTP:
147         serverType = kCFURLProtectionSpaceServerFTP;
148         break;
149     case ProtectionSpaceServerFTPS:
150         serverType = kCFURLProtectionSpaceServerFTPS;
151         break;
152     case ProtectionSpaceProxyHTTP:
153         serverType = kCFURLProtectionSpaceProxyHTTP;
154         break;
155     case ProtectionSpaceProxyHTTPS:
156         serverType = kCFURLProtectionSpaceProxyHTTPS;
157         break;
158     case ProtectionSpaceProxyFTP:
159         serverType = kCFURLProtectionSpaceProxyFTP;
160         break;
161     case ProtectionSpaceProxySOCKS:
162         serverType = kCFURLProtectionSpaceProxySOCKS;
163         break;
164     default:
165         ASSERT_NOT_REACHED();
166     }
167
168     CFURLProtectionSpaceAuthenticationScheme scheme = kCFURLProtectionSpaceAuthenticationSchemeDefault;
169     switch (coreSpace.authenticationScheme()) {
170     case ProtectionSpaceAuthenticationSchemeDefault:
171         scheme = kCFURLProtectionSpaceAuthenticationSchemeDefault;
172         break;
173     case ProtectionSpaceAuthenticationSchemeHTTPBasic:
174         scheme = kCFURLProtectionSpaceAuthenticationSchemeHTTPBasic;
175         break;
176     case ProtectionSpaceAuthenticationSchemeHTTPDigest:
177         scheme = kCFURLProtectionSpaceAuthenticationSchemeHTTPDigest;
178         break;
179     case ProtectionSpaceAuthenticationSchemeHTMLForm:
180         scheme = kCFURLProtectionSpaceAuthenticationSchemeHTMLForm;
181         break;
182     case ProtectionSpaceAuthenticationSchemeNTLM:
183         scheme = kCFURLProtectionSpaceAuthenticationSchemeNTLM;
184         break;
185     case ProtectionSpaceAuthenticationSchemeNegotiate:
186         scheme = kCFURLProtectionSpaceAuthenticationSchemeNegotiate;
187         break;
188 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
189     case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
190         scheme = kCFURLProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
191         break;
192     case ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
193         scheme = kCFURLProtectionSpaceAuthenticationSchemeClientCertificateRequested;
194         break;
195 #endif
196     default:
197         ASSERT_NOT_REACHED();
198     }
199
200     return CFURLProtectionSpaceCreate(0, coreSpace.host().createCFString().get(), coreSpace.port(), serverType, coreSpace.realm().createCFString().get(), scheme);
201 }
202
203 Credential core(CFURLCredentialRef cfCredential)
204 {
205     if (!cfCredential)
206         return Credential();
207
208     CredentialPersistence persistence = CredentialPersistenceNone;
209     switch (CFURLCredentialGetPersistence(cfCredential)) {
210     case kCFURLCredentialPersistenceNone:
211         break;
212     case kCFURLCredentialPersistenceForSession:
213         persistence = CredentialPersistenceForSession;
214         break;
215     case kCFURLCredentialPersistencePermanent:
216         persistence = CredentialPersistencePermanent;
217         break;
218     default:
219         ASSERT_NOT_REACHED();
220     }
221
222 #if CERTIFICATE_CREDENTIALS_SUPPORTED
223     SecIdentityRef identity = CFURLCredentialGetCertificateIdentity(cfCredential);
224     if (identity)
225         return Credential(identity, CFURLCredentialGetCertificateArray(cfCredential), persistence);
226 #endif
227
228     RetainPtr<CFStringRef> password(AdoptCF, CFURLCredentialCopyPassword(cfCredential));
229     return Credential(CFURLCredentialGetUsername(cfCredential), password.get(), persistence);
230 }
231
232 ProtectionSpace core(CFURLProtectionSpaceRef cfSpace)
233 {
234     ProtectionSpaceServerType serverType = ProtectionSpaceServerHTTP;
235     
236     switch (CFURLProtectionSpaceGetServerType(cfSpace)) {
237     case kCFURLProtectionSpaceServerHTTP:
238         break;
239     case kCFURLProtectionSpaceServerHTTPS:
240         serverType = ProtectionSpaceServerHTTPS;
241         break;
242     case kCFURLProtectionSpaceServerFTP:
243         serverType = ProtectionSpaceServerFTP;
244         break;
245     case kCFURLProtectionSpaceServerFTPS:
246         serverType = ProtectionSpaceServerFTPS;
247         break;
248     case kCFURLProtectionSpaceProxyHTTP:
249         serverType = ProtectionSpaceProxyHTTP;
250         break;
251     case kCFURLProtectionSpaceProxyHTTPS:
252         serverType = ProtectionSpaceProxyHTTPS;
253         break;
254     case kCFURLProtectionSpaceProxyFTP:
255         serverType = ProtectionSpaceProxyFTP;
256         break;
257     case kCFURLProtectionSpaceProxySOCKS:
258         serverType = ProtectionSpaceProxySOCKS;
259         break;
260     default:
261         ASSERT_NOT_REACHED();
262     }
263
264     ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault;
265     
266     switch (CFURLProtectionSpaceGetAuthenticationScheme(cfSpace)) {
267     case kCFURLProtectionSpaceAuthenticationSchemeDefault:
268         scheme = ProtectionSpaceAuthenticationSchemeDefault;
269         break;
270     case kCFURLProtectionSpaceAuthenticationSchemeHTTPBasic:
271         scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
272         break;
273     case kCFURLProtectionSpaceAuthenticationSchemeHTTPDigest:
274         scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
275         break;
276     case kCFURLProtectionSpaceAuthenticationSchemeHTMLForm:
277         scheme = ProtectionSpaceAuthenticationSchemeHTMLForm;
278         break;
279     case kCFURLProtectionSpaceAuthenticationSchemeNTLM:
280         scheme = ProtectionSpaceAuthenticationSchemeNTLM;
281         break;
282     case kCFURLProtectionSpaceAuthenticationSchemeNegotiate:
283         scheme = ProtectionSpaceAuthenticationSchemeNegotiate;
284         break;
285 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
286     case kCFURLProtectionSpaceAuthenticationSchemeClientCertificateRequested:
287         scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested;
288         break;
289     case kCFURLProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
290         scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
291         break;
292 #endif
293     default:
294         scheme = ProtectionSpaceAuthenticationSchemeUnknown;
295         ASSERT_NOT_REACHED();
296     }
297         
298     return ProtectionSpace(CFURLProtectionSpaceGetHost(cfSpace), 
299                            CFURLProtectionSpaceGetPort(cfSpace),
300                            serverType,
301                            CFURLProtectionSpaceGetRealm(cfSpace),
302                            scheme);
303 }
304
305 };
306
307 #endif // USE(CFNETWORK)