Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(675)

Side by Side Diff: chromeos/network/client_cert_util.cc

Issue 421113002: Use correct slot id for client certs in network config. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos/network/client_cert_util.h ('k') | chromeos/network/network_connection_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/network/client_cert_util.h" 5 #include "chromeos/network/client_cert_util.h"
6 6
7 #include <cert.h> 7 #include <cert.h>
8 #include <pk11pub.h> 8 #include <pk11pub.h>
9 9
10 #include <list> 10 #include <list>
11 #include <string> 11 #include <string>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
14 #include "base/values.h" 16 #include "base/values.h"
15 #include "chromeos/network/certificate_pattern.h" 17 #include "chromeos/network/certificate_pattern.h"
16 #include "chromeos/network/network_event_log.h" 18 #include "chromeos/network/network_event_log.h"
17 #include "components/onc/onc_constants.h" 19 #include "components/onc/onc_constants.h"
18 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
19 #include "net/cert/cert_database.h" 21 #include "net/cert/cert_database.h"
20 #include "net/cert/nss_cert_database.h" 22 #include "net/cert/nss_cert_database.h"
21 #include "net/cert/scoped_nss_types.h" 23 #include "net/cert/scoped_nss_types.h"
22 #include "net/cert/x509_cert_types.h" 24 #include "net/cert/x509_cert_types.h"
23 #include "net/cert/x509_certificate.h" 25 #include "net/cert/x509_certificate.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h" 26 #include "third_party/cros_system_api/dbus/service_constants.h"
25 27
26 namespace chromeos { 28 namespace chromeos {
27 29
28 namespace client_cert { 30 namespace client_cert {
29 31
30 namespace { 32 namespace {
31 33
32 // Functor to filter out non-matching issuers. 34 const char kDefaultTPMPin[] = "111111";
33 class IssuerFilter {
34 public:
35 explicit IssuerFilter(const IssuerSubjectPattern& issuer)
36 : issuer_(issuer) {}
37 bool operator()(const scoped_refptr<net::X509Certificate>& cert) const {
38 return !CertPrincipalMatches(issuer_, cert.get()->issuer());
39 }
40 private:
41 const IssuerSubjectPattern& issuer_;
42 };
43
44 // Functor to filter out non-matching subjects.
45 class SubjectFilter {
46 public:
47 explicit SubjectFilter(const IssuerSubjectPattern& subject)
48 : subject_(subject) {}
49 bool operator()(const scoped_refptr<net::X509Certificate>& cert) const {
50 return !CertPrincipalMatches(subject_, cert.get()->subject());
51 }
52 private:
53 const IssuerSubjectPattern& subject_;
54 };
55
56 // Functor to filter out certs that don't have private keys, or are invalid.
57 class PrivateKeyFilter {
58 public:
59 explicit PrivateKeyFilter(net::CertDatabase* cert_db) : cert_db_(cert_db) {}
60 bool operator()(const scoped_refptr<net::X509Certificate>& cert) const {
61 return cert_db_->CheckUserCert(cert.get()) != net::OK;
62 }
63 private:
64 net::CertDatabase* cert_db_;
65 };
66
67 // Functor to filter out certs that don't have an issuer in the associated
68 // IssuerCAPEMs list.
69 class IssuerCaFilter {
70 public:
71 explicit IssuerCaFilter(const std::vector<std::string>& issuer_ca_pems)
72 : issuer_ca_pems_(issuer_ca_pems) {}
73 bool operator()(const scoped_refptr<net::X509Certificate>& cert) const {
74 // Find the certificate issuer for each certificate.
75 // TODO(gspencer): this functionality should be available from
76 // X509Certificate or NSSCertDatabase.
77 net::ScopedCERTCertificate issuer_cert(CERT_FindCertIssuer(
78 cert.get()->os_cert_handle(), PR_Now(), certUsageAnyCA));
79
80 if (!issuer_cert)
81 return true;
82
83 std::string pem_encoded;
84 if (!net::X509Certificate::GetPEMEncoded(issuer_cert.get(),
85 &pem_encoded)) {
86 LOG(ERROR) << "Couldn't PEM-encode certificate.";
87 return true;
88 }
89
90 return (std::find(issuer_ca_pems_.begin(), issuer_ca_pems_.end(),
91 pem_encoded) ==
92 issuer_ca_pems_.end());
93 }
94 private:
95 const std::vector<std::string>& issuer_ca_pems_;
96 };
97 35
98 std::string GetStringFromDictionary(const base::DictionaryValue& dict, 36 std::string GetStringFromDictionary(const base::DictionaryValue& dict,
99 const std::string& key) { 37 const std::string& key) {
100 std::string s; 38 std::string s;
101 dict.GetStringWithoutPathExpansion(key, &s); 39 dict.GetStringWithoutPathExpansion(key, &s);
102 return s; 40 return s;
103 } 41 }
104 42
105 void GetClientCertTypeAndPattern( 43 void GetClientCertTypeAndPattern(
106 const base::DictionaryValue& dict_with_client_cert, 44 const base::DictionaryValue& dict_with_client_cert,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 principal.organization_unit_names.end(), 90 principal.organization_unit_names.end(),
153 pattern.organizational_unit()) == 91 pattern.organizational_unit()) ==
154 principal.organization_unit_names.end()) { 92 principal.organization_unit_names.end()) {
155 return false; 93 return false;
156 } 94 }
157 } 95 }
158 96
159 return true; 97 return true;
160 } 98 }
161 99
162 scoped_refptr<net::X509Certificate> GetCertificateMatch(
163 const CertificatePattern& pattern,
164 const net::CertificateList& all_certs) {
165 typedef std::list<scoped_refptr<net::X509Certificate> > CertificateStlList;
166
167 // Start with all the certs, and narrow it down from there.
168 CertificateStlList matching_certs;
169
170 if (all_certs.empty())
171 return NULL;
172
173 for (net::CertificateList::const_iterator iter = all_certs.begin();
174 iter != all_certs.end(); ++iter) {
175 matching_certs.push_back(*iter);
176 }
177
178 // Strip off any certs that don't have the right issuer and/or subject.
179 if (!pattern.issuer().Empty()) {
180 matching_certs.remove_if(IssuerFilter(pattern.issuer()));
181 if (matching_certs.empty())
182 return NULL;
183 }
184
185 if (!pattern.subject().Empty()) {
186 matching_certs.remove_if(SubjectFilter(pattern.subject()));
187 if (matching_certs.empty())
188 return NULL;
189 }
190
191 if (!pattern.issuer_ca_pems().empty()) {
192 matching_certs.remove_if(IssuerCaFilter(pattern.issuer_ca_pems()));
193 if (matching_certs.empty())
194 return NULL;
195 }
196
197 // Eliminate any certs that don't have private keys associated with
198 // them. The CheckUserCert call in the filter is a little slow (because of
199 // underlying PKCS11 calls), so we do this last to reduce the number of times
200 // we have to call it.
201 PrivateKeyFilter private_filter(net::CertDatabase::GetInstance());
202 matching_certs.remove_if(private_filter);
203
204 if (matching_certs.empty())
205 return NULL;
206
207 // We now have a list of certificates that match the pattern we're
208 // looking for. Now we find the one with the latest start date.
209 scoped_refptr<net::X509Certificate> latest(NULL);
210
211 // Iterate over the rest looking for the one that was issued latest.
212 for (CertificateStlList::iterator iter = matching_certs.begin();
213 iter != matching_certs.end(); ++iter) {
214 if (!latest.get() || (*iter)->valid_start() > latest->valid_start())
215 latest = *iter;
216 }
217
218 return latest;
219 }
220
221 std::string GetPkcs11IdFromEapCertId(const std::string& cert_id) { 100 std::string GetPkcs11IdFromEapCertId(const std::string& cert_id) {
222 if (cert_id.empty()) 101 if (cert_id.empty())
223 return std::string(); 102 return std::string();
224 103
225 size_t delimiter_pos = cert_id.find(':'); 104 size_t delimiter_pos = cert_id.find(':');
226 if (delimiter_pos == std::string::npos) { 105 if (delimiter_pos == std::string::npos) {
227 // No delimiter found, so |cert_id| only contains the PKCS11 id. 106 // No delimiter found, so |cert_id| only contains the PKCS11 id.
228 return cert_id; 107 return cert_id;
229 } 108 }
230 if (delimiter_pos + 1 >= cert_id.size()) { 109 if (delimiter_pos + 1 >= cert_id.size()) {
231 LOG(ERROR) << "Empty PKCS11 id in cert id."; 110 LOG(ERROR) << "Empty PKCS11 id in cert id.";
232 return std::string(); 111 return std::string();
233 } 112 }
234 return cert_id.substr(delimiter_pos + 1); 113 return cert_id.substr(delimiter_pos + 1);
235 } 114 }
236 115
237 void SetShillProperties(const ConfigType cert_config_type, 116 void SetShillProperties(const ConfigType cert_config_type,
238 const std::string& tpm_slot, 117 const int tpm_slot,
239 const std::string& tpm_pin, 118 const std::string& pkcs11_id,
240 const std::string* pkcs11_id,
241 base::DictionaryValue* properties) { 119 base::DictionaryValue* properties) {
242 const char* tpm_pin_property = NULL;
243 switch (cert_config_type) { 120 switch (cert_config_type) {
244 case CONFIG_TYPE_NONE: { 121 case CONFIG_TYPE_NONE: {
245 return; 122 return;
246 } 123 }
247 case CONFIG_TYPE_OPENVPN: { 124 case CONFIG_TYPE_OPENVPN: {
248 tpm_pin_property = shill::kOpenVPNPinProperty; 125 properties->SetStringWithoutPathExpansion(shill::kOpenVPNPinProperty,
249 if (pkcs11_id) { 126 kDefaultTPMPin);
250 properties->SetStringWithoutPathExpansion( 127 properties->SetStringWithoutPathExpansion(
251 shill::kOpenVPNClientCertIdProperty, *pkcs11_id); 128 shill::kOpenVPNClientCertIdProperty, pkcs11_id);
252 }
253 break; 129 break;
254 } 130 }
255 case CONFIG_TYPE_IPSEC: { 131 case CONFIG_TYPE_IPSEC: {
256 tpm_pin_property = shill::kL2tpIpsecPinProperty; 132 properties->SetStringWithoutPathExpansion(shill::kL2tpIpsecPinProperty,
257 if (!tpm_slot.empty()) { 133 kDefaultTPMPin);
258 properties->SetStringWithoutPathExpansion( 134 properties->SetStringWithoutPathExpansion(
259 shill::kL2tpIpsecClientCertSlotProperty, tpm_slot); 135 shill::kL2tpIpsecClientCertSlotProperty, base::IntToString(tpm_slot));
260 } 136 properties->SetStringWithoutPathExpansion(
261 if (pkcs11_id) { 137 shill::kL2tpIpsecClientCertIdProperty, pkcs11_id);
262 properties->SetStringWithoutPathExpansion(
263 shill::kL2tpIpsecClientCertIdProperty, *pkcs11_id);
264 }
265 break; 138 break;
266 } 139 }
267 case CONFIG_TYPE_EAP: { 140 case CONFIG_TYPE_EAP: {
268 tpm_pin_property = shill::kEapPinProperty; 141 properties->SetStringWithoutPathExpansion(shill::kEapPinProperty,
269 if (pkcs11_id) { 142 kDefaultTPMPin);
270 std::string key_id; 143 std::string key_id =
271 if (pkcs11_id->empty()) { 144 base::StringPrintf("%i:%s", tpm_slot, pkcs11_id.c_str());
272 // An empty pkcs11_id means that we should clear the properties. 145
273 } else { 146 // Shill requires both CertID and KeyID for TLS connections, despite the
274 if (tpm_slot.empty()) 147 // fact that by convention they are the same ID, because one identifies
275 NET_LOG_ERROR("Missing TPM slot id", ""); 148 // the certificate and the other the private key.
276 else 149 properties->SetStringWithoutPathExpansion(shill::kEapCertIdProperty,
277 key_id = tpm_slot + ":"; 150 key_id);
278 key_id.append(*pkcs11_id); 151 properties->SetStringWithoutPathExpansion(shill::kEapKeyIdProperty,
279 } 152 key_id);
280 // Shill requires both CertID and KeyID for TLS connections, despite the
281 // fact that by convention they are the same ID, because one identifies
282 // the certificate and the other the private key.
283 properties->SetStringWithoutPathExpansion(shill::kEapCertIdProperty,
284 key_id);
285 properties->SetStringWithoutPathExpansion(shill::kEapKeyIdProperty,
286 key_id);
287 }
288 break; 153 break;
289 } 154 }
290 } 155 }
291 DCHECK(tpm_pin_property); 156 }
292 if (!tpm_pin.empty()) 157
293 properties->SetStringWithoutPathExpansion(tpm_pin_property, tpm_pin); 158 void SetEmptyShillProperties(const ConfigType cert_config_type,
159 base::DictionaryValue* properties) {
160 switch (cert_config_type) {
161 case CONFIG_TYPE_NONE: {
162 return;
163 }
164 case CONFIG_TYPE_OPENVPN: {
165 properties->SetStringWithoutPathExpansion(shill::kOpenVPNPinProperty,
166 std::string());
167 properties->SetStringWithoutPathExpansion(
168 shill::kOpenVPNClientCertIdProperty, std::string());
169 break;
170 }
171 case CONFIG_TYPE_IPSEC: {
172 properties->SetStringWithoutPathExpansion(shill::kL2tpIpsecPinProperty,
173 std::string());
174 properties->SetStringWithoutPathExpansion(
175 shill::kL2tpIpsecClientCertSlotProperty, std::string());
176 properties->SetStringWithoutPathExpansion(
177 shill::kL2tpIpsecClientCertIdProperty, std::string());
178 break;
179 }
180 case CONFIG_TYPE_EAP: {
181 properties->SetStringWithoutPathExpansion(shill::kEapPinProperty,
182 std::string());
183 // Shill requires both CertID and KeyID for TLS connections, despite the
184 // fact that by convention they are the same ID, because one identifies
185 // the certificate and the other the private key.
186 properties->SetStringWithoutPathExpansion(shill::kEapCertIdProperty,
187 std::string());
188 properties->SetStringWithoutPathExpansion(shill::kEapKeyIdProperty,
189 std::string());
190 break;
191 }
192 }
294 } 193 }
295 194
296 ClientCertConfig::ClientCertConfig() 195 ClientCertConfig::ClientCertConfig()
297 : location(CONFIG_TYPE_NONE), 196 : location(CONFIG_TYPE_NONE),
298 client_cert_type(onc::client_cert::kClientCertTypeNone) { 197 client_cert_type(onc::client_cert::kClientCertTypeNone) {
299 } 198 }
300 199
301 void OncToClientCertConfig(const base::DictionaryValue& network_config, 200 void OncToClientCertConfig(const base::DictionaryValue& network_config,
302 ClientCertConfig* cert_config) { 201 ClientCertConfig* cert_config) {
303 using namespace ::onc; 202 using namespace ::onc;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 return !cert_id.empty() && !key_id.empty() && !identity.empty(); 284 return !cert_id.empty() && !key_id.empty() && !identity.empty();
386 } 285 }
387 } 286 }
388 NOTREACHED(); 287 NOTREACHED();
389 return false; 288 return false;
390 } 289 }
391 290
392 } // namespace client_cert 291 } // namespace client_cert
393 292
394 } // namespace chromeos 293 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/client_cert_util.h ('k') | chromeos/network/network_connection_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698