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

Side by Side Diff: chrome/browser/chromeos/cros/onc_network_parser.cc

Issue 8566056: This applies GUIDs to certificate and key nicknames when (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix memory leak Created 9 years 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
OLDNEW
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 <pk11pub.h>
8 #include <keyhi.h>
9
7 #include "base/base64.h" 10 #include "base/base64.h"
8 #include "base/json/json_value_serializer.h" 11 #include "base/json/json_value_serializer.h"
9 #include "base/json/json_writer.h" // for debug output only. 12 #include "base/json/json_writer.h" // for debug output only.
10 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
11 #include "base/values.h" 14 #include "base/values.h"
12 #include "chrome/browser/chromeos/cros/native_network_constants.h" 15 #include "chrome/browser/chromeos/cros/native_network_constants.h"
13 #include "chrome/browser/chromeos/cros/native_network_parser.h" 16 #include "chrome/browser/chromeos/cros/native_network_parser.h"
14 #include "chrome/browser/chromeos/cros/network_library.h" 17 #include "chrome/browser/chromeos/cros/network_library.h"
15 #include "net/base/cert_database.h" 18 #include "net/base/cert_database.h"
16 #include "net/base/crypto_module.h" 19 #include "net/base/crypto_module.h"
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 LOG(WARNING) << "OncNetworkParser received bad ONC file: " << parse_error_; 196 LOG(WARNING) << "OncNetworkParser received bad ONC file: " << parse_error_;
194 } else { 197 } else {
195 root_dict_.reset(static_cast<DictionaryValue*>(root.release())); 198 root_dict_.reset(static_cast<DictionaryValue*>(root.release()));
196 // At least one of NetworkConfigurations or Certificates is required. 199 // At least one of NetworkConfigurations or Certificates is required.
197 bool has_network_configurations = 200 bool has_network_configurations =
198 root_dict_->GetList("NetworkConfigurations", &network_configs_); 201 root_dict_->GetList("NetworkConfigurations", &network_configs_);
199 bool has_certificates = 202 bool has_certificates =
200 root_dict_->GetList("Certificates", &certificates_); 203 root_dict_->GetList("Certificates", &certificates_);
201 VLOG(2) << "ONC file has " << GetNetworkConfigsSize() << " networks and " 204 VLOG(2) << "ONC file has " << GetNetworkConfigsSize() << " networks and "
202 << GetCertificatesSize() << " certificates"; 205 << GetCertificatesSize() << " certificates";
203 if (!has_network_configurations || !has_certificates) { 206 LOG_IF(WARNING, (!has_network_configurations && !has_certificates))
204 LOG(WARNING) << "ONC file has no NetworkConfigurations or Certificates."; 207 << "ONC file has no NetworkConfigurations or Certificates.";
205 }
206 } 208 }
207 } 209 }
208 210
209 OncNetworkParser::OncNetworkParser() 211 OncNetworkParser::OncNetworkParser()
210 : NetworkParser(get_onc_mapper()), 212 : NetworkParser(get_onc_mapper()),
211 network_configs_(NULL), 213 network_configs_(NULL),
212 certificates_(NULL) { 214 certificates_(NULL) {
213 } 215 }
214 216
215 OncNetworkParser::~OncNetworkParser() { 217 OncNetworkParser::~OncNetworkParser() {
216 } 218 }
217 219
218 // static 220 // static
219 const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() { 221 const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() {
220 return get_onc_mapper(); 222 return get_onc_mapper();
221 } 223 }
222 224
223 int OncNetworkParser::GetNetworkConfigsSize() const { 225 int OncNetworkParser::GetNetworkConfigsSize() const {
224 return network_configs_ ? network_configs_->GetSize() : 0; 226 return network_configs_ ? network_configs_->GetSize() : 0;
225 } 227 }
226 228
227 int OncNetworkParser::GetCertificatesSize() const { 229 int OncNetworkParser::GetCertificatesSize() const {
228 return certificates_ ? certificates_->GetSize() : 0; 230 return certificates_ ? certificates_->GetSize() : 0;
229 } 231 }
230 232
231 bool OncNetworkParser::ParseCertificate(int cert_index) { 233 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseCertificate(
234 int cert_index) {
232 CHECK(certificates_); 235 CHECK(certificates_);
233 CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize()); 236 CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize());
234 CHECK(cert_index >= 0); 237 CHECK(cert_index >= 0);
235 base::DictionaryValue* certificate = NULL; 238 base::DictionaryValue* certificate = NULL;
236 certificates_->GetDictionary(cert_index, &certificate); 239 certificates_->GetDictionary(cert_index, &certificate);
237 CHECK(certificate); 240 CHECK(certificate);
238 241
239 if (VLOG_IS_ON(2)) { 242 if (VLOG_IS_ON(2)) {
240 std::string certificate_json; 243 std::string certificate_json;
241 base::JSONWriter::Write(static_cast<base::Value*>(certificate), 244 base::JSONWriter::Write(static_cast<base::Value*>(certificate),
242 true, &certificate_json); 245 true, &certificate_json);
243 VLOG(2) << "Parsing certificate at index " << cert_index 246 VLOG(2) << "Parsing certificate at index " << cert_index
244 << ": " << certificate_json; 247 << ": " << certificate_json;
245 } 248 }
246 249
247 // Get out the attributes of the given cert. 250 // Get out the attributes of the given certificate.
248 std::string guid; 251 std::string guid;
249 bool remove = false; 252 bool remove = false;
250 if (!certificate->GetString("GUID", &guid) || guid.empty()) { 253 if (!certificate->GetString("GUID", &guid) || guid.empty()) {
251 LOG(WARNING) << "ONC File: certificate missing identifier at index" 254 LOG(WARNING) << "ONC File: certificate missing identifier at index"
252 << cert_index; 255 << cert_index;
253 return false; 256 return NULL;
254 } 257 }
255 258
256 if (!certificate->GetBoolean("Remove", &remove)) 259 if (!certificate->GetBoolean("Remove", &remove))
257 remove = false; 260 remove = false;
258 261
259 net::CertDatabase cert_database; 262 net::CertDatabase cert_database;
260 if (remove) 263 if (remove) {
261 return cert_database.DeleteCertAndKeyByLabel(guid); 264 bool success = DeleteCertAndKeyByNickname(guid);
265 DCHECK(success);
266 // TODO(gspencer): return removed certificate?
267 return NULL;
268 }
262 269
263 // Not removing, so let's get the data we need to add this cert. 270 // Not removing, so let's get the data we need to add this certificate.
264 std::string cert_type; 271 std::string cert_type;
265 certificate->GetString("Type", &cert_type); 272 certificate->GetString("Type", &cert_type);
266 if (cert_type == "Server" || cert_type == "Authority") { 273 if (cert_type == "Server" || cert_type == "Authority") {
267 return ParseServerOrCaCertificate(cert_index, cert_type, certificate); 274 return ParseServerOrCaCertificate(cert_index, cert_type, guid, certificate);
268 } 275 }
269 if (cert_type == "Client") { 276 if (cert_type == "Client") {
270 return ParseClientCertificate(cert_index, certificate); 277 return ParseClientCertificate(cert_index, guid, certificate);
271 } 278 }
272 279
273 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type 280 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type
274 << " at index " << cert_index; 281 << " at index " << cert_index;
275 return false; 282 return NULL;
276 } 283 }
277 284
278 Network* OncNetworkParser::ParseNetwork(int n) { 285 Network* OncNetworkParser::ParseNetwork(int n) {
279 if (!network_configs_) 286 if (!network_configs_)
280 return NULL; 287 return NULL;
281 DictionaryValue* info = NULL; 288 DictionaryValue* info = NULL;
282 if (!network_configs_->GetDictionary(n, &info)) 289 if (!network_configs_->GetDictionary(n, &info))
283 return NULL; 290 return NULL;
284 if (VLOG_IS_ON(2)) { 291 if (VLOG_IS_ON(2)) {
285 std::string network_json; 292 std::string network_json;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 return type_string; 350 return type_string;
344 } 351 }
345 352
346 std::string OncNetworkParser::GetGuidFromDictionary( 353 std::string OncNetworkParser::GetGuidFromDictionary(
347 const base::DictionaryValue& info) { 354 const base::DictionaryValue& info) {
348 std::string guid_string; 355 std::string guid_string;
349 info.GetString("GUID", &guid_string); 356 info.GetString("GUID", &guid_string);
350 return guid_string; 357 return guid_string;
351 } 358 }
352 359
353 bool OncNetworkParser::ParseServerOrCaCertificate( 360 scoped_refptr<net::X509Certificate>
361 OncNetworkParser::ParseServerOrCaCertificate(
354 int cert_index, 362 int cert_index,
355 const std::string& cert_type, 363 const std::string& cert_type,
364 const std::string& guid,
356 base::DictionaryValue* certificate) { 365 base::DictionaryValue* certificate) {
357 net::CertDatabase cert_database; 366 net::CertDatabase cert_database;
358 bool web_trust = false; 367 bool web_trust = false;
359 base::ListValue* trust_list = NULL; 368 base::ListValue* trust_list = NULL;
360 if (certificate->GetList("Trust", &trust_list)) { 369 if (certificate->GetList("Trust", &trust_list)) {
361 for (size_t i = 0; i < trust_list->GetSize(); ++i) { 370 for (size_t i = 0; i < trust_list->GetSize(); ++i) {
362 std::string trust_type; 371 std::string trust_type;
363 if (!trust_list->GetString(i, &trust_type)) { 372 if (!trust_list->GetString(i, &trust_type)) {
364 LOG(WARNING) << "ONC File: certificate trust is invalid at index " 373 LOG(WARNING) << "ONC File: certificate trust is invalid at index "
365 << cert_index; 374 << cert_index;
366 return false; 375 return NULL;
367 } 376 }
368 if (trust_type == "Web") { 377 if (trust_type == "Web") {
369 web_trust = true; 378 web_trust = true;
370 } else { 379 } else {
371 LOG(WARNING) << "ONC File: certificate contains unknown " 380 LOG(WARNING) << "ONC File: certificate contains unknown "
372 << "trust type: " << trust_type 381 << "trust type: " << trust_type
373 << " at index " << cert_index; 382 << " at index " << cert_index;
374 return false; 383 return NULL;
375 } 384 }
376 } 385 }
377 } 386 }
378 387
379 std::string x509_data; 388 std::string x509_data;
380 if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) { 389 if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) {
381 LOG(WARNING) << "ONC File: certificate missing appropriate " 390 LOG(WARNING) << "ONC File: certificate missing appropriate "
382 << "certificate data for type: " << cert_type 391 << "certificate data for type: " << cert_type
383 << " at index " << cert_index; 392 << " at index " << cert_index;
384 return false; 393 return NULL;
385 } 394 }
386 395
387 std::string decoded_x509; 396 std::string decoded_x509;
388 if (!base::Base64Decode(x509_data, &decoded_x509)) { 397 if (!base::Base64Decode(x509_data, &decoded_x509)) {
389 LOG(WARNING) << "Unable to base64 decode X509 data: \"" 398 LOG(WARNING) << "Unable to base64 decode X509 data: \""
390 << x509_data << "\"."; 399 << x509_data << "\".";
391 return false; 400 return NULL;
392 } 401 }
393 402
394 scoped_refptr<net::X509Certificate> x509_cert( 403 scoped_refptr<net::X509Certificate> x509_cert =
395 net::X509Certificate::CreateFromBytes(decoded_x509.c_str(), 404 net::X509Certificate::CreateFromBytesWithNickname(
396 decoded_x509.size())); 405 decoded_x509.c_str(),
406 decoded_x509.size(),
407 guid.c_str());
397 if (!x509_cert.get()) { 408 if (!x509_cert.get()) {
398 LOG(WARNING) << "Unable to create X509 certificate from bytes."; 409 LOG(WARNING) << "Unable to create X509 certificate from bytes.";
399 return false; 410 return NULL;
400 } 411 }
412
401 net::CertificateList cert_list; 413 net::CertificateList cert_list;
402 cert_list.push_back(x509_cert); 414 cert_list.push_back(x509_cert);
403 net::CertDatabase::ImportCertFailureList failures; 415 net::CertDatabase::ImportCertFailureList failures;
404 bool success = false; 416 bool success = false;
405 if (cert_type == "Server") { 417 if (cert_type == "Server") {
406 success = cert_database.ImportServerCert(cert_list, &failures); 418 success = cert_database.ImportServerCert(cert_list, &failures);
407 } else { // Authority cert 419 } else { // Authority cert
408 net::CertDatabase::TrustBits trust = web_trust ? 420 net::CertDatabase::TrustBits trust = web_trust ?
409 net::CertDatabase::TRUSTED_SSL : 421 net::CertDatabase::TRUSTED_SSL :
410 net::CertDatabase::UNTRUSTED; 422 net::CertDatabase::UNTRUSTED;
411 success = cert_database.ImportCACerts(cert_list, trust, &failures); 423 success = cert_database.ImportCACerts(cert_list, trust, &failures);
wtc 2011/12/10 00:58:43 Another approach to avoid adding the default_nickn
Greg Spencer (Chromium) 2011/12/12 04:05:03 Well, the problem is that the multiplicity of the
412 } 424 }
413 if (!failures.empty()) { 425 if (!failures.empty()) {
414 LOG(WARNING) << "ONC File: Error (" 426 LOG(WARNING) << "ONC File: Error ("
415 << net::ErrorToString(failures[0].net_error) 427 << net::ErrorToString(failures[0].net_error)
416 << ") importing " << cert_type << " certificate at index " 428 << ") importing " << cert_type << " certificate at index "
417 << cert_index; 429 << cert_index;
418 return false; 430 return NULL;
419 } 431 }
420 if (!success) { 432 if (!success) {
421 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type 433 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type
422 << " certificate at index " << cert_index; 434 << " certificate at index " << cert_index;
423 return false; 435 return NULL;
424 } 436 }
425 VLOG(2) << "Successfully imported server/ca certificate at index " 437 VLOG(2) << "Successfully imported server/ca certificate at index "
426 << cert_index; 438 << cert_index;
427 return true; 439
440 return x509_cert;
428 } 441 }
429 442
430 bool OncNetworkParser::ParseClientCertificate( 443 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseClientCertificate(
431 int cert_index, 444 int cert_index,
445 const std::string& guid,
432 base::DictionaryValue* certificate) { 446 base::DictionaryValue* certificate) {
433 net::CertDatabase cert_database; 447 net::CertDatabase cert_database;
434 std::string pkcs12_data; 448 std::string pkcs12_data;
435 if (!certificate->GetString("PKCS12", &pkcs12_data) || 449 if (!certificate->GetString("PKCS12", &pkcs12_data) ||
436 pkcs12_data.empty()) { 450 pkcs12_data.empty()) {
437 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " 451 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client "
438 << "certificate at index " << cert_index; 452 << "certificate at index " << cert_index;
439 return false; 453 return NULL;
440 } 454 }
441 455
442 std::string decoded_pkcs12; 456 std::string decoded_pkcs12;
443 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { 457 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) {
444 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" 458 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \""
445 << pkcs12_data << "\"."; 459 << pkcs12_data << "\".";
446 return false; 460 return NULL;
447 } 461 }
448 462
449 // Since this has a private key, always use the private module. 463 // Since this has a private key, always use the private module.
450 scoped_refptr<net::CryptoModule> module(cert_database.GetPrivateModule()); 464 scoped_refptr<net::CryptoModule> module(cert_database.GetPrivateModule());
465 net::CertificateList imported_certs;
466
451 int result = cert_database.ImportFromPKCS12( 467 int result = cert_database.ImportFromPKCS12(
452 module.get(), decoded_pkcs12, string16(), false); 468 module.get(), decoded_pkcs12, string16(), false, &imported_certs);
453 if (result != net::OK) { 469 if (result != net::OK) {
454 LOG(WARNING) << "ONC File: Unable to import Client certificate at index " 470 LOG(WARNING) << "ONC File: Unable to import Client certificate at index "
455 << cert_index 471 << cert_index
456 << " (error " << net::ErrorToString(result) << ")."; 472 << " (error " << net::ErrorToString(result) << ").";
457 return false; 473 return NULL;
458 } 474 }
475
476 if (imported_certs.size() == 0) {
477 LOG(WARNING) << "ONC File: PKCS12 data contains no importable certificates"
478 << " at index " << cert_index;
479 return NULL;
480 }
481
482 if (imported_certs.size() != 1) {
483 LOG(WARNING) << "ONC File: PKCS12 data at index " << cert_index
484 << " contains more than one certificate. Only the first one will"
485 << " be imported.";
486 }
487
488 scoped_refptr<net::X509Certificate> cert_result = imported_certs[0];
489
490 // Find the private key associated with this certificate, and set the
491 // nickname on it.
492 SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert(
493 cert_result->os_cert_handle()->slot,
494 cert_result->os_cert_handle(),
495 NULL); // wincx
496 if (private_key) {
497 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str()));
498 SECKEY_DestroyPrivateKey(private_key);
499 } else {
500 LOG(WARNING) << "ONC File: Unable to find private key for cert at index"
501 << cert_index;
502 }
503
459 VLOG(2) << "Successfully imported client certificate at index " 504 VLOG(2) << "Successfully imported client certificate at index "
460 << cert_index; 505 << cert_index;
461 return true; 506 return cert_result;
462 } 507 }
463 508
464 bool OncNetworkParser::ParseNestedObject(Network* network, 509 bool OncNetworkParser::ParseNestedObject(Network* network,
465 const std::string& onc_type, 510 const std::string& onc_type,
466 const base::Value& value, 511 const base::Value& value,
467 OncValueSignature* signature, 512 OncValueSignature* signature,
468 ParserPointer parser) { 513 ParserPointer parser) {
469 bool any_errors = false; 514 bool any_errors = false;
470 if (!value.IsType(base::Value::TYPE_DICTIONARY)) { 515 if (!value.IsType(base::Value::TYPE_DICTIONARY)) {
471 VLOG(1) << network->name() << ": expected object of type " << onc_type; 516 VLOG(1) << network->name() << ": expected object of type " << onc_type;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 case PROPERTY_INDEX_GUID: 626 case PROPERTY_INDEX_GUID:
582 case PROPERTY_INDEX_NAME: 627 case PROPERTY_INDEX_NAME:
583 // Fall back to generic parser for these. 628 // Fall back to generic parser for these.
584 return parser->ParseValue(index, value, network); 629 return parser->ParseValue(index, value, network);
585 default: 630 default:
586 break; 631 break;
587 } 632 }
588 return false; 633 return false;
589 } 634 }
590 635
636 // static
637 bool OncNetworkParser::DeleteCertAndKeyByNickname(const std::string& label) {
638 net::CertificateList cert_list;
639 ListCertsWithNickname(label, &cert_list);
640 net::CertDatabase cert_db;
641 bool result = true;
642 for (net::CertificateList::iterator iter = cert_list.begin();
643 iter != cert_list.end(); ++iter) {
644 // If we fail, we try and delete the rest still.
645 // TODO(gspencer): this isn't very "transactional". If we fail on some, but
646 // not all, then it's possible to leave things in a weird state.
647 // Luckily there should only be one cert with a particular
648 // label, and the cert not being found is one of the few reasons the
649 // delete could fail, but still... The other choice is to return
650 // failure immediately, but that doesn't seem to do what is intended.
651 if (!cert_db.DeleteCertAndKey(iter->get()))
652 result = false;
653 }
654 return result;
655 }
656
657 // static
658 void OncNetworkParser::ListCertsWithNickname(const std::string& label,
659 net::CertificateList* result) {
660 net::CertificateList all_certs;
661 net::CertDatabase cert_db;
662 cert_db.ListCerts(&all_certs);
663 result->clear();
664 for (net::CertificateList::iterator iter = all_certs.begin();
665 iter != all_certs.end(); ++iter) {
666 if (iter->get()->os_cert_handle()->nickname) {
667 const char* delimiter =
668 ::strchr(iter->get()->os_cert_handle()->nickname, ':');
wtc 2011/12/10 00:58:43 You should explain why you are looking for ':' her
Greg Spencer (Chromium) 2011/12/12 04:05:03 Done.
669 if (delimiter) {
670 delimiter++; // move past the colon.
671 if (strcmp(delimiter, label.c_str()) == 0) {
672 result->push_back(*iter);
wtc 2011/12/10 00:58:43 IMPORTANT: should we add a 'continue' statement he
Greg Spencer (Chromium) 2011/12/12 04:05:03 Good catch, thanks!
673 }
674 }
675 }
676 // Now we find the private key for this certificate and see if it has a
677 // nickname that matches. If there is a private key, and it matches,
678 // then this is a client cert that we are looking for.
679 SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert(
680 iter->get()->os_cert_handle()->slot,
681 iter->get()->os_cert_handle(),
682 NULL); // wincx
683 if (private_key) {
684 char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key);
685 if (private_key_nickname && private_key_nickname == label)
686 result->push_back(*iter);
687 PORT_Free(private_key_nickname);
688 SECKEY_DestroyPrivateKey(private_key);
689 }
690 }
691 }
692
591 // -------------------- OncWirelessNetworkParser -------------------- 693 // -------------------- OncWirelessNetworkParser --------------------
592 694
593 OncWirelessNetworkParser::OncWirelessNetworkParser() {} 695 OncWirelessNetworkParser::OncWirelessNetworkParser() {}
594 OncWirelessNetworkParser::~OncWirelessNetworkParser() {} 696 OncWirelessNetworkParser::~OncWirelessNetworkParser() {}
595 697
596 // -------------------- OncWifiNetworkParser -------------------- 698 // -------------------- OncWifiNetworkParser --------------------
597 699
598 OncWifiNetworkParser::OncWifiNetworkParser() {} 700 OncWifiNetworkParser::OncWifiNetworkParser() {}
599 701
600 OncWifiNetworkParser::~OncWifiNetworkParser() {} 702 OncWifiNetworkParser::~OncWifiNetworkParser() {}
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 // on the value of AuthenticationType. 1147 // on the value of AuthenticationType.
1046 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK }, 1148 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK },
1047 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN }, 1149 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN },
1048 }; 1150 };
1049 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser, 1151 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser,
1050 (table, arraysize(table), PROVIDER_TYPE_MAX)); 1152 (table, arraysize(table), PROVIDER_TYPE_MAX));
1051 return parser.Get(type); 1153 return parser.Get(type);
1052 } 1154 }
1053 1155
1054 } // namespace chromeos 1156 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698