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