Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/ssl_config_service_mac.h"
      6 
      7 #include <CoreFoundation/CoreFoundation.h>
      8 
      9 #include "base/scoped_cftyperef.h"
     10 
     11 using base::TimeDelta;
     12 using base::TimeTicks;
     13 
     14 namespace net {
     15 
     16 namespace {
     17 
     18 static const int kConfigUpdateInterval = 10;  // seconds
     19 
     20 static const bool kSSL2EnabledDefaultValue = false;
     21 static const bool kSSL3EnabledDefaultValue = true;
     22 static const bool kTLS1EnabledDefaultValue = true;
     23 
     24 static CFStringRef kRevocationPreferencesIdentifier =
     25     CFSTR("com.apple.security.revocation");
     26 static CFStringRef kOCSPStyleKey = CFSTR("OCSPStyle");
     27 static CFStringRef kCRLStyleKey = CFSTR("CRLStyle");
     28 static CFStringRef kNoneRevocationValue = CFSTR("None");
     29 static CFStringRef kBestAttemptRevocationValue = CFSTR("BestAttempt");
     30 static CFStringRef kSSL2EnabledKey = CFSTR("org.chromium.ssl.ssl2");
     31 static CFStringRef kSSL3EnabledKey = CFSTR("org.chromium.ssl.ssl3");
     32 static CFStringRef kTLS1EnabledKey = CFSTR("org.chromium.ssl.tls1");
     33 
     34 bool RevocationStyleIsEnabled(CFStringRef key) {
     35   CFPropertyListRef plist_ref = CFPreferencesCopyValue(key,
     36       kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser,
     37       kCFPreferencesAnyHost);
     38   if (plist_ref) {
     39     scoped_cftyperef<CFPropertyListRef> scoped_plist_ref(plist_ref);
     40     if (CFGetTypeID(plist_ref) == CFStringGetTypeID()) {
     41       CFStringRef style = reinterpret_cast<CFStringRef>(plist_ref);
     42       if (CFStringCompare(kNoneRevocationValue, style,
     43                           kCFCompareCaseInsensitive))
     44         return true;
     45     }
     46   }
     47   return false;
     48 }
     49 
     50 inline bool SSLVersionIsEnabled(CFStringRef key, bool default_value) {
     51   Boolean exists_and_valid;
     52   Boolean rv = CFPreferencesGetAppBooleanValue(key,
     53                                                kCFPreferencesCurrentApplication,
     54                                                &exists_and_valid);
     55   if (!exists_and_valid)
     56     return default_value;
     57   return rv;
     58 }
     59 
     60 }  // namespace
     61 
     62 SSLConfigServiceMac::SSLConfigServiceMac() : ever_updated_(false) {
     63   // We defer retrieving the settings until the first call to GetSSLConfig, to
     64   // avoid an expensive call on the UI thread, which could affect startup time.
     65 }
     66 
     67 SSLConfigServiceMac::SSLConfigServiceMac(TimeTicks now) : ever_updated_(false) {
     68   UpdateConfig(now);
     69 }
     70 
     71 void SSLConfigServiceMac::GetSSLConfigAt(SSLConfig* config, TimeTicks now) {
     72   if (!ever_updated_ ||
     73       now - config_time_ > TimeDelta::FromSeconds(kConfigUpdateInterval))
     74     UpdateConfig(now);
     75   *config = config_info_;
     76 }
     77 
     78 // static
     79 bool SSLConfigServiceMac::GetSSLConfigNow(SSLConfig* config) {
     80   // Our own revocation checking flag is a binary value, but Mac OS X uses
     81   // several shades of revocation checking:
     82   //   - None (i.e., disabled, the default)
     83   //   - BestAttempt
     84   //   - RequireIfPresent
     85   //   - RequireForall
     86   // Mac OS X also breaks down revocation check for both CRLs and OCSP. We
     87   // set our revocation flag if the system-wide settings for either OCSP
     88   // or CRLs is anything other than None.
     89   config->rev_checking_enabled = (RevocationStyleIsEnabled(kOCSPStyleKey) ||
     90                                   RevocationStyleIsEnabled(kCRLStyleKey));
     91 
     92   config->ssl2_enabled = SSLVersionIsEnabled(kSSL2EnabledKey,
     93                                              kSSL2EnabledDefaultValue);
     94   config->ssl3_enabled = SSLVersionIsEnabled(kSSL3EnabledKey,
     95                                              kSSL3EnabledDefaultValue);
     96   config->tls1_enabled = SSLVersionIsEnabled(kTLS1EnabledKey,
     97                                              kTLS1EnabledDefaultValue);
     98 
     99   return true;
    100 }
    101 
    102 // static
    103 void SSLConfigServiceMac::SetSSL2Enabled(bool enabled) {
    104   CFPreferencesSetAppValue(kSSL2EnabledKey,
    105                            enabled ? kCFBooleanTrue : kCFBooleanFalse,
    106                            kCFPreferencesCurrentApplication);
    107   CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
    108 }
    109 
    110 // static
    111 void SSLConfigServiceMac::SetSSL3Enabled(bool enabled) {
    112   CFPreferencesSetAppValue(kSSL3EnabledKey,
    113                            enabled ? kCFBooleanTrue : kCFBooleanFalse,
    114                            kCFPreferencesCurrentApplication);
    115   CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
    116 }
    117 
    118 // static
    119 void SSLConfigServiceMac::SetTLS1Enabled(bool enabled) {
    120   CFPreferencesSetAppValue(kTLS1EnabledKey,
    121                            enabled ? kCFBooleanTrue : kCFBooleanFalse,
    122                            kCFPreferencesCurrentApplication);
    123   CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
    124 }
    125 
    126 // static
    127 void SSLConfigServiceMac::SetRevCheckingEnabled(bool enabled) {
    128   // This method is provided for use by the unit tests. These settings
    129   // are normally changed via the Keychain Access application's preferences
    130   // dialog.
    131   CFPreferencesSetValue(kOCSPStyleKey,
    132       enabled ? kBestAttemptRevocationValue : kNoneRevocationValue,
    133       kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser,
    134       kCFPreferencesAnyHost);
    135   CFPreferencesSetValue(kCRLStyleKey,
    136       enabled ? kBestAttemptRevocationValue : kNoneRevocationValue,
    137       kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser,
    138       kCFPreferencesAnyHost);
    139 }
    140 
    141 void SSLConfigServiceMac::UpdateConfig(TimeTicks now) {
    142   GetSSLConfigNow(&config_info_);
    143   config_time_ = now;
    144   ever_updated_ = true;
    145 }
    146 
    147 }  // namespace net
    148