summaryrefslogtreecommitdiffstats
path: root/net/base/ssl_config_service_mac.cc
blob: 82a363221c1d9977a216eabba21bef427b0924c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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);
  SSLConfigService::SetSSLConfigFlags(config);

  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) {
  SSLConfig orig_config = config_info_;
  GetSSLConfigNow(&config_info_);
  if (ever_updated_)
    ProcessConfigUpdate(orig_config, config_info_);
  config_time_ = now;
  ever_updated_ = true;
}

}  // namespace net