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