ChromeOS: Add more host verification options for OpenVpn.
Support the --verify-hash and --verify-x509-name options of OpenVPN via ONC. Note that the ONC validator restricts the possible types passable to --verify-x509-name to "name", "name-prefix" and "subject". See also https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage . BUG=276291 R=armansito@chromium.org, bartfab@chromium.org, pstew@chromium.org Review URL: https://codereview.chromium.org/61903002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234495 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
chromeos
network
onc
test
components/onc
@ -126,6 +126,13 @@ const OncFieldSignature openvpn_fields[] = {
|
||||
{ ::onc::vpn::kUsername, &kStringSignature},
|
||||
// Not supported, yet.
|
||||
{ ::onc::openvpn::kVerb, &kStringSignature},
|
||||
{ ::onc::openvpn::kVerifyHash, &kStringSignature},
|
||||
{ ::onc::openvpn::kVerifyX509, &kVerifyX509Signature},
|
||||
{NULL}};
|
||||
|
||||
const OncFieldSignature verify_x509_fields[] = {
|
||||
{ ::onc::verify_x509::kName, &kStringSignature},
|
||||
{ ::onc::verify_x509::kType, &kStringSignature},
|
||||
{NULL}};
|
||||
|
||||
const OncFieldSignature vpn_fields[] = {
|
||||
@ -316,6 +323,9 @@ const OncValueSignature kL2TPSignature = {
|
||||
const OncValueSignature kOpenVPNSignature = {
|
||||
Value::TYPE_DICTIONARY, openvpn_fields, NULL
|
||||
};
|
||||
const OncValueSignature kVerifyX509Signature = {
|
||||
Value::TYPE_DICTIONARY, verify_x509_fields, NULL
|
||||
};
|
||||
const OncValueSignature kVPNSignature = {
|
||||
Value::TYPE_DICTIONARY, vpn_fields, NULL
|
||||
};
|
||||
|
@ -42,6 +42,7 @@ CHROMEOS_EXPORT extern const OncValueSignature kCertificatePatternSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kIPsecSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kL2TPSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kOpenVPNSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kVerifyX509Signature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kVPNSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kEthernetSignature;
|
||||
CHROMEOS_EXPORT extern const OncValueSignature kIPConfigSignature;
|
||||
|
@ -83,7 +83,14 @@ const FieldTranslationEntry openvpn_fields[] = {
|
||||
{ ::onc::openvpn::kStaticChallenge, shill::kOpenVPNStaticChallengeProperty},
|
||||
{ ::onc::openvpn::kTLSAuthContents, shill::kOpenVPNTLSAuthContentsProperty},
|
||||
{ ::onc::openvpn::kTLSRemote, shill::kOpenVPNTLSRemoteProperty},
|
||||
{ ::onc::vpn::kUsername, shill::kOpenVPNUserProperty}, {NULL}};
|
||||
{ ::onc::vpn::kUsername, shill::kOpenVPNUserProperty},
|
||||
{ ::onc::openvpn::kVerifyHash, shill::kOpenVPNVerifyHashProperty},
|
||||
{NULL}};
|
||||
|
||||
const FieldTranslationEntry verify_x509_fields[] = {
|
||||
{ ::onc::verify_x509::kName, shill::kOpenVPNVerifyX509NameProperty},
|
||||
{ ::onc::verify_x509::kType, shill::kOpenVPNVerifyX509TypeProperty},
|
||||
{NULL}};
|
||||
|
||||
const FieldTranslationEntry vpn_fields[] = {
|
||||
{ ::onc::vpn::kAutoConnect, shill::kAutoConnectProperty},
|
||||
@ -173,6 +180,7 @@ const OncValueTranslationEntry onc_value_translation_table[] = {
|
||||
{ &kIPsecSignature, ipsec_fields },
|
||||
{ &kL2TPSignature, l2tp_fields },
|
||||
{ &kOpenVPNSignature, openvpn_fields },
|
||||
{ &kVerifyX509Signature, verify_x509_fields },
|
||||
{ &kVPNSignature, vpn_fields },
|
||||
{ &kWiFiSignature, wifi_fields },
|
||||
{ &kWiFiWithStateSignature, wifi_fields },
|
||||
|
@ -146,6 +146,9 @@ void ShillToONCTranslator::TranslateEthernet() {
|
||||
}
|
||||
|
||||
void ShillToONCTranslator::TranslateOpenVPN() {
|
||||
if (shill_dictionary_->HasKey(shill::kOpenVPNVerifyX509NameProperty))
|
||||
TranslateAndAddNestedObject(::onc::openvpn::kVerifyX509);
|
||||
|
||||
// Shill supports only one RemoteCertKU but ONC requires a list. If existing,
|
||||
// wraps the value into a list.
|
||||
std::string certKU;
|
||||
|
@ -126,6 +126,8 @@ scoped_ptr<base::DictionaryValue> Validator::MapObject(
|
||||
valid = ValidateIPsec(onc_object, repaired.get());
|
||||
else if (&signature == &kOpenVPNSignature)
|
||||
valid = ValidateOpenVPN(onc_object, repaired.get());
|
||||
else if (&signature == &kVerifyX509Signature)
|
||||
valid = ValidateVerifyX509(onc_object, repaired.get());
|
||||
else if (&signature == &kCertificatePatternSignature)
|
||||
valid = ValidateCertificatePattern(onc_object, repaired.get());
|
||||
else if (&signature == &kProxySettingsSignature)
|
||||
@ -666,6 +668,21 @@ bool Validator::ValidateOpenVPN(
|
||||
return !error_on_missing_field_ || allRequiredExist;
|
||||
}
|
||||
|
||||
bool Validator::ValidateVerifyX509(const base::DictionaryValue& onc_object,
|
||||
base::DictionaryValue* result) {
|
||||
using namespace ::onc::verify_x509;
|
||||
|
||||
static const char* kValidTypeValues[] =
|
||||
{types::kName, types::kNamePrefix, types::kSubject, NULL};
|
||||
|
||||
if (FieldExistsAndHasNoValidValue(*result, kType, kValidTypeValues))
|
||||
return false;
|
||||
|
||||
bool allRequiredExist = RequireField(*result, kName);
|
||||
|
||||
return !error_on_missing_field_ || allRequiredExist;
|
||||
}
|
||||
|
||||
bool Validator::ValidateCertificatePattern(
|
||||
const base::DictionaryValue& onc_object,
|
||||
base::DictionaryValue* result) {
|
||||
|
@ -181,6 +181,10 @@ class CHROMEOS_EXPORT Validator : public Mapper {
|
||||
const base::DictionaryValue& onc_object,
|
||||
base::DictionaryValue* result);
|
||||
|
||||
bool ValidateVerifyX509(
|
||||
const base::DictionaryValue& onc_object,
|
||||
base::DictionaryValue* result);
|
||||
|
||||
bool ValidateCertificatePattern(
|
||||
const base::DictionaryValue& onc_object,
|
||||
base::DictionaryValue* result);
|
||||
|
@ -165,6 +165,9 @@ INSTANTIATE_TEST_CASE_P(
|
||||
true),
|
||||
OncParams("translation_of_shill_wifi_with_state.onc",
|
||||
&kNetworkWithStateSignature,
|
||||
false),
|
||||
OncParams("valid_openvpn_with_cert_pems.onc",
|
||||
&kNetworkConfigurationSignature,
|
||||
false)));
|
||||
|
||||
namespace {
|
||||
@ -292,6 +295,9 @@ INSTANTIATE_TEST_CASE_P(
|
||||
false),
|
||||
RepairParams("",
|
||||
"network-nested-state-field-repaired")),
|
||||
std::make_pair(OncParams("openvpn-missing-verify-x509-name",
|
||||
&kNetworkConfigurationSignature, false),
|
||||
RepairParams("", "openvpn-missing-verify-x509-name")),
|
||||
std::make_pair(OncParams("toplevel-with-repairable-networks",
|
||||
&kToplevelConfigurationSignature,
|
||||
false,
|
||||
@ -366,7 +372,11 @@ INSTANTIATE_TEST_CASE_P(
|
||||
std::make_pair(OncParams("network-with-client-cert-pattern",
|
||||
&kNetworkConfigurationSignature, true,
|
||||
::onc::ONC_SOURCE_DEVICE_POLICY),
|
||||
RepairParams("", ""))));
|
||||
RepairParams("", "")),
|
||||
std::make_pair(OncParams("openvpn-invalid-verify-x509-type",
|
||||
&kNetworkConfigurationSignature, false),
|
||||
RepairParams("", ""))
|
||||
));
|
||||
|
||||
} // namespace onc
|
||||
} // namespace chromeos
|
||||
|
@ -187,6 +187,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"openvpn-missing-verify-x509-name": {
|
||||
"GUID": "guid",
|
||||
"Type": "VPN",
|
||||
"Name": "name",
|
||||
"VPN": {
|
||||
"Host": "host",
|
||||
"Type": "OpenVPN",
|
||||
"OpenVPN": {
|
||||
"ClientCertType": "None",
|
||||
"VerifyX509": {
|
||||
"Type": "name"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"openvpn-invalid-verify-x509-type": {
|
||||
"GUID": "guid",
|
||||
"Type": "VPN",
|
||||
"Name": "name",
|
||||
"VPN": {
|
||||
"Host": "host",
|
||||
"Type": "OpenVPN",
|
||||
"OpenVPN": {
|
||||
"ClientCertType": "None",
|
||||
"VerifyX509": {
|
||||
"Type": "unknown type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"toplevel-empty": {
|
||||
"Type": "UnencryptedConfiguration",
|
||||
"NetworkConfigurations": [ ]
|
||||
|
@ -1,26 +1,32 @@
|
||||
{
|
||||
"AutoConnect": true,
|
||||
"GUID": "{a3860e83-f03d-4cb1-bafa-b22c9e746950}",
|
||||
"Type": "vpn",
|
||||
"Name": "my vpn",
|
||||
"SaveCredentials": false,
|
||||
"Provider.Type": "openvpn",
|
||||
"Provider.Host": "vpn.my.domain.com",
|
||||
"OpenVPN.AuthRetry": "interact",
|
||||
"OpenVPN.User": "abc ${LOGIN_EMAIL} def",
|
||||
"OpenVPN.Password": "some password",
|
||||
"OpenVPN.StaticChallenge": "Please enter token OTP",
|
||||
"OpenVPN.CompLZO": "true",
|
||||
"OpenVPN.ServerPollTimeout": "10",
|
||||
"OpenVPN.RemoteCertKU": "e0",
|
||||
"OpenVPN.CACertPEM": [ "pem1", "pem2" ],
|
||||
"OpenVPN.RemoteCertTLS": "server",
|
||||
"OpenVPN.Port": "443",
|
||||
"OpenVPN.TLSRemote": "my.domain.com",
|
||||
"OpenVPN.KeyDirection": "1",
|
||||
"OpenVPN.RenegSec": "0",
|
||||
"OpenVPN.RemoteCertEKU": "TLS Web Server Authentication",
|
||||
"OpenVPN.Proto": "udp",
|
||||
"OpenVPN.PushPeerInfo": "true",
|
||||
"OpenVPN.TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n"
|
||||
"AutoConnect":true,
|
||||
"GUID":"{a3860e83-f03d-4cb1-bafa-b22c9e746950}",
|
||||
"Name":"my vpn",
|
||||
"OpenVPN.AuthRetry":"interact",
|
||||
"OpenVPN.CACertPEM":[
|
||||
"pem1",
|
||||
"pem2"
|
||||
],
|
||||
"OpenVPN.CompLZO":"true",
|
||||
"OpenVPN.KeyDirection":"1",
|
||||
"OpenVPN.Password":"some password",
|
||||
"OpenVPN.Port":"443",
|
||||
"OpenVPN.Proto":"udp",
|
||||
"OpenVPN.PushPeerInfo":"true",
|
||||
"OpenVPN.RemoteCertEKU":"TLS Web Server Authentication",
|
||||
"OpenVPN.RemoteCertKU":"e0",
|
||||
"OpenVPN.RemoteCertTLS":"server",
|
||||
"OpenVPN.RenegSec":"0",
|
||||
"OpenVPN.ServerPollTimeout":"10",
|
||||
"OpenVPN.StaticChallenge":"Please enter token OTP",
|
||||
"OpenVPN.TLSAuthContents":"-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n",
|
||||
"OpenVPN.TLSRemote":"my.domain.com",
|
||||
"OpenVPN.User":"abc ${LOGIN_EMAIL} def",
|
||||
"OpenVPN.VerifyHash":"some hash",
|
||||
"OpenVPN.VerifyX509Name":"some x509 name",
|
||||
"OpenVPN.VerifyX509Type":"name-prefix",
|
||||
"Provider.Host":"vpn.my.domain.com",
|
||||
"Provider.Type":"openvpn",
|
||||
"SaveCredentials":false,
|
||||
"Type":"vpn"
|
||||
}
|
||||
|
@ -27,6 +27,11 @@
|
||||
"TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n",
|
||||
"TLSRemote": "my.domain.com",
|
||||
"Username": "abc ${LOGIN_EMAIL} def",
|
||||
"VerifyHash": "some hash",
|
||||
"VerifyX509": {
|
||||
"Name": "some x509 name",
|
||||
"Type": "name-prefix"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
"Type": "OpenVPN",
|
||||
"OpenVPN": {
|
||||
"AuthRetry": "interact",
|
||||
"ClientCertType": "None",
|
||||
"CompLZO": "true",
|
||||
"KeyDirection": "1",
|
||||
"Password": "some password",
|
||||
@ -27,6 +28,11 @@
|
||||
"TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n",
|
||||
"TLSRemote": "my.domain.com",
|
||||
"Username": "abc ${LOGIN_EMAIL} def",
|
||||
"VerifyHash": "some hash",
|
||||
"VerifyX509": {
|
||||
"Name": "some x509 name",
|
||||
"Type": "name-prefix"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1192,9 +1192,52 @@
|
||||
(optional)
|
||||
<span class="type">string</span>
|
||||
</span>
|
||||
Verbosity level, defaults to openvpn default if not specified.
|
||||
Verbosity level, defaults to OpenVpn's default if not specified.
|
||||
</dd>
|
||||
|
||||
<dt class="field">VerifyHash</dt>
|
||||
<dd>
|
||||
<span class="field_meta">
|
||||
(optional)
|
||||
<span class="type">string</span>
|
||||
</span>
|
||||
If set, this value is passed as the "--verify-hash" argument to OpenVPN,
|
||||
which specifies the SHA1 fingerprint for the level-1 certificate.
|
||||
</dd>
|
||||
|
||||
<dt class="field">VerifyX509</dt>
|
||||
<dd>
|
||||
<span class="field_meta">
|
||||
(optional)
|
||||
<span class="type">VerifyX509</span>
|
||||
</span>
|
||||
If set, the "--verify-x509-name" argument is passed to OpenVPN with the values of this object and only connections will be accepted if a host's X.509 name is equal to the given name.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<span class="type">VerifyX509</span> type contains the following:
|
||||
</p>
|
||||
<dl class="field_list">
|
||||
<dt class="field">Name</dt>
|
||||
<dd>
|
||||
<span class="field_meta">
|
||||
(required)
|
||||
<span class="type">string</span>
|
||||
</span>
|
||||
The name that the host's X.509 name is compared to. Which host name is compared depends on the value of <span class="field">Type</span>.
|
||||
</dd>
|
||||
|
||||
<dt class="field">Type</dt>
|
||||
<dd>
|
||||
<span class="field_meta">
|
||||
(optional)
|
||||
<span class="type">string</span>
|
||||
</span>
|
||||
Determines which of the host's X.509 names will be verified. Allowed values are <span class="value">name</span>, <span class="value">name-prefix</span> and <span class="value">subject</span>. See OpenVPN's documentation for "--verify-x509-name" for the meaning of each value. Defaults to OpenVPN's default if not specified.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
@ -265,8 +265,21 @@ const char kStaticChallenge[] = "StaticChallenge";
|
||||
const char kTLSAuthContents[] = "TLSAuthContents";
|
||||
const char kTLSRemote[] = "TLSRemote";
|
||||
const char kVerb[] = "Verb";
|
||||
const char kVerifyHash[] = "VerifyHash";
|
||||
const char kVerifyX509[] = "VerifyX509";
|
||||
} // namespace openvpn
|
||||
|
||||
namespace verify_x509 {
|
||||
const char kName[] = "Name";
|
||||
const char kType[] = "Type";
|
||||
|
||||
namespace types {
|
||||
const char kName[] = "name";
|
||||
const char kNamePrefix[] = "name-prefix";
|
||||
const char kSubject[] = "subject";
|
||||
} // namespace types
|
||||
} // namespace verify_x509
|
||||
|
||||
namespace proxy {
|
||||
const char kDirect[] = "Direct";
|
||||
const char kExcludeDomains[] = "ExcludeDomains";
|
||||
|
@ -288,8 +288,21 @@ ONC_EXPORT extern const char kStaticChallenge[];
|
||||
ONC_EXPORT extern const char kTLSAuthContents[];
|
||||
ONC_EXPORT extern const char kTLSRemote[];
|
||||
ONC_EXPORT extern const char kVerb[];
|
||||
ONC_EXPORT extern const char kVerifyHash[];
|
||||
ONC_EXPORT extern const char kVerifyX509[];
|
||||
} // namespace openvpn
|
||||
|
||||
namespace verify_x509 {
|
||||
ONC_EXPORT extern const char kName[];
|
||||
ONC_EXPORT extern const char kType[];
|
||||
|
||||
namespace types {
|
||||
ONC_EXPORT extern const char kName[];
|
||||
ONC_EXPORT extern const char kNamePrefix[];
|
||||
ONC_EXPORT extern const char kSubject[];
|
||||
} // namespace types
|
||||
} // namespace verify_x509
|
||||
|
||||
namespace substitutes {
|
||||
ONC_EXPORT extern const char kEmailField[];
|
||||
ONC_EXPORT extern const char kLoginIDField[];
|
||||
|
Reference in New Issue
Block a user