summaryrefslogtreecommitdiffstats
path: root/chromeos/network/onc
diff options
context:
space:
mode:
authorpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 16:42:18 +0000
committerpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 16:42:18 +0000
commitd46dc78255481d716d3be4da48f70a0bf06dabe6 (patch)
treead93eec88d64b552cd6718f41ea9c0a0b30902ae /chromeos/network/onc
parent5e5ce0faaee95df25a9ec4b1daa4ad50651ae8ee (diff)
downloadchromium_src-d46dc78255481d716d3be4da48f70a0bf06dabe6.zip
chromium_src-d46dc78255481d716d3be4da48f70a0bf06dabe6.tar.gz
chromium_src-d46dc78255481d716d3be4da48f70a0bf06dabe6.tar.bz2
Move PEM certificate decoding to onc_utils.
This prepares usage of the decoding in NetworkLibrary. While there, removed redundant namespace qualifiers from onc_utils.*. BUG=208986 Review URL: https://chromiumcodereview.appspot.com/17471005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207861 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/network/onc')
-rw-r--r--chromeos/network/onc/onc_certificate_importer.cc45
-rw-r--r--chromeos/network/onc/onc_utils.cc110
-rw-r--r--chromeos/network/onc/onc_utils.h18
3 files changed, 90 insertions, 83 deletions
diff --git a/chromeos/network/onc/onc_certificate_importer.cc b/chromeos/network/onc/onc_certificate_importer.cc
index fe8e66b..72c715e 100644
--- a/chromeos/network/onc/onc_certificate_importer.cc
+++ b/chromeos/network/onc/onc_certificate_importer.cc
@@ -13,10 +13,10 @@
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/onc/onc_constants.h"
+#include "chromeos/network/onc/onc_utils.h"
#include "net/base/crypto_module.h"
#include "net/base/net_errors.h"
#include "net/cert/nss_cert_database.h"
-#include "net/cert/pem_tokenizer.h"
#include "net/cert/x509_certificate.h"
#define ONC_LOG_WARNING(message) \
@@ -24,15 +24,6 @@
#define ONC_LOG_ERROR(message) \
NET_LOG_ERROR("ONC Certificate Import Error", message)
-namespace {
-
-// The PEM block header used for DER certificates
-const char kCertificateHeader[] = "CERTIFICATE";
-// This is an older PEM marker for DER certificates.
-const char kX509CertificateHeader[] = "X509 CERTIFICATE";
-
-} // namespace
-
namespace chromeos {
namespace onc {
@@ -206,34 +197,11 @@ bool CertificateImporter::ParseServerOrCaCertificate(
return false;
}
- // Parse PEM certificate, and get the decoded data for use in creating
- // certificate below.
- std::vector<std::string> pem_headers;
- pem_headers.push_back(kCertificateHeader);
- pem_headers.push_back(kX509CertificateHeader);
-
- net::PEMTokenizer pem_tokenizer(x509_data, pem_headers);
- std::string decoded_x509;
- if (!pem_tokenizer.GetNext()) {
- // If we failed to read the data as a PEM file, then let's just try plain
- // base64 decode: some versions of Spigots didn't apply the PEM marker
- // strings. For this to work, there has to be no white space, and it has to
- // only contain the base64-encoded data.
- if (!base::Base64Decode(x509_data, &decoded_x509)) {
- ONC_LOG_ERROR("Unable to base64 decode X509 data: " + x509_data);
- return false;
- }
- } else {
- decoded_x509 = pem_tokenizer.data();
- }
-
scoped_refptr<net::X509Certificate> x509_cert =
- net::X509Certificate::CreateFromBytesWithNickname(
- decoded_x509.data(),
- decoded_x509.size(),
- guid.c_str());
+ DecodePEMCertificate(x509_data, guid);
if (!x509_cert.get()) {
- ONC_LOG_ERROR("Unable to create X509 certificate from bytes.");
+ ONC_LOG_ERROR("Unable to create certificate from PEM encoding, type: " +
+ cert_type);
return false;
}
@@ -264,10 +232,7 @@ bool CertificateImporter::ParseServerOrCaCertificate(
}
// Reload the cert here to get an actual temporary cert instance.
- x509_cert = net::X509Certificate::CreateFromBytesWithNickname(
- decoded_x509.data(),
- decoded_x509.size(),
- guid.c_str());
+ x509_cert = DecodePEMCertificate(x509_data, guid);
if (!x509_cert.get()) {
ONC_LOG_ERROR("Unable to create X509 certificate from bytes.");
return false;
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 4dbbfba..7976826 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -18,6 +18,7 @@
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
+#include "net/cert/pem_tokenizer.h"
#define ONC_LOG_WARNING(message) NET_LOG_WARNING("ONC", message)
#define ONC_LOG_ERROR(message) NET_LOG_ERROR("ONC", message)
@@ -179,14 +180,14 @@ void ExpandField(const std::string fieldname,
std::string login_id;
if (substitution.GetSubstitute(substitutes::kLoginIDField, &login_id)) {
ReplaceSubstringsAfterOffset(&user_string, 0,
- onc::substitutes::kLoginIDField,
+ substitutes::kLoginIDField,
login_id);
}
std::string email;
if (substitution.GetSubstitute(substitutes::kEmailField, &email)) {
ReplaceSubstringsAfterOffset(&user_string, 0,
- onc::substitutes::kEmailField,
+ substitutes::kEmailField,
email);
}
@@ -224,10 +225,10 @@ void ExpandStringsInOncObject(
namespace {
-class OncMaskValues : public onc::Mapper {
+class OncMaskValues : public Mapper {
public:
static scoped_ptr<base::DictionaryValue> Mask(
- const onc::OncValueSignature& signature,
+ const OncValueSignature& signature,
const base::DictionaryValue& onc_object,
const std::string& mask) {
OncMaskValues masker(mask);
@@ -242,15 +243,15 @@ class OncMaskValues : public onc::Mapper {
virtual scoped_ptr<base::Value> MapField(
const std::string& field_name,
- const onc::OncValueSignature& object_signature,
+ const OncValueSignature& object_signature,
const base::Value& onc_value,
bool* found_unknown_field,
bool* error) OVERRIDE {
- if (onc::FieldIsCredential(object_signature, field_name)) {
+ if (FieldIsCredential(object_signature, field_name)) {
return scoped_ptr<base::Value>(new base::StringValue(mask_));
} else {
- return onc::Mapper::MapField(field_name, object_signature, onc_value,
- found_unknown_field, error);
+ return Mapper::MapField(field_name, object_signature, onc_value,
+ found_unknown_field, error);
}
}
@@ -261,92 +262,125 @@ class OncMaskValues : public onc::Mapper {
} // namespace
scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject(
- const onc::OncValueSignature& signature,
+ const OncValueSignature& signature,
const base::DictionaryValue& onc_object,
const std::string& mask) {
return OncMaskValues::Mask(signature, onc_object, mask);
}
-bool ParseAndValidateOncForImport(
- const std::string& onc_blob,
- chromeos::onc::ONCSource onc_source,
- const std::string& passphrase,
- base::ListValue* network_configs,
- base::ListValue* certificates) {
+bool ParseAndValidateOncForImport(const std::string& onc_blob,
+ ONCSource onc_source,
+ const std::string& passphrase,
+ base::ListValue* network_configs,
+ base::ListValue* certificates) {
certificates->Clear();
network_configs->Clear();
if (onc_blob.empty())
return true;
scoped_ptr<base::DictionaryValue> toplevel_onc =
- onc::ReadDictionaryFromJson(onc_blob);
+ ReadDictionaryFromJson(onc_blob);
if (toplevel_onc.get() == NULL) {
- LOG(ERROR) << "ONC loaded from " << onc::GetSourceAsString(onc_source)
+ LOG(ERROR) << "ONC loaded from " << GetSourceAsString(onc_source)
<< " is not a valid JSON dictionary.";
return false;
}
// Check and see if this is an encrypted ONC file. If so, decrypt it.
std::string onc_type;
- toplevel_onc->GetStringWithoutPathExpansion(onc::toplevel_config::kType,
+ toplevel_onc->GetStringWithoutPathExpansion(toplevel_config::kType,
&onc_type);
- if (onc_type == onc::toplevel_config::kEncryptedConfiguration) {
- toplevel_onc = onc::Decrypt(passphrase, *toplevel_onc);
+ if (onc_type == toplevel_config::kEncryptedConfiguration) {
+ toplevel_onc = Decrypt(passphrase, *toplevel_onc);
if (toplevel_onc.get() == NULL) {
LOG(ERROR) << "Couldn't decrypt the ONC from "
- << onc::GetSourceAsString(onc_source);
+ << GetSourceAsString(onc_source);
return false;
}
}
- bool from_policy = (onc_source == onc::ONC_SOURCE_USER_POLICY ||
- onc_source == onc::ONC_SOURCE_DEVICE_POLICY);
+ bool from_policy = (onc_source == ONC_SOURCE_USER_POLICY ||
+ onc_source == ONC_SOURCE_DEVICE_POLICY);
// Validate the ONC dictionary. We are liberal and ignore unknown field
// names and ignore invalid field names in kRecommended arrays.
- onc::Validator validator(false, // Ignore unknown fields.
- false, // Ignore invalid recommended field names.
- true, // Fail on missing fields.
- from_policy);
+ Validator validator(false, // Ignore unknown fields.
+ false, // Ignore invalid recommended field names.
+ true, // Fail on missing fields.
+ from_policy);
validator.SetOncSource(onc_source);
- onc::Validator::Result validation_result;
+ Validator::Result validation_result;
toplevel_onc = validator.ValidateAndRepairObject(
- &onc::kToplevelConfigurationSignature,
+ &kToplevelConfigurationSignature,
*toplevel_onc,
&validation_result);
if (from_policy) {
UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation",
- validation_result == onc::Validator::VALID);
+ validation_result == Validator::VALID);
}
bool success = true;
- if (validation_result == onc::Validator::VALID_WITH_WARNINGS) {
- LOG(WARNING) << "ONC from " << onc::GetSourceAsString(onc_source)
+ if (validation_result == Validator::VALID_WITH_WARNINGS) {
+ LOG(WARNING) << "ONC from " << GetSourceAsString(onc_source)
<< " produced warnings.";
success = false;
- } else if (validation_result == onc::Validator::INVALID ||
- toplevel_onc == NULL) {
- LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source)
+ } else if (validation_result == Validator::INVALID || toplevel_onc == NULL) {
+ LOG(ERROR) << "ONC from " << GetSourceAsString(onc_source)
<< " is invalid and couldn't be repaired.";
return false;
}
base::ListValue* validated_certs = NULL;
- if (toplevel_onc->GetListWithoutPathExpansion(
- onc::toplevel_config::kCertificates, &validated_certs)) {
+ if (toplevel_onc->GetListWithoutPathExpansion(toplevel_config::kCertificates,
+ &validated_certs)) {
certificates->Swap(validated_certs);
}
base::ListValue* validated_networks = NULL;
if (toplevel_onc->GetListWithoutPathExpansion(
- onc::toplevel_config::kNetworkConfigurations, &validated_networks)) {
+ toplevel_config::kNetworkConfigurations, &validated_networks)) {
network_configs->Swap(validated_networks);
}
return success;
}
+scoped_refptr<net::X509Certificate> DecodePEMCertificate(
+ const std::string& pem_encoded,
+ const std::string& nickname) {
+ // The PEM block header used for DER certificates
+ static const char kCertificateHeader[] = "CERTIFICATE";
+ // This is an older PEM marker for DER certificates.
+ static const char kX509CertificateHeader[] = "X509 CERTIFICATE";
+
+ std::vector<std::string> pem_headers;
+ pem_headers.push_back(kCertificateHeader);
+ pem_headers.push_back(kX509CertificateHeader);
+
+ net::PEMTokenizer pem_tokenizer(pem_encoded, pem_headers);
+ std::string decoded;
+ if (pem_tokenizer.GetNext()) {
+ decoded = pem_tokenizer.data();
+ } else {
+ // If we failed to read the data as a PEM file, then try plain base64 decode
+ // in case the PEM marker strings are missing. For this to work, there has
+ // to be no white space, and it has to only contain the base64-encoded data.
+ if (!base::Base64Decode(pem_encoded, &decoded)) {
+ LOG(ERROR) << "Unable to base64 decode X509 data: " << pem_encoded;
+ return scoped_refptr<net::X509Certificate>();
+ }
+ }
+
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromBytesWithNickname(decoded.data(),
+ decoded.size(),
+ nickname.c_str());
+ LOG_IF(ERROR, !cert) << "Couldn't create certificate from X509 data: "
+ << decoded;
+ return cert;
+}
+
} // namespace onc
} // namespace chromeos
diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h
index 6a6d273..d604cfc 100644
--- a/chromeos/network/onc/onc_utils.h
+++ b/chromeos/network/onc/onc_utils.h
@@ -8,9 +8,11 @@
#include <string>
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/network/onc/onc_constants.h"
+#include "net/cert/x509_certificate.h"
namespace base {
class DictionaryValue;
@@ -49,8 +51,8 @@ class CHROMEOS_EXPORT StringSubstitution {
virtual ~StringSubstitution() {}
// Returns the replacement string for |placeholder| in
- // |substitute|. Currently, onc::substitutes::kLoginIDField and
- // onc::substitutes::kEmailField are supported.
+ // |substitute|. Currently, substitutes::kLoginIDField and
+ // substitutes::kEmailField are supported.
virtual bool GetSubstitute(std::string placeholder,
std::string* substitute) const = 0;
private:
@@ -59,8 +61,8 @@ class CHROMEOS_EXPORT StringSubstitution {
// Replaces all expandable fields that are mentioned in the ONC
// specification. The object of |onc_object| is modified in place. Currently
-// onc::substitutes::kLoginIDField and onc::substitutes::kEmailField are
-// expanded. The replacement strings are obtained from |substitution|.
+// substitutes::kLoginIDField and substitutes::kEmailField are expanded. The
+// replacement strings are obtained from |substitution|.
CHROMEOS_EXPORT void ExpandStringsInOncObject(
const OncValueSignature& signature,
const StringSubstitution& substitution,
@@ -81,11 +83,17 @@ CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> MaskCredentialsInOncObject(
// output lists and should be further processed by the caller.
CHROMEOS_EXPORT bool ParseAndValidateOncForImport(
const std::string& onc_blob,
- chromeos::onc::ONCSource onc_source,
+ ONCSource onc_source,
const std::string& passphrase,
base::ListValue* network_configs,
base::ListValue* certificates);
+// Parse the given PEM encoded certificate |pem_encoded| and create a
+// X509Certificate from it.
+CHROMEOS_EXPORT scoped_refptr<net::X509Certificate> DecodePEMCertificate(
+ const std::string& pem_encoded,
+ const std::string& nickname);
+
} // namespace onc
} // namespace chromeos