summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-16 13:08:13 +0000
committerpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-16 13:08:13 +0000
commit7f123d2a3dc472dd796c13e2d7d599446fe9831d (patch)
tree6f3ead0503ad43e7d88db6d130ae4b65f89bf5a4
parentff39e9b81c8619d19a318a8d97d0bac552d455b4 (diff)
downloadchromium_src-7f123d2a3dc472dd796c13e2d7d599446fe9831d.zip
chromium_src-7f123d2a3dc472dd796c13e2d7d599446fe9831d.tar.gz
chromium_src-7f123d2a3dc472dd796c13e2d7d599446fe9831d.tar.bz2
ONC: Allow multiple CA certificates.
So far only a single CA certificate was supported for EAP/IPsec/OpenVPN. Instead, we now support multiple CA certs. These are provided as a list of GUID references to CA certificates in the toplevel "Certificates" section. BUG=276291 R=armansito@chromium.org, davidroche@chromium.org Review URL: https://codereview.chromium.org/68343010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240874 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chromeos/network/onc/onc_signature.cc9
-rw-r--r--chromeos/network/onc/onc_utils.cc51
-rw-r--r--chromeos/network/onc/onc_validator.cc69
-rw-r--r--chromeos/network/onc/onc_validator_unittest.cc12
-rw-r--r--chromeos/test/data/network/augmented_merge.json4
-rw-r--r--chromeos/test/data/network/invalid_settings_with_repairs.json27
-rw-r--r--chromeos/test/data/network/managed_toplevel_l2tpipsec.onc8
-rw-r--r--chromeos/test/data/network/managed_vpn.onc3
-rw-r--r--chromeos/test/data/network/managed_vpn_without_recommended.onc3
-rw-r--r--chromeos/test/data/network/network_configs_with_resolved_certs.json93
-rw-r--r--components/onc/docs/onc_spec.html72
-rw-r--r--components/onc/onc_constants.cc7
-rw-r--r--components/onc/onc_constants.h7
13 files changed, 317 insertions, 48 deletions
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc
index cdedf67..b0e9656 100644
--- a/chromeos/network/onc/onc_signature.cc
+++ b/chromeos/network/onc/onc_signature.cc
@@ -47,6 +47,7 @@ const OncFieldSignature certificate_pattern_fields[] = {
{ ::onc::certificate::kEnrollmentURI, &kStringListSignature},
{ ::onc::certificate::kIssuer, &kIssuerSubjectPatternSignature},
{ ::onc::certificate::kIssuerCARef, &kStringListSignature},
+ // Used internally. Not officially supported.
{ ::onc::certificate::kIssuerCAPEMs, &kStringListSignature},
{ ::onc::certificate::kSubject, &kIssuerSubjectPatternSignature},
{NULL}};
@@ -62,8 +63,10 @@ const OncFieldSignature eap_fields[] = {
{ ::onc::eap::kOuter, &kStringSignature},
{ ::onc::eap::kPassword, &kStringSignature},
{ ::onc::eap::kSaveCredentials, &kBoolSignature},
+ // Used internally. Not officially supported.
{ ::onc::eap::kServerCAPEMs, &kStringListSignature},
{ ::onc::eap::kServerCARef, &kStringSignature},
+ { ::onc::eap::kServerCARefs, &kStringListSignature},
{ ::onc::eap::kUseSystemCAs, &kBoolSignature},
{NULL}};
@@ -77,8 +80,10 @@ const OncFieldSignature ipsec_fields[] = {
{ ::onc::ipsec::kIKEVersion, &kIntegerSignature},
{ ::onc::ipsec::kPSK, &kStringSignature},
{ ::onc::vpn::kSaveCredentials, &kBoolSignature},
- { ::onc::ipsec::kServerCAPEMs, &kStringSignature},
+ // Used internally. Not officially supported.
+ { ::onc::ipsec::kServerCAPEMs, &kStringListSignature},
{ ::onc::ipsec::kServerCARef, &kStringSignature},
+ { ::onc::ipsec::kServerCARefs, &kStringListSignature},
// Not yet supported.
// { ipsec::kEAP, &kEAPSignature },
// { ipsec::kXAUTH, &kXAUTHSignature },
@@ -113,8 +118,10 @@ const OncFieldSignature openvpn_fields[] = {
{ ::onc::openvpn::kRemoteCertTLS, &kStringSignature},
{ ::onc::openvpn::kRenegSec, &kIntegerSignature},
{ ::onc::vpn::kSaveCredentials, &kBoolSignature},
+ // Used internally. Not officially supported.
{ ::onc::openvpn::kServerCAPEMs, &kStringListSignature},
{ ::onc::openvpn::kServerCARef, &kStringSignature},
+ { ::onc::openvpn::kServerCARefs, &kStringListSignature},
// Not supported, yet.
{ ::onc::openvpn::kServerCertPEM, &kStringSignature},
{ ::onc::openvpn::kServerCertRef, &kStringSignature},
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 586907d..aa612d9 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -431,7 +431,6 @@ bool ParseAndValidateOncForImport(const std::string& onc_blob,
success = false;
}
- ResolveServerCertRefsInNetworks(server_and_ca_certs, validated_networks);
network_configs->Swap(validated_networks);
}
@@ -537,6 +536,29 @@ bool ResolveSingleCertRefToList(const CertPEMsByGUIDMap& certs_by_guid,
return true;
}
+// Resolves the reference list at |key_guid_refs| if present and otherwise the
+// single reference at |key_guid_ref|. Returns whether the respective resolving
+// was successful.
+bool ResolveCertRefsOrRefToList(const CertPEMsByGUIDMap& certs_by_guid,
+ const std::string& key_guid_refs,
+ const std::string& key_guid_ref,
+ const std::string& key_pem_list,
+ base::DictionaryValue* onc_object) {
+ if (onc_object->HasKey(key_guid_refs)) {
+ if (onc_object->HasKey(key_guid_ref)) {
+ LOG(ERROR) << "Found both " << key_guid_refs << " and " << key_guid_ref
+ << ". Ignoring and removing the latter.";
+ onc_object->RemoveWithoutPathExpansion(key_guid_ref, NULL);
+ }
+ return ResolveCertRefList(
+ certs_by_guid, key_guid_refs, key_pem_list, onc_object);
+ }
+
+ // Only resolve |key_guid_ref| if |key_guid_refs| isn't present.
+ return ResolveSingleCertRefToList(
+ certs_by_guid, key_guid_ref, key_pem_list, onc_object);
+}
+
bool ResolveServerCertRefsInObject(const CertPEMsByGUIDMap& certs_by_guid,
const OncValueSignature& signature,
base::DictionaryValue* onc_object) {
@@ -546,21 +568,32 @@ bool ResolveServerCertRefsInObject(const CertPEMsByGUIDMap& certs_by_guid,
return false;
}
} else if (&signature == &kEAPSignature) {
- if (!ResolveSingleCertRefToList(certs_by_guid, eap::kServerCARef,
- eap::kServerCAPEMs, onc_object)) {
+ if (!ResolveCertRefsOrRefToList(certs_by_guid,
+ eap::kServerCARefs,
+ eap::kServerCARef,
+ eap::kServerCAPEMs,
+ onc_object)) {
return false;
}
} else if (&signature == &kIPsecSignature) {
- if (!ResolveSingleCertRefToList(certs_by_guid, ipsec::kServerCARef,
- ipsec::kServerCAPEMs, onc_object)) {
+ if (!ResolveCertRefsOrRefToList(certs_by_guid,
+ ipsec::kServerCARefs,
+ ipsec::kServerCARef,
+ ipsec::kServerCAPEMs,
+ onc_object)) {
return false;
}
} else if (&signature == &kIPsecSignature ||
&signature == &kOpenVPNSignature) {
- if (!ResolveSingleCertRef(certs_by_guid, openvpn::kServerCertRef,
- openvpn::kServerCertPEM, onc_object) ||
- !ResolveSingleCertRefToList(certs_by_guid, openvpn::kServerCARef,
- openvpn::kServerCAPEMs, onc_object)) {
+ if (!ResolveSingleCertRef(certs_by_guid,
+ openvpn::kServerCertRef,
+ openvpn::kServerCertPEM,
+ onc_object) ||
+ !ResolveCertRefsOrRefToList(certs_by_guid,
+ openvpn::kServerCARefs,
+ openvpn::kServerCARef,
+ openvpn::kServerCAPEMs,
+ onc_object)) {
return false;
}
}
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc
index 7fdaba8..6755390 100644
--- a/chromeos/network/onc/onc_validator.cc
+++ b/chromeos/network/onc/onc_validator.cc
@@ -348,9 +348,20 @@ bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue& object,
bool Validator::FieldExistsAndIsEmpty(const base::DictionaryValue& object,
const std::string& field_name) {
- std::string value;
- if (!object.GetStringWithoutPathExpansion(field_name, &value) ||
- !value.empty()) {
+ const base::Value* value = NULL;
+ if (!object.GetWithoutPathExpansion(field_name, &value))
+ return false;
+
+ std::string str;
+ const base::ListValue* list = NULL;
+ if (value->GetAsString(&str)) {
+ if (!str.empty())
+ return false;
+ } else if (value->GetAsList(&list)) {
+ if (!list->empty())
+ return false;
+ } else {
+ NOTREACHED();
return false;
}
@@ -583,7 +594,15 @@ bool Validator::ValidateIPsec(base::DictionaryValue* result) {
if (FieldExistsAndHasNoValidValue(
*result, kAuthenticationType, kValidAuthentications) ||
FieldExistsAndHasNoValidValue(
- *result, ::onc::vpn::kClientCertType, kValidCertTypes)) {
+ *result, ::onc::vpn::kClientCertType, kValidCertTypes) ||
+ FieldExistsAndIsEmpty(*result, kServerCARefs)) {
+ return false;
+ }
+
+ if (result->HasKey(kServerCARefs) && result->HasKey(kServerCARef)) {
+ error_or_warning_found_ = true;
+ LOG(ERROR) << MessageHeader() << "At most one of " << kServerCARefs
+ << " and " << kServerCARef << " can be set.";
return false;
}
@@ -591,13 +610,25 @@ bool Validator::ValidateIPsec(base::DictionaryValue* result) {
RequireField(*result, kIKEVersion);
std::string auth;
result->GetStringWithoutPathExpansion(kAuthenticationType, &auth);
+ bool has_server_ca_cert =
+ result->HasKey(kServerCARefs) || result->HasKey(kServerCARef);
if (auth == kCert) {
- all_required_exist &= RequireField(*result, ::onc::vpn::kClientCertType) &&
- RequireField(*result, kServerCARef);
- } else if (result->HasKey(kServerCARef)) {
+ all_required_exist &= RequireField(*result, ::onc::vpn::kClientCertType);
+ if (!has_server_ca_cert) {
+ all_required_exist = false;
+ error_or_warning_found_ = true;
+ std::string message = MessageHeader() + "The required field '" +
+ kServerCARefs + "' is missing.";
+ if (error_on_missing_field_)
+ LOG(ERROR) << message;
+ else
+ LOG(WARNING) << message;
+ }
+ } else if (has_server_ca_cert) {
error_or_warning_found_ = true;
- LOG(ERROR) << MessageHeader() << kServerCARef << " can only be set if "
- << kAuthenticationType << " is set to " << kCert << ".";
+ LOG(ERROR) << MessageHeader() << kServerCARefs << " (or " << kServerCARef
+ << ") can only be set if " << kAuthenticationType
+ << " is set to " << kCert << ".";
return false;
}
@@ -632,7 +663,15 @@ bool Validator::ValidateOpenVPN(base::DictionaryValue* result) {
FieldExistsAndHasNoValidValue(
*result, ::onc::vpn::kClientCertType, kValidCertTypes) ||
FieldExistsAndHasNoValidValue(
- *result, kRemoteCertTLS, kValidCertTlsValues)) {
+ *result, kRemoteCertTLS, kValidCertTlsValues) ||
+ FieldExistsAndIsEmpty(*result, kServerCARefs)) {
+ return false;
+ }
+
+ if (result->HasKey(kServerCARefs) && result->HasKey(kServerCARef)) {
+ error_or_warning_found_ = true;
+ LOG(ERROR) << MessageHeader() << "At most one of " << kServerCARefs
+ << " and " << kServerCARef << " can be set.";
return false;
}
@@ -727,7 +766,15 @@ bool Validator::ValidateEAP(base::DictionaryValue* result) {
if (FieldExistsAndHasNoValidValue(*result, kInner, kValidInnerValues) ||
FieldExistsAndHasNoValidValue(*result, kOuter, kValidOuterValues) ||
FieldExistsAndHasNoValidValue(
- *result, kClientCertType, kValidCertTypes)) {
+ *result, kClientCertType, kValidCertTypes) ||
+ FieldExistsAndIsEmpty(*result, kServerCARefs)) {
+ return false;
+ }
+
+ if (result->HasKey(kServerCARefs) && result->HasKey(kServerCARef)) {
+ error_or_warning_found_ = true;
+ LOG(ERROR) << MessageHeader() << "At most one of " << kServerCARefs
+ << " and " << kServerCARef << " can be set.";
return false;
}
diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc
index d100aea..7722676 100644
--- a/chromeos/network/onc/onc_validator_unittest.cc
+++ b/chromeos/network/onc/onc_validator_unittest.cc
@@ -383,6 +383,18 @@ INSTANTIATE_TEST_CASE_P(
std::make_pair(OncParams("ipsec-with-psk-and-cacert",
&kIPsecSignature, false),
RepairParams("", "")),
+ std::make_pair(OncParams("ipsec-with-empty-cacertrefs",
+ &kIPsecSignature, false),
+ RepairParams("", "")),
+ std::make_pair(OncParams("ipsec-with-servercaref-and-servercarefs",
+ &kIPsecSignature, false),
+ RepairParams("", "")),
+ std::make_pair(OncParams("openvpn-with-servercaref-and-servercarefs",
+ &kOpenVPNSignature, false),
+ RepairParams("", "")),
+ std::make_pair(OncParams("eap-with-servercaref-and-servercarefs",
+ &kEAPSignature, false),
+ RepairParams("", "")),
std::make_pair(OncParams("managed-network-value-out-of-range",
&kNetworkConfigurationSignature, true),
RepairParams("", "")),
diff --git a/chromeos/test/data/network/augmented_merge.json b/chromeos/test/data/network/augmented_merge.json
index fbd90ba..d7987ae 100644
--- a/chromeos/test/data/network/augmented_merge.json
+++ b/chromeos/test/data/network/augmented_merge.json
@@ -101,6 +101,10 @@
"Effective": "DevicePolicy",
"UserEditable": true,
"UserPolicy": "policy user"
+ },
+ "ServerCARefs": {
+ "UserPolicy": ["ref1", "ref2"],
+ "Effective": "UserPolicy"
}
},
"Type": {
diff --git a/chromeos/test/data/network/invalid_settings_with_repairs.json b/chromeos/test/data/network/invalid_settings_with_repairs.json
index 0815629..fbe6ada 100644
--- a/chromeos/test/data/network/invalid_settings_with_repairs.json
+++ b/chromeos/test/data/network/invalid_settings_with_repairs.json
@@ -199,6 +199,33 @@
"ClientCertType": "Ref",
"ClientCertRef": "a cert ref"
},
+ "ipsec-with-empty-cacertrefs": {
+ "AuthenticationType": "Cert",
+ "IKEVersion": 1,
+ "ClientCertType": "Ref",
+ "ClientCertRef": "a cert ref",
+ "ServerCARefs": []
+ },
+ "ipsec-with-servercaref-and-servercarefs": {
+ "AuthenticationType": "Cert",
+ "ClientCertType": "Ref",
+ "ClientCertRef": "a cert ref",
+ "IKEVersion": 1,
+ "ServerCARef": "a cert ref",
+ "ServerCARefs": ["ref1", "ref2"]
+ },
+ "openvpn-with-servercaref-and-servercarefs": {
+ "ClientCertType": "None",
+ "ServerCARef": "a cert ref",
+ "ServerCARefs": ["ref1", "ref2"]
+ },
+ "eap-with-servercaref-and-servercarefs": {
+ "ClientCertType": "Ref",
+ "ClientCertRef": "a cert ref",
+ "Outer": "LEAP",
+ "ServerCARef": "a cert ref",
+ "ServerCARefs": ["ref1", "ref2"]
+ },
"openvpn-missing-verify-x509-name": {
"GUID": "guid",
"Type": "VPN",
diff --git a/chromeos/test/data/network/managed_toplevel_l2tpipsec.onc b/chromeos/test/data/network/managed_toplevel_l2tpipsec.onc
index f20cd63..e08d4e9 100644
--- a/chromeos/test/data/network/managed_toplevel_l2tpipsec.onc
+++ b/chromeos/test/data/network/managed_toplevel_l2tpipsec.onc
@@ -8,10 +8,12 @@
"VPN": {
"Host": "l2tp.acme.org",
"IPsec": {
- "AuthenticationType": "PSK",
+ "AuthenticationType": "Cert",
"IKEVersion": 1,
+ "ClientCertType": "Ref",
+ "ClientCertRef": "a cert ref",
"SaveCredentials": false,
- "PSK": "passphrase"
+ "ServerCARefs": ["ref1", "ref2"]
},
"L2TP": {
"Recommended": [
@@ -24,4 +26,4 @@
}
],
"Type": "UnencryptedConfiguration"
-} \ No newline at end of file
+}
diff --git a/chromeos/test/data/network/managed_vpn.onc b/chromeos/test/data/network/managed_vpn.onc
index 4c52e97..c12bfc9 100644
--- a/chromeos/test/data/network/managed_vpn.onc
+++ b/chromeos/test/data/network/managed_vpn.onc
@@ -18,7 +18,8 @@
"ClientCertPattern": {
"IssuerCARef": [ "openvpn-test-ca" ],
"Recommended": [ "EnrollmentURI", "IssuerCARef" ]
- }
+ },
+ "ServerCARefs": ["ref1", "ref2"]
},
"IPsec": {
"AuthenticationType": "PSK",
diff --git a/chromeos/test/data/network/managed_vpn_without_recommended.onc b/chromeos/test/data/network/managed_vpn_without_recommended.onc
index 037bf53..471ff23 100644
--- a/chromeos/test/data/network/managed_vpn_without_recommended.onc
+++ b/chromeos/test/data/network/managed_vpn_without_recommended.onc
@@ -15,7 +15,8 @@
"ClientCertType": "Pattern",
"ClientCertPattern": {
"IssuerCARef": [ "openvpn-test-ca" ],
- }
+ },
+ "ServerCARefs": ["ref1", "ref2"]
},
"IPsec": {
"AuthenticationType": "PSK",
diff --git a/chromeos/test/data/network/network_configs_with_resolved_certs.json b/chromeos/test/data/network/network_configs_with_resolved_certs.json
index 021099d..7e7a367 100644
--- a/chromeos/test/data/network/network_configs_with_resolved_certs.json
+++ b/chromeos/test/data/network/network_configs_with_resolved_certs.json
@@ -1,5 +1,88 @@
{
- "OpenVPN and IssuerCARef": {
+ "OpenVPN with CARefs": {
+ "WithCertRefs": [ {
+ "Type": "VPN",
+ "VPN": {
+ "Type": "OpenVPN",
+ "OpenVPN": {
+ "PushPeerInfo": true,
+ "ServerCARefs": [ "cert_google", "cert_webkit" ]
+ }
+ },
+ } ],
+ "WithResolvedRefs": [ {
+ "Type": "VPN",
+ "VPN": {
+ "Type": "OpenVPN",
+ "OpenVPN": {
+ "PushPeerInfo": true,
+ "ServerCAPEMs": [ "pem_google", "pem_webkit" ]
+ }
+ },
+ } ]
+ },
+ "OpenVPN with CARefs and CARef": {
+ "WithCertRefs": [ {
+ "Type": "VPN",
+ "VPN": {
+ "Type": "OpenVPN",
+ "OpenVPN": {
+ "PushPeerInfo": true,
+ "ServerCARef": "cert_google",
+ "ServerCARefs": [ "cert_google", "cert_webkit" ]
+ }
+ },
+ } ],
+ "WithResolvedRefs": [ {
+ "Type": "VPN",
+ "VPN": {
+ "Type": "OpenVPN",
+ "OpenVPN": {
+ "PushPeerInfo": true,
+ "ServerCAPEMs": [ "pem_google", "pem_webkit" ]
+ }
+ },
+ } ]
+ },
+ "EAP with CARefs": {
+ "WithCertRefs":
+ [ { "WiFi": {
+ "EAP": {
+ "ServerCARefs": [ "cert_google", "cert_webkit" ]
+ }
+ }
+ }
+ ],
+ "WithResolvedRefs":
+ [ { "WiFi": {
+ "EAP": {
+ "ServerCAPEMs": [ "pem_google", "pem_webkit" ]
+ }
+ }
+ }
+ ]
+ },
+ "L2TP with CARefs": {
+ "WithCertRefs":
+ [ { "VPN": {
+ "IPsec": {
+ "SaveCredentials": true,
+ "ServerCARefs": [ "cert_google", "cert_webkit" ]
+ }
+ }
+ }
+ ],
+ "WithResolvedRefs":
+ [ { "VPN": {
+ "IPsec": {
+ "SaveCredentials": true,
+ "ServerCAPEMs": [ "pem_google", "pem_webkit" ]
+ }
+ }
+ }
+ ]
+ },
+ "OpenVPN with ServerCARef and IssuerCARef": {
"WithCertRefs": [
{
"GUID": "{a3860e83-f03d-4cb1-bafa-789oij}",
@@ -51,7 +134,7 @@
}
} ]
},
- "EAP and L2TP without ref": {
+ "EAP with and L2TP without ref": {
"WithCertRefs":
[ { "WiFi": {
"EAP": {
@@ -68,7 +151,7 @@
},
{ "VPN": {
"IPsec": {
- "SaveCredentials": true,
+ "SaveCredentials": true
}
}
}
@@ -91,7 +174,7 @@
},
{ "VPN": {
"IPsec": {
- "SaveCredentials": true,
+ "SaveCredentials": true
}
}
}
@@ -126,7 +209,7 @@
"SaveCredentials": true,
"ServerCAPEMs": [
"pem_google"
- ],
+ ]
}
}
}
diff --git a/components/onc/docs/onc_spec.html b/components/onc/docs/onc_spec.html
index 709ca0f..10b2f0f 100644
--- a/components/onc/docs/onc_spec.html
+++ b/components/onc/docs/onc_spec.html
@@ -658,7 +658,7 @@
<span class="rule">
<span class="rule_id"></span>
Allowed values are <span class="value">PSK</span> and
- <span class="value">Cert</span>
+ <span class="value">Cert</span>. If <span class="value">Cert</span> is used, <span class="field">ClientCertType</span> and <span class="field">ServerCARefs</span> (or the deprecated <span class="field">ServerCARef</span>) must be set.
</span>
</dd>
@@ -749,14 +749,25 @@
(PSK) each time they connect.
</dd>
+ <dt class="field">ServerCARefs</dt>
+ <dd>
+ <span class="field_meta">
+ (optional if <span class="field">AuthenticationType</span>
+ is <span class="value">Cert</span>, otherwise rejected)
+ <span class="type">array of string</span>
+ </span>
+ Non-empty list of references to CA certificates in <span class="field">Certificates</span> to be used for verifying the host's certificate chain. At least one of the CA certificates must match. If this field is set, <span class="field">ServerCARef</span> must be unset.
+ </dd>
+
<dt class="field">ServerCARef</dt>
<dd>
<span class="field_meta">
- (required if <span class="field">AuthenticationType</span>
+ (optional if <span class="field">AuthenticationType</span>
is <span class="value">Cert</span>, otherwise rejected)
<span class="type">string</span>
</span>
- Reference to server certificate authority stored in certificate section.
+ DEPRECATED, use <span class="field">ServerCARefs</span> instead.<br/>
+ Reference to a CA certificate in <span class="field">Certificates</span>. Certificate authority to use for verifying connection. If this field is set, <span class="field">ServerCARefs</span> must be unset.
</dd>
<dt class="field">XAUTH</dt>
@@ -771,6 +782,16 @@
</dd>
</dl>
+ <p class="rule">
+ <span class="rule_id"></span>
+ If <span class="field">AuthenticationType</span> is set to <span class="value">Cert</span>, <span class="field">ServerCARefs</span> or <span class="field">ServerCARef</span> must be set.
+ </p>
+
+ <p class="rule">
+ <span class="rule_id"></span>
+ At most one of <span class="field">ServerCARefs</span> and <span class="field">ServerCARef</span> can be set.
+ </p>
+
<p>
<span class="type">L2TP</span> type contains the following:
</p>
@@ -1108,14 +1129,23 @@
each time they connect.
</dd>
+ <dt class="field">ServerCARefs</dt>
+ <dd>
+ <span class="field_meta">
+ (optional)
+ <span class="type">array of string</span>
+ </span>
+ Non-empty list of references to CA certificates in <span class="field">Certificates</span> to be used for verifying the host's certificate chain. At least one of the CA certificates must match. See also OpenVPN's command line option "--ca". If this field is set, <span class="field">ServerCARef</span> must be unset.
+ </dd>
+
<dt class="field">ServerCARef</dt>
<dd>
<span class="field_meta">
(optional)
<span class="type">string</span>
</span>
- Reference to a certificate. Certificate authority to use for verifying
- connection.
+ DEPRECATED, use <span class="field">ServerCARefs</span> instead.<br/>
+ Reference to a CA certificate in <span class="field">Certificates</span>. Certificate authority to use for verifying connection. If this field is set, <span class="field">ServerCARefs</span> must be unset.
</dd>
<dt class="field">ServerCertRef</dt>
@@ -1215,6 +1245,11 @@
</dd>
</dl>
+ <p class="rule">
+ <span class="rule_id"></span>
+ At most one of <span class="field">ServerCARefs</span> and <span class="field">ServerCARef</span> can be set.
+ </p>
+
<p>
<span class="type">VerifyX509</span> type contains the following:
</p>
@@ -1618,16 +1653,23 @@
<span class="value">false</span> is not allowed.
</dd>
+ <dt class="field">ServerCARefs</dt>
+ <dd>
+ <span class="field_meta">
+ (optional)
+ <span class="type">array of string</span>
+ </span>
+ Non-empty list of references to CA certificates in <span class="field">Certificates</span> to be used for verifying the host's certificate chain. At least one of the CA certificates must match. If this field is set, <span class="field">ServerCARef</span> must be unset. If neither <span class="field">ServerCARefs</span> nor <span class="field">ServerCARef</span> is set, the client does not check that the server certificate is signed by a specific CA. A verification using the system's CA certificates may still apply. See <span class="field">UseSystemCAs</span> for this.
+ </dd>
+
<dt class="field">ServerCARef</dt>
<dd>
<span class="field_meta">
(optional)
<span class="type">string</span>
</span>
- Reference to server certificate authority stored in certificate
- section. If not specified, client does not check the server certificate is
- signed by a specific CA. It will still check the server CA
- if <span class="field">UseSystemCAs</span> is set.
+ DEPRECATED, use <span class="field">ServerCARefs</span> instead.<br/>
+ Reference to a CA certificate in <span class="field">Certificates</span>. If this field is set, <span class="field">ServerCARefs</span> must be unset. If neither <span class="field">ServerCARefs</span> nor <span class="field">ServerCARef</span> is set, the client does not check that the server certificate is signed by a specific CA. A verification using the system's CA certificates may still apply. See <span class="field">UseSystemCAs</span> for this.
</dd>
<dt class="field">UseSystemCAs</dt>
@@ -1637,15 +1679,19 @@
<span class="type">boolean</span>
</span>
Required server certificate to be signed by "system default certificate
- authorities". If both <span class="field">ServerCARef</span>
+ authorities". If both <span class="field">ServerCARefs</span> (or <span class="field">ServerCARef</span>)
and <span class="field">UseSystemCAs</span> are supplied, a server
certificate will be allowed if it either has a chain of trust to a system
- CA or to the given server CA. If <span class="field">UseSystemCAs</span>
- is <span class="value">false</span>, and
- no <span class="field">ServerCARef</span> is set, then the certificate
+ CA or to one of the given CA certificates. If <span class="field">UseSystemCAs</span>
+ is <span class="value">false</span>, and no <span class="field">ServerCARef</span> is set, the certificate
must be a self signed certificate, and no CA signature is required.
</dd>
</dl>
+
+ <p class="rule">
+ <span class="rule_id"></span>
+ At most one of <span class="field">ServerCARefs</span> and <span class="field">ServerCARef</span> can be set.
+ </p>
</section>
<section>
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc
index efd2b9d..68b8755 100644
--- a/components/onc/onc_constants.cc
+++ b/components/onc/onc_constants.cc
@@ -205,6 +205,7 @@ const char kPassword[] = "Password";
const char kSaveCredentials[] = "SaveCredentials";
const char kServerCAPEMs[] = "ServerCAPEMs";
const char kServerCARef[] = "ServerCARef";
+const char kServerCARefs[] = "ServerCARefs";
const char kUseSystemCAs[] = "UseSystemCAs";
} // namespace eap
@@ -231,8 +232,9 @@ const char kEAP[] = "EAP";
const char kGroup[] = "Group";
const char kIKEVersion[] = "IKEVersion";
const char kPSK[] = "PSK";
-const char kServerCARef[] = "ServerCARef";
const char kServerCAPEMs[] = "ServerCAPEMs";
+const char kServerCARef[] = "ServerCARef";
+const char kServerCARefs[] = "ServerCARefs";
const char kXAUTH[] = "XAUTH";
} // namespace ipsec
@@ -255,8 +257,9 @@ const char kRemoteCertEKU[] = "RemoteCertEKU";
const char kRemoteCertKU[] = "RemoteCertKU";
const char kRemoteCertTLS[] = "RemoteCertTLS";
const char kRenegSec[] = "RenegSec";
-const char kServerCARef[] = "ServerCARef";
const char kServerCAPEMs[] = "ServerCAPEMs";
+const char kServerCARef[] = "ServerCARef";
+const char kServerCARefs[] = "ServerCARefs";
const char kServerCertPEM[] = "ServerCertPEM";
const char kServerCertRef[] = "ServerCertRef";
const char kServerPollTimeout[] = "ServerPollTimeout";
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h
index 4ef51e7..400b340 100644
--- a/components/onc/onc_constants.h
+++ b/components/onc/onc_constants.h
@@ -226,8 +226,9 @@ ONC_EXPORT extern const char kPAP[];
ONC_EXPORT extern const char kPEAP[];
ONC_EXPORT extern const char kPassword[];
ONC_EXPORT extern const char kSaveCredentials[];
-ONC_EXPORT extern const char kServerCARef[];
ONC_EXPORT extern const char kServerCAPEMs[];
+ONC_EXPORT extern const char kServerCARef[];
+ONC_EXPORT extern const char kServerCARefs[];
ONC_EXPORT extern const char kUseSystemCAs[];
} // namespace eap
@@ -254,8 +255,9 @@ ONC_EXPORT extern const char kEAP[];
ONC_EXPORT extern const char kGroup[];
ONC_EXPORT extern const char kIKEVersion[];
ONC_EXPORT extern const char kPSK[];
-ONC_EXPORT extern const char kServerCARef[];
ONC_EXPORT extern const char kServerCAPEMs[];
+ONC_EXPORT extern const char kServerCARef[];
+ONC_EXPORT extern const char kServerCARefs[];
ONC_EXPORT extern const char kXAUTH[];
} // namespace ipsec
@@ -280,6 +282,7 @@ ONC_EXPORT extern const char kRemoteCertTLS[];
ONC_EXPORT extern const char kRenegSec[];
ONC_EXPORT extern const char kServerCAPEMs[];
ONC_EXPORT extern const char kServerCARef[];
+ONC_EXPORT extern const char kServerCARefs[];
ONC_EXPORT extern const char kServerCertPEM[];
ONC_EXPORT extern const char kServerCertRef[];
ONC_EXPORT extern const char kServerPollTimeout[];