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 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 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#include <CFNetwork/CFURLAuthChallengePriv.h>
36#include <CFNetwork/CFURLCredentialPriv.h>
37#include <CFNetwork/CFURLProtectionSpacePriv.h>
38
39namespace WebCore {
40
41AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace,
42                                                 const Credential& proposedCredential,
43                                                 unsigned previousFailureCount,
44                                                 const ResourceResponse& response,
45                                                 const ResourceError& error)
46    : AuthenticationChallengeBase(protectionSpace,
47                                  proposedCredential,
48                                  previousFailureCount,
49                                  response,
50                                  error)
51{
52}
53
54AuthenticationChallenge::AuthenticationChallenge(CFURLAuthChallengeRef cfChallenge,
55                                                 AuthenticationClient* authenticationClient)
56#if PLATFORM(COCOA)
57    : AuthenticationChallengeBase(ProtectionSpace(CFURLAuthChallengeGetProtectionSpace(cfChallenge)),
58#else
59    : AuthenticationChallengeBase(core(CFURLAuthChallengeGetProtectionSpace(cfChallenge)),
60#endif
61                                  core(CFURLAuthChallengeGetProposedCredential(cfChallenge)),
62                                  CFURLAuthChallengeGetPreviousFailureCount(cfChallenge),
63                                  (CFURLResponseRef)CFURLAuthChallengeGetFailureResponse(cfChallenge),
64                                  CFURLAuthChallengeGetError(cfChallenge))
65    , m_authenticationClient(authenticationClient)
66    , m_cfChallenge(cfChallenge)
67{
68}
69
70void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client)
71{
72    m_authenticationClient = client;
73}
74
75AuthenticationClient* AuthenticationChallenge::authenticationClient() const
76{
77    return m_authenticationClient.get();
78}
79
80bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
81{
82    if (a.authenticationClient() != b.authenticationClient())
83        return false;
84
85    if (a.cfURLAuthChallengeRef() != b.cfURLAuthChallengeRef())
86        return false;
87
88    return true;
89}
90
91CFURLAuthChallengeRef createCF(const AuthenticationChallenge& coreChallenge)
92{
93    // FIXME: Why not cache CFURLAuthChallengeRef in m_cfChallenge? Foundation counterpart does that.
94
95    CFURLCredentialRef credential = createCF(coreChallenge.proposedCredential());
96
97#if PLATFORM(COCOA)
98    CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, coreChallenge.protectionSpace().cfSpace(), credential,
99#else
100    RetainPtr<CFURLProtectionSpaceRef> protectionSpace = adoptCF(createCF(coreChallenge.protectionSpace()));
101
102    CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, protectionSpace.get(), credential,
103#endif
104                                        coreChallenge.previousFailureCount(),
105                                        coreChallenge.failureResponse().cfURLResponse(),
106                                        coreChallenge.error());
107    CFRelease(credential);
108    return result;
109}
110
111CFURLCredentialRef createCF(const Credential& coreCredential)
112{
113    CFURLCredentialPersistence persistence = kCFURLCredentialPersistenceNone;
114    switch (coreCredential.persistence()) {
115    case CredentialPersistenceNone:
116        break;
117    case CredentialPersistenceForSession:
118        persistence = kCFURLCredentialPersistenceForSession;
119        break;
120    case CredentialPersistencePermanent:
121        persistence = kCFURLCredentialPersistencePermanent;
122        break;
123    default:
124        ASSERT_NOT_REACHED();
125    }
126
127#if CERTIFICATE_CREDENTIALS_SUPPORTED
128    if (coreCredential.type() == CredentialTypeClientCertificate)
129        return CFURLCredentialCreateWithIdentityAndCertificateArray(kCFAllocatorDefault, coreCredential.identity(), coreCredential.certificates(), persistence);
130#endif
131
132    return CFURLCredentialCreate(0, coreCredential.user().createCFString().get(), coreCredential.password().createCFString().get(), 0, persistence);
133}
134
135#if PLATFORM(WIN)
136CFURLProtectionSpaceRef 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#endif // PLATFORM(WIN)
203
204Credential core(CFURLCredentialRef cfCredential)
205{
206    if (!cfCredential)
207        return Credential();
208
209    CredentialPersistence persistence = CredentialPersistenceNone;
210    switch (CFURLCredentialGetPersistence(cfCredential)) {
211    case kCFURLCredentialPersistenceNone:
212        break;
213    case kCFURLCredentialPersistenceForSession:
214        persistence = CredentialPersistenceForSession;
215        break;
216    case kCFURLCredentialPersistencePermanent:
217        persistence = CredentialPersistencePermanent;
218        break;
219    default:
220        ASSERT_NOT_REACHED();
221    }
222
223#if CERTIFICATE_CREDENTIALS_SUPPORTED
224    SecIdentityRef identity = CFURLCredentialGetCertificateIdentity(cfCredential);
225    if (identity)
226        return Credential(identity, CFURLCredentialGetCertificateArray(cfCredential), persistence);
227#endif
228
229    RetainPtr<CFStringRef> password = adoptCF(CFURLCredentialCopyPassword(cfCredential));
230    return Credential(CFURLCredentialGetUsername(cfCredential), password.get(), persistence);
231}
232
233#if PLATFORM(WIN)
234ProtectionSpace core(CFURLProtectionSpaceRef cfSpace)
235{
236    ProtectionSpaceServerType serverType = ProtectionSpaceServerHTTP;
237
238    switch (CFURLProtectionSpaceGetServerType(cfSpace)) {
239    case kCFURLProtectionSpaceServerHTTP:
240        break;
241    case kCFURLProtectionSpaceServerHTTPS:
242        serverType = ProtectionSpaceServerHTTPS;
243        break;
244    case kCFURLProtectionSpaceServerFTP:
245        serverType = ProtectionSpaceServerFTP;
246        break;
247    case kCFURLProtectionSpaceServerFTPS:
248        serverType = ProtectionSpaceServerFTPS;
249        break;
250    case kCFURLProtectionSpaceProxyHTTP:
251        serverType = ProtectionSpaceProxyHTTP;
252        break;
253    case kCFURLProtectionSpaceProxyHTTPS:
254        serverType = ProtectionSpaceProxyHTTPS;
255        break;
256    case kCFURLProtectionSpaceProxyFTP:
257        serverType = ProtectionSpaceProxyFTP;
258        break;
259    case kCFURLProtectionSpaceProxySOCKS:
260        serverType = ProtectionSpaceProxySOCKS;
261        break;
262    default:
263        ASSERT_NOT_REACHED();
264    }
265
266    ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault;
267
268    switch (CFURLProtectionSpaceGetAuthenticationScheme(cfSpace)) {
269    case kCFURLProtectionSpaceAuthenticationSchemeDefault:
270        scheme = ProtectionSpaceAuthenticationSchemeDefault;
271        break;
272    case kCFURLProtectionSpaceAuthenticationSchemeHTTPBasic:
273        scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic;
274        break;
275    case kCFURLProtectionSpaceAuthenticationSchemeHTTPDigest:
276        scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
277        break;
278    case kCFURLProtectionSpaceAuthenticationSchemeHTMLForm:
279        scheme = ProtectionSpaceAuthenticationSchemeHTMLForm;
280        break;
281    case kCFURLProtectionSpaceAuthenticationSchemeNTLM:
282        scheme = ProtectionSpaceAuthenticationSchemeNTLM;
283        break;
284    case kCFURLProtectionSpaceAuthenticationSchemeNegotiate:
285        scheme = ProtectionSpaceAuthenticationSchemeNegotiate;
286        break;
287#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
288    case kCFURLProtectionSpaceAuthenticationSchemeClientCertificateRequested:
289        scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested;
290        break;
291    case kCFURLProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
292        scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
293        break;
294#endif
295    default:
296        scheme = ProtectionSpaceAuthenticationSchemeUnknown;
297        ASSERT_NOT_REACHED();
298    }
299
300    return ProtectionSpace(CFURLProtectionSpaceGetHost(cfSpace),
301                           CFURLProtectionSpaceGetPort(cfSpace),
302                           serverType,
303                           CFURLProtectionSpaceGetRealm(cfSpace),
304                           scheme);
305}
306#endif // PLATFORM(WIN)
307
308};
309
310#endif // USE(CFNETWORK)
311