| OLD | NEW |
| 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 "chrome/browser/chromeos/cros/onc_network_parser.h" | 5 #include "chrome/browser/chromeos/cros/onc_network_parser.h" |
| 6 | 6 |
| 7 #include <keyhi.h> | 7 #include <keyhi.h> |
| 8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "chrome/browser/chromeos/cros/onc_constants.h" | 21 #include "chrome/browser/chromeos/cros/onc_constants.h" |
| 22 #include "chrome/browser/chromeos/proxy_config_service_impl.h" | 22 #include "chrome/browser/chromeos/proxy_config_service_impl.h" |
| 23 #include "chrome/browser/prefs/proxy_config_dictionary.h" | 23 #include "chrome/browser/prefs/proxy_config_dictionary.h" |
| 24 #include "chrome/common/net/x509_certificate_model.h" | 24 #include "chrome/common/net/x509_certificate_model.h" |
| 25 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
| 26 #include "crypto/encryptor.h" | 26 #include "crypto/encryptor.h" |
| 27 #include "crypto/hmac.h" | 27 #include "crypto/hmac.h" |
| 28 #include "crypto/scoped_nss_types.h" | 28 #include "crypto/scoped_nss_types.h" |
| 29 #include "crypto/symmetric_key.h" | 29 #include "crypto/symmetric_key.h" |
| 30 #include "grit/generated_resources.h" | 30 #include "grit/generated_resources.h" |
| 31 #include "net/base/cert_database.h" | |
| 32 #include "net/base/crypto_module.h" | 31 #include "net/base/crypto_module.h" |
| 33 #include "net/base/net_errors.h" | 32 #include "net/base/net_errors.h" |
| 33 #include "net/base/nss_cert_database.h" |
| 34 #include "net/base/pem_tokenizer.h" | 34 #include "net/base/pem_tokenizer.h" |
| 35 #include "net/base/x509_certificate.h" | 35 #include "net/base/x509_certificate.h" |
| 36 #include "net/proxy/proxy_bypass_rules.h" | 36 #include "net/proxy/proxy_bypass_rules.h" |
| 37 #include "third_party/cros_system_api/dbus/service_constants.h" | 37 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 38 #include "ui/base/l10n/l10n_util.h" | 38 #include "ui/base/l10n/l10n_util.h" |
| 39 | 39 |
| 40 namespace chromeos { | 40 namespace chromeos { |
| 41 | 41 |
| 42 // Local constants. | 42 // Local constants. |
| 43 namespace { | 43 namespace { |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 LOG(WARNING) << "ONC File: certificate missing identifier at index" | 519 LOG(WARNING) << "ONC File: certificate missing identifier at index" |
| 520 << cert_index; | 520 << cert_index; |
| 521 parse_error_ = l10n_util::GetStringUTF8( | 521 parse_error_ = l10n_util::GetStringUTF8( |
| 522 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_MISSING); | 522 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_MISSING); |
| 523 return NULL; | 523 return NULL; |
| 524 } | 524 } |
| 525 | 525 |
| 526 if (!certificate->GetBoolean("Remove", &remove)) | 526 if (!certificate->GetBoolean("Remove", &remove)) |
| 527 remove = false; | 527 remove = false; |
| 528 | 528 |
| 529 net::CertDatabase cert_database; | |
| 530 if (remove) { | 529 if (remove) { |
| 531 if (!DeleteCertAndKeyByNickname(guid)) { | 530 if (!DeleteCertAndKeyByNickname(guid)) { |
| 532 parse_error_ = l10n_util::GetStringUTF8( | 531 parse_error_ = l10n_util::GetStringUTF8( |
| 533 IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); | 532 IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); |
| 534 } | 533 } |
| 535 return NULL; | 534 return NULL; |
| 536 } | 535 } |
| 537 | 536 |
| 538 // Not removing, so let's get the data we need to add this certificate. | 537 // Not removing, so let's get the data we need to add this certificate. |
| 539 std::string cert_type; | 538 std::string cert_type; |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 // identical certificate known to NSS, so we can safely import the | 922 // identical certificate known to NSS, so we can safely import the |
| 924 // certificate. The GUID being imported may still be on a different | 923 // certificate. The GUID being imported may still be on a different |
| 925 // certificate, and we could jump through hoops to reimport the existing | 924 // certificate, and we could jump through hoops to reimport the existing |
| 926 // certificate with a different nickname. However, that would mean lots of | 925 // certificate with a different nickname. However, that would mean lots of |
| 927 // effort for a case that's pretty much illegal (reusing GUIDs contradicts | 926 // effort for a case that's pretty much illegal (reusing GUIDs contradicts |
| 928 // the intention of GUIDs), so we just report an error. | 927 // the intention of GUIDs), so we just report an error. |
| 929 // | 928 // |
| 930 // TODO(mnissler, gspencer): We should probably switch to a mode where we | 929 // TODO(mnissler, gspencer): We should probably switch to a mode where we |
| 931 // keep our own database for mapping GUIDs to certs in order to enable several | 930 // keep our own database for mapping GUIDs to certs in order to enable several |
| 932 // GUIDs to map to the same cert. See http://crosbug.com/26073. | 931 // GUIDs to map to the same cert. See http://crosbug.com/26073. |
| 933 net::CertDatabase cert_database; | 932 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); |
| 934 if (x509_cert->os_cert_handle()->isperm) { | 933 if (x509_cert->os_cert_handle()->isperm) { |
| 935 if (!cert_database.DeleteCertAndKey(x509_cert.get())) { | 934 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { |
| 936 parse_error_ = l10n_util::GetStringUTF8( | 935 parse_error_ = l10n_util::GetStringUTF8( |
| 937 IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); | 936 IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); |
| 938 return NULL; | 937 return NULL; |
| 939 } | 938 } |
| 940 | 939 |
| 941 // Reload the cert here to get an actual temporary cert instance. | 940 // Reload the cert here to get an actual temporary cert instance. |
| 942 x509_cert = | 941 x509_cert = |
| 943 net::X509Certificate::CreateFromBytesWithNickname( | 942 net::X509Certificate::CreateFromBytesWithNickname( |
| 944 decoded_x509.data(), | 943 decoded_x509.data(), |
| 945 decoded_x509.size(), | 944 decoded_x509.size(), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 960 ListCertsWithNickname(guid, &certs); | 959 ListCertsWithNickname(guid, &certs); |
| 961 if (!certs.empty()) { | 960 if (!certs.empty()) { |
| 962 LOG(WARNING) << "Cert GUID is already in use: " << guid; | 961 LOG(WARNING) << "Cert GUID is already in use: " << guid; |
| 963 parse_error_ = l10n_util::GetStringUTF8( | 962 parse_error_ = l10n_util::GetStringUTF8( |
| 964 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_COLLISION); | 963 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_COLLISION); |
| 965 return NULL; | 964 return NULL; |
| 966 } | 965 } |
| 967 | 966 |
| 968 net::CertificateList cert_list; | 967 net::CertificateList cert_list; |
| 969 cert_list.push_back(x509_cert); | 968 cert_list.push_back(x509_cert); |
| 970 net::CertDatabase::ImportCertFailureList failures; | 969 net::NSSCertDatabase::ImportCertFailureList failures; |
| 971 bool success = false; | 970 bool success = false; |
| 972 net::CertDatabase::TrustBits trust = web_trust ? | 971 net::NSSCertDatabase::TrustBits trust = web_trust ? |
| 973 net::CertDatabase::TRUSTED_SSL : | 972 net::NSSCertDatabase::TRUSTED_SSL : |
| 974 net::CertDatabase::TRUST_DEFAULT; | 973 net::NSSCertDatabase::TRUST_DEFAULT; |
| 975 if (cert_type == "Server") { | 974 if (cert_type == "Server") { |
| 976 success = cert_database.ImportServerCert(cert_list, trust, &failures); | 975 success = cert_database->ImportServerCert(cert_list, trust, &failures); |
| 977 } else { // Authority cert | 976 } else { // Authority cert |
| 978 success = cert_database.ImportCACerts(cert_list, trust, &failures); | 977 success = cert_database->ImportCACerts(cert_list, trust, &failures); |
| 979 } | 978 } |
| 980 if (!failures.empty()) { | 979 if (!failures.empty()) { |
| 981 LOG(WARNING) << "ONC File: Error (" | 980 LOG(WARNING) << "ONC File: Error (" |
| 982 << net::ErrorToString(failures[0].net_error) | 981 << net::ErrorToString(failures[0].net_error) |
| 983 << ") importing " << cert_type << " certificate at index " | 982 << ") importing " << cert_type << " certificate at index " |
| 984 << cert_index; | 983 << cert_index; |
| 985 parse_error_ = l10n_util::GetStringUTF8( | 984 parse_error_ = l10n_util::GetStringUTF8( |
| 986 IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); | 985 IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); |
| 987 return NULL; | 986 return NULL; |
| 988 } | 987 } |
| 989 if (!success) { | 988 if (!success) { |
| 990 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type | 989 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type |
| 991 << " certificate at index " << cert_index; | 990 << " certificate at index " << cert_index; |
| 992 parse_error_ = l10n_util::GetStringUTF8( | 991 parse_error_ = l10n_util::GetStringUTF8( |
| 993 IDS_NETWORK_CONFIG_ERROR_UNKNOWN); | 992 IDS_NETWORK_CONFIG_ERROR_UNKNOWN); |
| 994 return NULL; | 993 return NULL; |
| 995 } | 994 } |
| 996 VLOG(2) << "Successfully imported server/ca certificate at index " | 995 VLOG(2) << "Successfully imported server/ca certificate at index " |
| 997 << cert_index; | 996 << cert_index; |
| 998 | 997 |
| 999 return x509_cert; | 998 return x509_cert; |
| 1000 } | 999 } |
| 1001 | 1000 |
| 1002 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseClientCertificate( | 1001 scoped_refptr<net::X509Certificate> OncNetworkParser::ParseClientCertificate( |
| 1003 int cert_index, | 1002 int cert_index, |
| 1004 const std::string& guid, | 1003 const std::string& guid, |
| 1005 base::DictionaryValue* certificate) { | 1004 base::DictionaryValue* certificate) { |
| 1006 net::CertDatabase cert_database; | |
| 1007 std::string pkcs12_data; | 1005 std::string pkcs12_data; |
| 1008 if (!certificate->GetString("PKCS12", &pkcs12_data) || | 1006 if (!certificate->GetString("PKCS12", &pkcs12_data) || |
| 1009 pkcs12_data.empty()) { | 1007 pkcs12_data.empty()) { |
| 1010 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " | 1008 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " |
| 1011 << "certificate at index " << cert_index; | 1009 << "certificate at index " << cert_index; |
| 1012 parse_error_ = l10n_util::GetStringUTF8( | 1010 parse_error_ = l10n_util::GetStringUTF8( |
| 1013 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MISSING); | 1011 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MISSING); |
| 1014 return NULL; | 1012 return NULL; |
| 1015 } | 1013 } |
| 1016 | 1014 |
| 1017 std::string decoded_pkcs12; | 1015 std::string decoded_pkcs12; |
| 1018 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { | 1016 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { |
| 1019 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" | 1017 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" |
| 1020 << pkcs12_data << "\"."; | 1018 << pkcs12_data << "\"."; |
| 1021 parse_error_ = l10n_util::GetStringUTF8( | 1019 parse_error_ = l10n_util::GetStringUTF8( |
| 1022 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); | 1020 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); |
| 1023 return NULL; | 1021 return NULL; |
| 1024 } | 1022 } |
| 1025 | 1023 |
| 1026 // Since this has a private key, always use the private module. | 1024 // Since this has a private key, always use the private module. |
| 1027 scoped_refptr<net::CryptoModule> module(cert_database.GetPrivateModule()); | 1025 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); |
| 1026 scoped_refptr<net::CryptoModule> module(cert_database->GetPrivateModule()); |
| 1028 net::CertificateList imported_certs; | 1027 net::CertificateList imported_certs; |
| 1029 | 1028 |
| 1030 int result = cert_database.ImportFromPKCS12( | 1029 int result = cert_database->ImportFromPKCS12( |
| 1031 module.get(), decoded_pkcs12, string16(), false, &imported_certs); | 1030 module.get(), decoded_pkcs12, string16(), false, &imported_certs); |
| 1032 if (result != net::OK) { | 1031 if (result != net::OK) { |
| 1033 LOG(WARNING) << "ONC File: Unable to import Client certificate at index " | 1032 LOG(WARNING) << "ONC File: Unable to import Client certificate at index " |
| 1034 << cert_index | 1033 << cert_index |
| 1035 << " (error " << net::ErrorToString(result) << ")."; | 1034 << " (error " << net::ErrorToString(result) << ")."; |
| 1036 parse_error_ = l10n_util::GetStringUTF8( | 1035 parse_error_ = l10n_util::GetStringUTF8( |
| 1037 IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); | 1036 IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); |
| 1038 return NULL; | 1037 return NULL; |
| 1039 } | 1038 } |
| 1040 | 1039 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 }; | 1080 }; |
| 1082 CR_DEFINE_STATIC_LOCAL(EnumMapper<ClientCertType>, parser, | 1081 CR_DEFINE_STATIC_LOCAL(EnumMapper<ClientCertType>, parser, |
| 1083 (table, arraysize(table), CLIENT_CERT_TYPE_NONE)); | 1082 (table, arraysize(table), CLIENT_CERT_TYPE_NONE)); |
| 1084 return parser.Get(type); | 1083 return parser.Get(type); |
| 1085 } | 1084 } |
| 1086 | 1085 |
| 1087 // static | 1086 // static |
| 1088 void OncNetworkParser::ListCertsWithNickname(const std::string& label, | 1087 void OncNetworkParser::ListCertsWithNickname(const std::string& label, |
| 1089 net::CertificateList* result) { | 1088 net::CertificateList* result) { |
| 1090 net::CertificateList all_certs; | 1089 net::CertificateList all_certs; |
| 1091 net::CertDatabase cert_db; | 1090 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs); |
| 1092 cert_db.ListCerts(&all_certs); | |
| 1093 result->clear(); | 1091 result->clear(); |
| 1094 for (net::CertificateList::iterator iter = all_certs.begin(); | 1092 for (net::CertificateList::iterator iter = all_certs.begin(); |
| 1095 iter != all_certs.end(); ++iter) { | 1093 iter != all_certs.end(); ++iter) { |
| 1096 if (iter->get()->os_cert_handle()->nickname) { | 1094 if (iter->get()->os_cert_handle()->nickname) { |
| 1097 // Separate the nickname stored in the certificate at the colon, since | 1095 // Separate the nickname stored in the certificate at the colon, since |
| 1098 // NSS likes to store it as token:nickname. | 1096 // NSS likes to store it as token:nickname. |
| 1099 const char* delimiter = | 1097 const char* delimiter = |
| 1100 ::strchr(iter->get()->os_cert_handle()->nickname, ':'); | 1098 ::strchr(iter->get()->os_cert_handle()->nickname, ':'); |
| 1101 if (delimiter) { | 1099 if (delimiter) { |
| 1102 delimiter++; // move past the colon. | 1100 delimiter++; // move past the colon. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1120 PORT_Free(private_key_nickname); | 1118 PORT_Free(private_key_nickname); |
| 1121 SECKEY_DestroyPrivateKey(private_key); | 1119 SECKEY_DestroyPrivateKey(private_key); |
| 1122 } | 1120 } |
| 1123 } | 1121 } |
| 1124 } | 1122 } |
| 1125 | 1123 |
| 1126 // static | 1124 // static |
| 1127 bool OncNetworkParser::DeleteCertAndKeyByNickname(const std::string& label) { | 1125 bool OncNetworkParser::DeleteCertAndKeyByNickname(const std::string& label) { |
| 1128 net::CertificateList cert_list; | 1126 net::CertificateList cert_list; |
| 1129 ListCertsWithNickname(label, &cert_list); | 1127 ListCertsWithNickname(label, &cert_list); |
| 1130 net::CertDatabase cert_db; | |
| 1131 bool result = true; | 1128 bool result = true; |
| 1132 for (net::CertificateList::iterator iter = cert_list.begin(); | 1129 for (net::CertificateList::iterator iter = cert_list.begin(); |
| 1133 iter != cert_list.end(); ++iter) { | 1130 iter != cert_list.end(); ++iter) { |
| 1134 // If we fail, we try and delete the rest still. | 1131 // If we fail, we try and delete the rest still. |
| 1135 // TODO(gspencer): this isn't very "transactional". If we fail on some, but | 1132 // TODO(gspencer): this isn't very "transactional". If we fail on some, but |
| 1136 // not all, then it's possible to leave things in a weird state. | 1133 // not all, then it's possible to leave things in a weird state. |
| 1137 // Luckily there should only be one cert with a particular | 1134 // Luckily there should only be one cert with a particular |
| 1138 // label, and the cert not being found is one of the few reasons the | 1135 // label, and the cert not being found is one of the few reasons the |
| 1139 // delete could fail, but still... The other choice is to return | 1136 // delete could fail, but still... The other choice is to return |
| 1140 // failure immediately, but that doesn't seem to do what is intended. | 1137 // failure immediately, but that doesn't seem to do what is intended. |
| 1141 if (!cert_db.DeleteCertAndKey(iter->get())) | 1138 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get())) |
| 1142 result = false; | 1139 result = false; |
| 1143 } | 1140 } |
| 1144 return result; | 1141 return result; |
| 1145 } | 1142 } |
| 1146 | 1143 |
| 1147 // static | 1144 // static |
| 1148 std::string OncNetworkParser::GetPkcs11IdFromCertGuid(const std::string& guid) { | 1145 std::string OncNetworkParser::GetPkcs11IdFromCertGuid(const std::string& guid) { |
| 1149 // We have to look up the GUID to find the PKCS#11 ID that is needed. | 1146 // We have to look up the GUID to find the PKCS#11 ID that is needed. |
| 1150 net::CertificateList cert_list; | 1147 net::CertificateList cert_list; |
| 1151 ListCertsWithNickname(guid, &cert_list); | 1148 ListCertsWithNickname(guid, &cert_list); |
| (...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 // on the value of AuthenticationType. | 2024 // on the value of AuthenticationType. |
| 2028 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK }, | 2025 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK }, |
| 2029 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN }, | 2026 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN }, |
| 2030 }; | 2027 }; |
| 2031 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser, | 2028 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser, |
| 2032 (table, arraysize(table), PROVIDER_TYPE_MAX)); | 2029 (table, arraysize(table), PROVIDER_TYPE_MAX)); |
| 2033 return parser.Get(type); | 2030 return parser.Get(type); |
| 2034 } | 2031 } |
| 2035 | 2032 |
| 2036 } // namespace chromeos | 2033 } // namespace chromeos |
| OLD | NEW |