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