1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromeos/network/onc/onc_certificate_pattern.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10
11 #include "base/values.h"
12 #include "components/onc/onc_constants.h"
13 #include "net/cert/x509_certificate.h"
14 #include "net/cert/x509_util_nss.h"
15
16 namespace chromeos {
17
18 namespace {
19
GetAsListOfStrings(const base::Value & value,std::vector<std::string> * result)20 bool GetAsListOfStrings(const base::Value& value,
21 std::vector<std::string>* result) {
22 if (!value.is_list())
23 return false;
24
25 result->clear();
26 result->reserve(value.GetList().size());
27 for (const auto& entry : value.GetList()) {
28 if (!entry.is_string())
29 return false;
30 result->push_back(entry.GetString());
31 }
32
33 return true;
34 }
35
36 } // namespace
37
38 ////////////////////////////////////////////////////////////////////////////////
39 // OncCertificatePattern
40
41 OncCertificatePattern::OncCertificatePattern() = default;
42
43 OncCertificatePattern::OncCertificatePattern(
44 const OncCertificatePattern& other) = default;
45
46 OncCertificatePattern::OncCertificatePattern(OncCertificatePattern&& other) =
47 default;
48
49 OncCertificatePattern::~OncCertificatePattern() = default;
50
51 OncCertificatePattern& OncCertificatePattern::operator=(
52 const OncCertificatePattern& rhs) = default;
53 OncCertificatePattern& OncCertificatePattern::operator=(
54 OncCertificatePattern&& rhs) = default;
55
Empty() const56 bool OncCertificatePattern::Empty() const {
57 return pem_encoded_issuer_cas_.empty() && issuer_pattern_.Empty() &&
58 subject_pattern_.Empty();
59 }
60
Matches(const net::X509Certificate & certificate,const std::string & pem_encoded_issuer_ca) const61 bool OncCertificatePattern::Matches(
62 const net::X509Certificate& certificate,
63 const std::string& pem_encoded_issuer_ca) const {
64 if (!issuer_pattern_.Empty() || !subject_pattern_.Empty()) {
65 if (!issuer_pattern_.Empty() &&
66 !issuer_pattern_.Matches(certificate.issuer()))
67 return false;
68 if (!subject_pattern_.Empty() &&
69 !subject_pattern_.Matches(certificate.subject()))
70 return false;
71 }
72
73 if (!pem_encoded_issuer_cas_.empty() &&
74 !base::Contains(pem_encoded_issuer_cas_, pem_encoded_issuer_ca)) {
75 return false;
76 }
77 return true;
78 }
79
80 // static
81 base::Optional<OncCertificatePattern>
ReadFromONCDictionary(const base::Value & dict)82 OncCertificatePattern::ReadFromONCDictionary(const base::Value& dict) {
83 // All of these are optional.
84 const base::Value* pem_encoded_issuer_cas_value = dict.FindKeyOfType(
85 onc::client_cert::kIssuerCAPEMs, base::Value::Type::LIST);
86 std::vector<std::string> pem_encoded_issuer_cas;
87 if (pem_encoded_issuer_cas_value &&
88 !GetAsListOfStrings(*pem_encoded_issuer_cas_value,
89 &pem_encoded_issuer_cas)) {
90 return base::nullopt;
91 }
92
93 const base::Value* enrollment_uri_list_value = dict.FindKeyOfType(
94 onc::client_cert::kEnrollmentURI, base::Value::Type::LIST);
95 std::vector<std::string> enrollment_uri_list;
96 if (enrollment_uri_list_value &&
97 !GetAsListOfStrings(*enrollment_uri_list_value, &enrollment_uri_list)) {
98 return base::nullopt;
99 }
100
101 auto issuer_pattern =
102 certificate_matching::CertificatePrincipalPattern::ParseFromOptionalDict(
103 dict.FindKeyOfType(onc::client_cert::kIssuer,
104 base::Value::Type::DICTIONARY),
105 onc::client_cert::kCommonName, onc::client_cert::kLocality,
106 onc::client_cert::kOrganization,
107 onc::client_cert::kOrganizationalUnit);
108 auto subject_pattern =
109 certificate_matching::CertificatePrincipalPattern::ParseFromOptionalDict(
110 dict.FindKeyOfType(onc::client_cert::kSubject,
111 base::Value::Type::DICTIONARY),
112 onc::client_cert::kCommonName, onc::client_cert::kLocality,
113 onc::client_cert::kOrganization,
114 onc::client_cert::kOrganizationalUnit);
115
116 return OncCertificatePattern(pem_encoded_issuer_cas, issuer_pattern,
117 subject_pattern, enrollment_uri_list);
118 }
119
OncCertificatePattern(std::vector<std::string> pem_encoded_issuer_cas,certificate_matching::CertificatePrincipalPattern issuer_pattern,certificate_matching::CertificatePrincipalPattern subject_pattern,std::vector<std::string> enrollment_uri_list)120 OncCertificatePattern::OncCertificatePattern(
121 std::vector<std::string> pem_encoded_issuer_cas,
122 certificate_matching::CertificatePrincipalPattern issuer_pattern,
123 certificate_matching::CertificatePrincipalPattern subject_pattern,
124 std::vector<std::string> enrollment_uri_list)
125 : pem_encoded_issuer_cas_(std::move(pem_encoded_issuer_cas)),
126 issuer_pattern_(std::move(issuer_pattern)),
127 subject_pattern_(std::move(subject_pattern)),
128 enrollment_uri_list_(std::move(enrollment_uri_list)) {}
129
130 } // namespace chromeos
131