Home | History | Annotate | Download | only in mac
      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