OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/chromeos/cros/onc_network_parser.h" | 5 #include "chrome/browser/chromeos/cros/onc_network_parser.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/json/json_value_serializer.h" | 8 #include "base/json/json_value_serializer.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 } | 101 } |
102 | 102 |
103 int OncNetworkParser::GetNetworkConfigsSize() const { | 103 int OncNetworkParser::GetNetworkConfigsSize() const { |
104 return network_configs_ ? network_configs_->GetSize() : 0; | 104 return network_configs_ ? network_configs_->GetSize() : 0; |
105 } | 105 } |
106 | 106 |
107 int OncNetworkParser::GetCertificatesSize() const { | 107 int OncNetworkParser::GetCertificatesSize() const { |
108 return certificates_ ? certificates_->GetSize() : 0; | 108 return certificates_ ? certificates_->GetSize() : 0; |
109 } | 109 } |
110 | 110 |
111 bool OncNetworkParser::ParseCertificate(int cert_index) { | 111 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseCertificate( |
| 112 int cert_index) { |
112 CHECK(certificates_); | 113 CHECK(certificates_); |
113 CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize()); | 114 CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize()); |
114 CHECK(cert_index >= 0); | 115 CHECK(cert_index >= 0); |
115 base::DictionaryValue* certificate = NULL; | 116 base::DictionaryValue* certificate = NULL; |
116 certificates_->GetDictionary(cert_index, &certificate); | 117 certificates_->GetDictionary(cert_index, &certificate); |
117 CHECK(certificate); | 118 CHECK(certificate); |
118 | 119 |
119 // Get out the attributes of the given cert. | 120 // Get out the attributes of the given certificate. |
120 std::string guid; | 121 std::string guid; |
121 bool remove = false; | 122 bool remove = false; |
122 if (!certificate->GetString("GUID", &guid) || guid.empty()) { | 123 if (!certificate->GetString("GUID", &guid) || guid.empty()) { |
123 LOG(WARNING) << "ONC File: certificate missing identifier at index" | 124 LOG(WARNING) << "ONC File: certificate missing identifier at index" |
124 << cert_index; | 125 << cert_index; |
125 return false; | 126 return NULL; |
126 } | 127 } |
127 | 128 |
128 if (!certificate->GetBoolean("Remove", &remove)) | 129 if (!certificate->GetBoolean("Remove", &remove)) |
129 remove = false; | 130 remove = false; |
130 | 131 |
131 net::CertDatabase cert_database; | 132 net::CertDatabase cert_database; |
132 if (remove) | 133 if (remove) { |
133 return cert_database.DeleteCertAndKeyByLabel(guid); | 134 bool success = cert_database.DeleteCertAndKeyByLabel(guid); |
| 135 DCHECK(success); |
| 136 // TODO(gspencer): return removed certificate? |
| 137 return NULL; |
| 138 } |
134 | 139 |
135 // Not removing, so let's get the data we need to add this cert. | 140 // Not removing, so let's get the data we need to add this certificate. |
136 std::string cert_type; | 141 std::string cert_type; |
137 certificate->GetString("Type", &cert_type); | 142 certificate->GetString("Type", &cert_type); |
138 if (cert_type == "Server" || cert_type == "Authority") { | 143 if (cert_type == "Server" || cert_type == "Authority") { |
139 return ParseServerOrCaCertificate(cert_index, cert_type, certificate); | 144 return ParseServerOrCaCertificate(cert_index, cert_type, guid, certificate); |
140 } | 145 } |
141 if (cert_type == "Client") { | 146 if (cert_type == "Client") { |
142 return ParseClientCertificate(cert_index, certificate); | 147 return ParseClientCertificate(cert_index, guid, certificate); |
143 } | 148 } |
144 | 149 |
145 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type | 150 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type |
146 << " at index " << cert_index; | 151 << " at index " << cert_index; |
147 return false; | 152 return NULL; |
148 } | 153 } |
149 | 154 |
150 Network* OncNetworkParser::ParseNetwork(int n) { | 155 Network* OncNetworkParser::ParseNetwork(int n) { |
151 // TODO(chocobo): Change this to parse network into a dictionary. | 156 // TODO(chocobo): Change this to parse network into a dictionary. |
152 if (!network_configs_) | 157 if (!network_configs_) |
153 return NULL; | 158 return NULL; |
154 DictionaryValue* info = NULL; | 159 DictionaryValue* info = NULL; |
155 if (!network_configs_->GetDictionary(n, &info)) | 160 if (!network_configs_->GetDictionary(n, &info)) |
156 return NULL; | 161 return NULL; |
157 // Parse Open Network Configuration blob into a temporary Network object. | 162 // Parse Open Network Configuration blob into a temporary Network object. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 return ParseType(GetTypeFromDictionary(info)); | 205 return ParseType(GetTypeFromDictionary(info)); |
201 } | 206 } |
202 | 207 |
203 std::string OncNetworkParser::GetTypeFromDictionary( | 208 std::string OncNetworkParser::GetTypeFromDictionary( |
204 const base::DictionaryValue& info) { | 209 const base::DictionaryValue& info) { |
205 std::string type_string; | 210 std::string type_string; |
206 info.GetString("Type", &type_string); | 211 info.GetString("Type", &type_string); |
207 return type_string; | 212 return type_string; |
208 } | 213 } |
209 | 214 |
210 bool OncNetworkParser::ParseServerOrCaCertificate( | 215 scoped_refptr<net::X509Certificate> |
| 216 OncNetworkParser::ParseServerOrCaCertificate( |
211 int cert_index, | 217 int cert_index, |
212 const std::string& cert_type, | 218 const std::string& cert_type, |
| 219 const std::string& guid, |
213 base::DictionaryValue* certificate) { | 220 base::DictionaryValue* certificate) { |
214 net::CertDatabase cert_database; | 221 net::CertDatabase cert_database; |
215 bool web_trust = false; | 222 bool web_trust = false; |
216 base::ListValue* trust_list = NULL; | 223 base::ListValue* trust_list = NULL; |
217 if (certificate->GetList("Trust", &trust_list)) { | 224 if (certificate->GetList("Trust", &trust_list)) { |
218 for (size_t i = 0; i < trust_list->GetSize(); ++i) { | 225 for (size_t i = 0; i < trust_list->GetSize(); ++i) { |
219 std::string trust_type; | 226 std::string trust_type; |
220 if (!trust_list->GetString(i, &trust_type)) { | 227 if (!trust_list->GetString(i, &trust_type)) { |
221 LOG(WARNING) << "ONC File: certificate trust is invalid at index " | 228 LOG(WARNING) << "ONC File: certificate trust is invalid at index " |
222 << cert_index; | 229 << cert_index; |
223 return false; | 230 return NULL; |
224 } | 231 } |
225 if (trust_type == "Web") { | 232 if (trust_type == "Web") { |
226 web_trust = true; | 233 web_trust = true; |
227 } else { | 234 } else { |
228 LOG(WARNING) << "ONC File: certificate contains unknown " | 235 LOG(WARNING) << "ONC File: certificate contains unknown " |
229 << "trust type: " << trust_type | 236 << "trust type: " << trust_type |
230 << " at index " << cert_index; | 237 << " at index " << cert_index; |
231 return false; | 238 return NULL; |
232 } | 239 } |
233 } | 240 } |
234 } | 241 } |
235 | 242 |
236 std::string x509_data; | 243 std::string x509_data; |
237 if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) { | 244 if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) { |
238 LOG(WARNING) << "ONC File: certificate missing appropriate " | 245 LOG(WARNING) << "ONC File: certificate missing appropriate " |
239 << "certificate data for type: " << cert_type | 246 << "certificate data for type: " << cert_type |
240 << " at index " << cert_index; | 247 << " at index " << cert_index; |
241 return false; | 248 return NULL; |
242 } | 249 } |
243 | 250 |
244 std::string decoded_x509; | 251 std::string decoded_x509; |
245 if (!base::Base64Decode(x509_data, &decoded_x509)) { | 252 if (!base::Base64Decode(x509_data, &decoded_x509)) { |
246 LOG(WARNING) << "Unable to base64 decode X509 data: \"" | 253 LOG(WARNING) << "Unable to base64 decode X509 data: \"" |
247 << x509_data << "\"."; | 254 << x509_data << "\"."; |
248 return false; | 255 return NULL; |
249 } | 256 } |
250 | 257 |
251 scoped_refptr<net::X509Certificate> x509_cert( | 258 scoped_refptr<net::X509Certificate> x509_cert = |
252 net::X509Certificate::CreateFromBytes(decoded_x509.c_str(), | 259 net::X509Certificate::CreateFromBytesWithNickname( |
253 decoded_x509.size())); | 260 decoded_x509.c_str(), |
| 261 decoded_x509.size(), |
| 262 guid.c_str()); |
254 if (!x509_cert.get()) { | 263 if (!x509_cert.get()) { |
255 LOG(WARNING) << "Unable to create X509 certificate from bytes."; | 264 LOG(WARNING) << "Unable to create X509 certificate from bytes."; |
256 return false; | 265 return NULL; |
257 } | 266 } |
| 267 |
| 268 if (!x509_cert->SetLabel(guid)) |
| 269 return NULL; |
| 270 |
258 net::CertificateList cert_list; | 271 net::CertificateList cert_list; |
259 cert_list.push_back(x509_cert); | 272 cert_list.push_back(x509_cert); |
260 net::CertDatabase::ImportCertFailureList failures; | 273 net::CertDatabase::ImportCertFailureList failures; |
261 bool success = false; | 274 bool success = false; |
262 if (cert_type == "Server") { | 275 if (cert_type == "Server") { |
263 success = cert_database.ImportServerCert(cert_list, &failures); | 276 success = cert_database.ImportServerCert(cert_list, &failures); |
264 } else { // Authority cert | 277 } else { // Authority cert |
265 net::CertDatabase::TrustBits trust = web_trust ? | 278 net::CertDatabase::TrustBits trust = web_trust ? |
266 net::CertDatabase::TRUSTED_SSL : | 279 net::CertDatabase::TRUSTED_SSL : |
267 net::CertDatabase::UNTRUSTED; | 280 net::CertDatabase::UNTRUSTED; |
268 success = cert_database.ImportCACerts(cert_list, trust, &failures); | 281 success = cert_database.ImportCACerts(cert_list, trust, &failures); |
269 } | 282 } |
270 if (!failures.empty()) { | 283 if (!failures.empty()) { |
271 LOG(WARNING) << "ONC File: Error (" | 284 LOG(WARNING) << "ONC File: Error (" |
272 << net::ErrorToString(failures[0].net_error) | 285 << net::ErrorToString(failures[0].net_error) |
273 << ") importing " << cert_type << " certificate at index " | 286 << ") importing " << cert_type << " certificate at index " |
274 << cert_index; | 287 << cert_index; |
275 return false; | 288 return NULL; |
276 } | 289 } |
277 if (!success) { | 290 if (!success) { |
278 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type | 291 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type |
279 << " certificate at index " << cert_index; | 292 << " certificate at index " << cert_index; |
280 return false; | 293 return NULL; |
281 } | 294 } |
282 return true; | 295 |
| 296 // Have to set the label again, because PKCS#11 seems to want to set |
| 297 // it to token:nickname. We have to set it the first time so that |
| 298 // it gets properly imported into the low-level token inside of |
| 299 // ImportCACerts or ImportServerCert. |
| 300 if (!x509_cert->SetLabel(guid)) |
| 301 return NULL; |
| 302 |
| 303 return x509_cert; |
283 } | 304 } |
284 | 305 |
285 bool OncNetworkParser::ParseClientCertificate( | 306 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseClientCertificate( |
286 int cert_index, | 307 int cert_index, |
| 308 const std::string& guid, |
287 base::DictionaryValue* certificate) { | 309 base::DictionaryValue* certificate) { |
288 net::CertDatabase cert_database; | 310 net::CertDatabase cert_database; |
289 std::string pkcs12_data; | 311 std::string pkcs12_data; |
290 if (!certificate->GetString("PKCS12", &pkcs12_data) || | 312 if (!certificate->GetString("PKCS12", &pkcs12_data) || |
291 pkcs12_data.empty()) { | 313 pkcs12_data.empty()) { |
292 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " | 314 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " |
293 << "certificate at index " << cert_index; | 315 << "certificate at index " << cert_index; |
294 return false; | 316 return NULL; |
295 } | 317 } |
296 | 318 |
297 std::string decoded_pkcs12; | 319 std::string decoded_pkcs12; |
298 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { | 320 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { |
299 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" | 321 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" |
300 << pkcs12_data << "\"."; | 322 << pkcs12_data << "\"."; |
301 return false; | 323 return NULL; |
302 } | 324 } |
303 | 325 |
304 // Since this has a private key, always use the private module. | 326 // Since this has a private key, always use the private module. |
305 scoped_refptr<net::CryptoModule> module(cert_database.GetPrivateModule()); | 327 scoped_refptr<net::CryptoModule> module(cert_database.GetPrivateModule()); |
| 328 net::CertificateList imported_certs; |
306 int result = cert_database.ImportFromPKCS12( | 329 int result = cert_database.ImportFromPKCS12( |
307 module.get(), decoded_pkcs12, string16(), false); | 330 module.get(), decoded_pkcs12, string16(), false, &imported_certs); |
308 if (result != net::OK) { | 331 if (result != net::OK) { |
309 LOG(WARNING) << "ONC File: Unable to import Client certificate at index " | 332 LOG(WARNING) << "ONC File: Unable to import Client certificate at index " |
310 << cert_index | 333 << cert_index |
311 << " (error " << net::ErrorToString(result) << ")."; | 334 << " (error " << net::ErrorToString(result) << ")."; |
312 return false; | 335 return NULL; |
313 } | 336 } |
314 return true; | 337 |
| 338 if (imported_certs.size() == 0ul) { |
| 339 LOG(WARNING) << "ONC File: PKCS12 data contains no importable certificates" |
| 340 << " at index " << cert_index; |
| 341 return NULL; |
| 342 } |
| 343 |
| 344 if (imported_certs.size() != 1ul) { |
| 345 LOG(WARNING) << "ONC File: PKCS12 data at index " << cert_index |
| 346 << " contains more than one certificate. Only the first one will" |
| 347 << " be imported."; |
| 348 } |
| 349 |
| 350 scoped_refptr<net::X509Certificate> cert_result = imported_certs[0]; |
| 351 if (!cert_result->SetLabel(guid)) |
| 352 return NULL; |
| 353 |
| 354 return cert_result; |
315 } | 355 } |
316 | 356 |
317 // -------------------- OncWirelessNetworkParser -------------------- | 357 // -------------------- OncWirelessNetworkParser -------------------- |
318 | 358 |
319 OncWirelessNetworkParser::OncWirelessNetworkParser() {} | 359 OncWirelessNetworkParser::OncWirelessNetworkParser() {} |
320 OncWirelessNetworkParser::~OncWirelessNetworkParser() {} | 360 OncWirelessNetworkParser::~OncWirelessNetworkParser() {} |
321 | 361 |
322 bool OncWirelessNetworkParser::ParseValue(PropertyIndex index, | 362 bool OncWirelessNetworkParser::ParseValue(PropertyIndex index, |
323 const base::Value& value, | 363 const base::Value& value, |
324 Network* network) { | 364 Network* network) { |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 static EnumMapper<ProviderType>::Pair table[] = { | 672 static EnumMapper<ProviderType>::Pair table[] = { |
633 { flimflam::kProviderL2tpIpsec, PROVIDER_TYPE_L2TP_IPSEC_PSK }, | 673 { flimflam::kProviderL2tpIpsec, PROVIDER_TYPE_L2TP_IPSEC_PSK }, |
634 { flimflam::kProviderOpenVpn, PROVIDER_TYPE_OPEN_VPN }, | 674 { flimflam::kProviderOpenVpn, PROVIDER_TYPE_OPEN_VPN }, |
635 }; | 675 }; |
636 static EnumMapper<ProviderType> parser( | 676 static EnumMapper<ProviderType> parser( |
637 table, arraysize(table), PROVIDER_TYPE_MAX); | 677 table, arraysize(table), PROVIDER_TYPE_MAX); |
638 return parser.Get(type); | 678 return parser.Get(type); |
639 } | 679 } |
640 | 680 |
641 } // namespace chromeos | 681 } // namespace chromeos |
OLD | NEW |