summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorhawk@chromium.org <hawk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-09 22:07:32 +0000
committerhawk@chromium.org <hawk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-09 22:07:32 +0000
commitf37c98ff15a2c2de0b86646be4ff7c5e2f59b703 (patch)
tree07f3dab046d81479ad73a521216ded00b32fb051 /net
parentf7238c977a13f719f2d540a2927a51f6c1e70e74 (diff)
downloadchromium_src-f37c98ff15a2c2de0b86646be4ff7c5e2f59b703.zip
chromium_src-f37c98ff15a2c2de0b86646be4ff7c5e2f59b703.tar.gz
chromium_src-f37c98ff15a2c2de0b86646be4ff7c5e2f59b703.tar.bz2
Add an SSLConfigService implementation for Mac OS X
BUG=19293 TEST=https://test-ssev.verisign.com/ has three links: one should work OK, the other should warn that the certificate is expired, the other that the certificate is revoked. Review URL: http://codereview.chromium.org/193009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25798 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/ssl_config_service.cc4
-rw-r--r--net/base/ssl_config_service_mac.cc147
-rw-r--r--net/base/ssl_config_service_mac.h55
-rw-r--r--net/base/ssl_config_service_mac_unittest.cc115
-rw-r--r--net/net.gyp3
5 files changed, 324 insertions, 0 deletions
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index 8fae14e..67d1349 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -6,6 +6,8 @@
#if defined(OS_WIN)
#include "net/base/ssl_config_service_win.h"
+#elif defined(OS_MACOSX)
+#include "net/base/ssl_config_service_mac.h"
#else
#include "net/base/ssl_config_service_defaults.h"
#endif
@@ -16,6 +18,8 @@ namespace net {
SSLConfigService* SSLConfigService::CreateSystemSSLConfigService() {
#if defined(OS_WIN)
return new SSLConfigServiceWin;
+#elif defined(OS_MACOSX)
+ return new SSLConfigServiceMac;
#else
return new SSLConfigServiceDefaults;
#endif
diff --git a/net/base/ssl_config_service_mac.cc b/net/base/ssl_config_service_mac.cc
new file mode 100644
index 0000000..e4cbf1b
--- /dev/null
+++ b/net/base/ssl_config_service_mac.cc
@@ -0,0 +1,147 @@
+// 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(kOCSPStyleKey,
+ 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
diff --git a/net/base/ssl_config_service_mac.h b/net/base/ssl_config_service_mac.h
new file mode 100644
index 0000000..4741034
--- /dev/null
+++ b/net/base/ssl_config_service_mac.h
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef NET_BASE_SSL_CONFIG_SERVICE_MAC_H_
+#define NET_BASE_SSL_CONFIG_SERVICE_MAC_H_
+
+#include "base/time.h"
+#include "net/base/ssl_config_service.h"
+
+namespace net {
+
+// This class is responsible for getting and setting the SSL configuration on
+// Mac OS X.
+class SSLConfigServiceMac : public SSLConfigService {
+ public:
+ SSLConfigServiceMac();
+ explicit SSLConfigServiceMac(base::TimeTicks now); // Used for testing.
+ virtual ~SSLConfigServiceMac() {}
+
+ // Get the current SSL configuration settings. Can be called on any
+ // thread.
+ static bool GetSSLConfigNow(SSLConfig* config);
+
+ // Setters. Can be called on any thread.
+ static void SetRevCheckingEnabled(bool enabled);
+ static void SetSSL2Enabled(bool enabled);
+ static void SetSSL3Enabled(bool enabled);
+ static void SetTLS1Enabled(bool enabled);
+
+ // Get the (cached) SSL configuration settings that are fresh within 10
+ // seconds. This is cheaper than GetSSLConfigNow and is suitable when
+ // we don't need the absolutely current configuration settings. This
+ // method is not thread-safe, so it must be called on the same thread.
+ void GetSSLConfig(SSLConfig* config) {
+ GetSSLConfigAt(config, base::TimeTicks::Now());
+ }
+
+ // Used for testing.
+ void GetSSLConfigAt(SSLConfig* config, base::TimeTicks now);
+
+ private:
+ void UpdateConfig(base::TimeTicks now);
+
+ // We store the system SSL config and the time that we fetched it.
+ SSLConfig config_info_;
+ base::TimeTicks config_time_;
+ bool ever_updated_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SSLConfigServiceMac);
+};
+
+} // namespace net
+
+#endif // NET_BASE_SSL_CONFIG_SERVICE_MAC_H_
diff --git a/net/base/ssl_config_service_mac_unittest.cc b/net/base/ssl_config_service_mac_unittest.cc
new file mode 100644
index 0000000..d16129b
--- /dev/null
+++ b/net/base/ssl_config_service_mac_unittest.cc
@@ -0,0 +1,115 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace {
+
+class SSLConfigServiceMacTest : public testing::Test {
+};
+
+} // namespace
+
+TEST(SSLConfigServiceMacTest, GetNowTest) {
+ // Verify that the constructor sets the correct default values.
+ net::SSLConfig config;
+ EXPECT_EQ(true, config.rev_checking_enabled);
+ EXPECT_EQ(false, config.ssl2_enabled);
+ EXPECT_EQ(true, config.ssl3_enabled);
+ EXPECT_EQ(true, config.tls1_enabled);
+
+ bool rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+}
+
+TEST(SSLConfigServiceMacTest, SetTest) {
+ // Save the current settings so we can restore them after the tests.
+ net::SSLConfig config_save;
+ bool rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config_save);
+ EXPECT_TRUE(rv);
+
+ net::SSLConfig config;
+
+ // Test SetRevCheckingEnabled.
+ net::SSLConfigServiceMac::SetRevCheckingEnabled(true);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_TRUE(config.rev_checking_enabled);
+
+ net::SSLConfigServiceMac::SetRevCheckingEnabled(false);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_FALSE(config.rev_checking_enabled);
+
+ net::SSLConfigServiceMac::SetRevCheckingEnabled(
+ config_save.rev_checking_enabled);
+
+ // Test SetSSL2Enabled.
+ net::SSLConfigServiceMac::SetSSL2Enabled(true);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_TRUE(config.ssl2_enabled);
+
+ net::SSLConfigServiceMac::SetSSL2Enabled(false);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_FALSE(config.ssl2_enabled);
+
+ net::SSLConfigServiceMac::SetSSL2Enabled(config_save.ssl2_enabled);
+
+ // Test SetSSL3Enabled.
+ net::SSLConfigServiceMac::SetSSL3Enabled(true);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_TRUE(config.ssl3_enabled);
+
+ net::SSLConfigServiceMac::SetSSL3Enabled(false);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_FALSE(config.ssl3_enabled);
+
+ net::SSLConfigServiceMac::SetSSL3Enabled(config_save.ssl3_enabled);
+
+ // Test SetTLS1Enabled.
+ net::SSLConfigServiceMac::SetTLS1Enabled(true);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_TRUE(config.tls1_enabled);
+
+ net::SSLConfigServiceMac::SetTLS1Enabled(false);
+ rv = net::SSLConfigServiceMac::GetSSLConfigNow(&config);
+ EXPECT_TRUE(rv);
+ EXPECT_FALSE(config.tls1_enabled);
+
+ net::SSLConfigServiceMac::SetTLS1Enabled(config_save.tls1_enabled);
+}
+
+TEST(SSLConfigServiceMacTest, GetTest) {
+ TimeTicks now = TimeTicks::Now();
+ TimeTicks now_1 = now + TimeDelta::FromSeconds(1);
+ TimeTicks now_11 = now + TimeDelta::FromSeconds(11);
+
+ net::SSLConfig config, config_1, config_11;
+ scoped_refptr<net::SSLConfigServiceMac> config_service(
+ new net::SSLConfigServiceMac(now));
+ config_service->GetSSLConfigAt(&config, now);
+
+ // Flip rev_checking_enabled.
+ net::SSLConfigServiceMac::SetRevCheckingEnabled(
+ !config.rev_checking_enabled);
+
+ config_service->GetSSLConfigAt(&config_1, now_1);
+ EXPECT_EQ(config.rev_checking_enabled, config_1.rev_checking_enabled);
+
+ config_service->GetSSLConfigAt(&config_11, now_11);
+ EXPECT_EQ(!config.rev_checking_enabled, config_11.rev_checking_enabled);
+
+ // Restore the original value.
+ net::SSLConfigServiceMac::SetRevCheckingEnabled(
+ config.rev_checking_enabled);
+}
diff --git a/net/net.gyp b/net/net.gyp
index 00d5039..34281d1 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -124,6 +124,8 @@
'base/ssl_config_service.cc',
'base/ssl_config_service.h',
'base/ssl_config_service_defaults.h',
+ 'base/ssl_config_service_mac.cc',
+ 'base/ssl_config_service_mac.h',
'base/ssl_config_service_win.cc',
'base/ssl_config_service_win.h',
'base/ssl_info.h',
@@ -472,6 +474,7 @@
'base/run_all_unittests.cc',
'base/sdch_filter_unittest.cc',
'base/ssl_client_auth_cache_unittest.cc',
+ 'base/ssl_config_service_mac_unittest.cc',
'base/ssl_config_service_win_unittest.cc',
'base/strict_transport_security_state_unittest.cc',
'base/telnet_server_unittest.cc',