// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/base/ssl_config_service_mac.h" #include <CoreFoundation/CoreFoundation.h> #include "base/scoped_cftyperef.h" using base::TimeDelta; using base::TimeTicks; namespace net { namespace { static const int kConfigUpdateInterval = 10; // seconds static const bool kSSL2EnabledDefaultValue = false; static const bool kSSL3EnabledDefaultValue = true; static const bool kTLS1EnabledDefaultValue = true; static CFStringRef kRevocationPreferencesIdentifier = CFSTR("com.apple.security.revocation"); static CFStringRef kOCSPStyleKey = CFSTR("OCSPStyle"); static CFStringRef kCRLStyleKey = CFSTR("CRLStyle"); static CFStringRef kNoneRevocationValue = CFSTR("None"); static CFStringRef kBestAttemptRevocationValue = CFSTR("BestAttempt"); static CFStringRef kSSL2EnabledKey = CFSTR("org.chromium.ssl.ssl2"); static CFStringRef kSSL3EnabledKey = CFSTR("org.chromium.ssl.ssl3"); static CFStringRef kTLS1EnabledKey = CFSTR("org.chromium.ssl.tls1"); bool RevocationStyleIsEnabled(CFStringRef key) { CFPropertyListRef plist_ref = CFPreferencesCopyValue(key, kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if (plist_ref) { scoped_cftyperef<CFPropertyListRef> scoped_plist_ref(plist_ref); if (CFGetTypeID(plist_ref) == CFStringGetTypeID()) { CFStringRef style = reinterpret_cast<CFStringRef>(plist_ref); if (CFStringCompare(kNoneRevocationValue, style, kCFCompareCaseInsensitive)) return true; } } return false; } inline bool SSLVersionIsEnabled(CFStringRef key, bool default_value) { Boolean exists_and_valid; Boolean rv = CFPreferencesGetAppBooleanValue(key, kCFPreferencesCurrentApplication, &exists_and_valid); if (!exists_and_valid) return default_value; return rv; } } // namespace SSLConfigServiceMac::SSLConfigServiceMac() : ever_updated_(false) { // We defer retrieving the settings until the first call to GetSSLConfig, to // avoid an expensive call on the UI thread, which could affect startup time. } SSLConfigServiceMac::SSLConfigServiceMac(TimeTicks now) : ever_updated_(false) { UpdateConfig(now); } void SSLConfigServiceMac::GetSSLConfigAt(SSLConfig* config, TimeTicks now) { if (!ever_updated_ || now - config_time_ > TimeDelta::FromSeconds(kConfigUpdateInterval)) UpdateConfig(now); *config = config_info_; } // static bool SSLConfigServiceMac::GetSSLConfigNow(SSLConfig* config) { // Our own revocation checking flag is a binary value, but Mac OS X uses // several shades of revocation checking: // - None (i.e., disabled, the default) // - BestAttempt // - RequireIfPresent // - RequireForall // Mac OS X also breaks down revocation check for both CRLs and OCSP. We // set our revocation flag if the system-wide settings for either OCSP // or CRLs is anything other than None. config->rev_checking_enabled = (RevocationStyleIsEnabled(kOCSPStyleKey) || RevocationStyleIsEnabled(kCRLStyleKey)); config->ssl2_enabled = SSLVersionIsEnabled(kSSL2EnabledKey, kSSL2EnabledDefaultValue); config->ssl3_enabled = SSLVersionIsEnabled(kSSL3EnabledKey, kSSL3EnabledDefaultValue); config->tls1_enabled = SSLVersionIsEnabled(kTLS1EnabledKey, kTLS1EnabledDefaultValue); return true; } // static void SSLConfigServiceMac::SetSSL2Enabled(bool enabled) { CFPreferencesSetAppValue(kSSL2EnabledKey, enabled ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); } // static void SSLConfigServiceMac::SetSSL3Enabled(bool enabled) { CFPreferencesSetAppValue(kSSL3EnabledKey, enabled ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); } // static void SSLConfigServiceMac::SetTLS1Enabled(bool enabled) { CFPreferencesSetAppValue(kTLS1EnabledKey, enabled ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); } // static void SSLConfigServiceMac::SetRevCheckingEnabled(bool enabled) { // This method is provided for use by the unit tests. These settings // are normally changed via the Keychain Access application's preferences // dialog. CFPreferencesSetValue(kOCSPStyleKey, enabled ? kBestAttemptRevocationValue : kNoneRevocationValue, kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSetValue(kCRLStyleKey, enabled ? kBestAttemptRevocationValue : kNoneRevocationValue, kRevocationPreferencesIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } void SSLConfigServiceMac::UpdateConfig(TimeTicks now) { GetSSLConfigNow(&config_info_); config_time_ = now; ever_updated_ = true; } } // namespace net