summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/net/onc_utils.cc224
-rw-r--r--chrome/browser/chromeos/net/onc_utils.h42
-rw-r--r--chrome/browser/chromeos/net/onc_utils_unittest.cc85
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.cc6
-rw-r--r--chrome/browser/chromeos/proxy_config_service_impl.h2
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/test/data/chromeos/net/proxy_config.json84
-rw-r--r--chrome/test/data/chromeos/net/uidata_for_l2tpipsec_clientcert.json19
-rw-r--r--chrome/test/data/chromeos/net/uidata_for_openvpn_clientcert.json19
-rw-r--r--chrome/test/data/chromeos/net/uidata_for_wifi_clientcert.json13
-rw-r--r--chrome/test/data/chromeos/net/uidata_for_wifi_clientref.json4
-rw-r--r--chrome/test/data/chromeos/net/uidata_for_wifi_psk.json3
-rw-r--r--chromeos/chromeos.gyp4
-rw-r--r--chromeos/network/onc/onc_certificate_importer.cc4
-rw-r--r--chromeos/network/onc/onc_certificate_importer.h4
-rw-r--r--chromeos/network/onc/onc_signature.cc36
-rw-r--r--chromeos/network/onc/onc_signature.h5
-rw-r--r--chromeos/network/onc/onc_translation_tables.cc32
-rw-r--r--chromeos/network/onc/onc_translation_tables.h4
-rw-r--r--chromeos/network/onc/onc_translator_onc_to_shill.cc64
-rw-r--r--chromeos/network/onc/onc_translator_shill_to_onc.cc7
-rw-r--r--chromeos/network/onc/onc_translator_unittest.cc11
-rw-r--r--chromeos/network/onc/onc_utils.cc57
-rw-r--r--chromeos/network/onc/onc_utils.h32
-rw-r--r--chromeos/network/onc/onc_utils_unittest.cc50
-rw-r--r--chromeos/test/data/network/shill_ethernet.json1
-rw-r--r--chromeos/test/data/network/shill_l2tpipsec_clientcert.json10
-rw-r--r--chromeos/test/data/network/shill_openvpn.json2
-rw-r--r--chromeos/test/data/network/shill_openvpn_clientcert.json13
-rw-r--r--chromeos/test/data/network/shill_wifi_clientcert.json10
-rw-r--r--chromeos/test/data/network/shill_wifi_clientref.json10
-rw-r--r--chromeos/test/data/network/shill_wifi_psk.json9
-rw-r--r--chromeos/test/data/network/valid_l2tpipsec_clientcert.onc31
-rw-r--r--chromeos/test/data/network/valid_openvpn.onc2
-rw-r--r--chromeos/test/data/network/valid_openvpn_clientcert.onc35
-rw-r--r--chromeos/test/data/network/valid_wifi_clientcert.onc29
-rw-r--r--chromeos/test/data/network/valid_wifi_clientref.onc23
-rw-r--r--chromeos/test/data/network/valid_wifi_psk.onc33
39 files changed, 981 insertions, 41 deletions
diff --git a/chrome/browser/chromeos/net/onc_utils.cc b/chrome/browser/chromeos/net/onc_utils.cc
new file mode 100644
index 0000000..8ac31f5
--- /dev/null
+++ b/chrome/browser/chromeos/net/onc_utils.cc
@@ -0,0 +1,224 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/onc_utils.h"
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/cros/network_ui_data.h"
+#include "chrome/browser/chromeos/proxy_config_service_impl.h"
+#include "chrome/browser/prefs/proxy_config_dictionary.h"
+#include "chromeos/network/onc/onc_signature.h"
+#include "chromeos/network/onc/onc_utils.h"
+#include "googleurl/src/gurl.h"
+#include "net/proxy/proxy_server.h"
+
+namespace chromeos {
+namespace onc {
+
+namespace {
+
+net::ProxyServer ConvertOncProxyLocationToHostPort(
+ net::ProxyServer::Scheme default_proxy_scheme,
+ const base::DictionaryValue& onc_proxy_location) {
+ std::string host;
+ onc_proxy_location.GetStringWithoutPathExpansion(onc::proxy::kHost, &host);
+ // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
+ net::ProxyServer proxy_server =
+ net::ProxyServer::FromURI(host, default_proxy_scheme);
+ int port = 0;
+ onc_proxy_location.GetIntegerWithoutPathExpansion(onc::proxy::kPort, &port);
+
+ // Replace the port parsed from |host| by the provided |port|.
+ return net::ProxyServer(
+ proxy_server.scheme(),
+ net::HostPortPair(proxy_server.host_port_pair().host(),
+ static_cast<uint16>(port)));
+}
+
+void AppendProxyServerForScheme(
+ const base::DictionaryValue& onc_manual,
+ const std::string& onc_scheme,
+ std::string* spec) {
+ const base::DictionaryValue* onc_proxy_location = NULL;
+ if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
+ &onc_proxy_location)) {
+ return;
+ }
+
+ net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
+ std::string url_scheme;
+ if (onc_scheme == proxy::kFtp) {
+ url_scheme = "ftp";
+ } else if (onc_scheme == proxy::kHttp) {
+ url_scheme = "http";
+ } else if (onc_scheme == proxy::kHttps) {
+ url_scheme = "https";
+ } else if (onc_scheme == proxy::kSocks) {
+ default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
+ url_scheme = "socks";
+ } else {
+ NOTREACHED();
+ }
+
+ net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
+ default_proxy_scheme, *onc_proxy_location);
+
+ ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
+ url_scheme, proxy_server, spec);
+}
+
+net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
+ const base::ListValue& onc_exclude_domains) {
+ net::ProxyBypassRules rules;
+ for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
+ it != onc_exclude_domains.end(); ++it) {
+ std::string rule;
+ (*it)->GetAsString(&rule);
+ rules.AddRuleFromString(rule);
+ }
+ return rules;
+}
+
+} // namespace
+
+scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
+ const base::DictionaryValue& onc_proxy_settings) {
+ std::string type;
+ onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kType, &type);
+ scoped_ptr<DictionaryValue> proxy_dict;
+
+ if (type == proxy::kDirect) {
+ proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
+ } else if (type == proxy::kWPAD) {
+ proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
+ } else if (type == proxy::kPAC) {
+ std::string pac_url;
+ onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kPAC, &pac_url);
+ GURL url(pac_url);
+ DCHECK(url.is_valid())
+ << "PAC field is invalid for this ProxySettings.Type";
+ proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
+ false));
+ } else if (type == proxy::kManual) {
+ const base::DictionaryValue* manual_dict = NULL;
+ onc_proxy_settings.GetDictionaryWithoutPathExpansion(proxy::kManual,
+ &manual_dict);
+ std::string manual_spec;
+ AppendProxyServerForScheme(*manual_dict, proxy::kFtp, &manual_spec);
+ AppendProxyServerForScheme(*manual_dict, proxy::kHttp, &manual_spec);
+ AppendProxyServerForScheme(*manual_dict, proxy::kSocks, &manual_spec);
+ AppendProxyServerForScheme(*manual_dict, proxy::kHttps, &manual_spec);
+
+ const base::ListValue* exclude_domains = NULL;
+ net::ProxyBypassRules bypass_rules;
+ if (onc_proxy_settings.GetListWithoutPathExpansion(proxy::kExcludeDomains,
+ &exclude_domains)) {
+ bypass_rules.AssignFrom(
+ ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
+ }
+ proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
+ manual_spec, bypass_rules.ToString()));
+ } else {
+ NOTREACHED();
+ }
+ return proxy_dict.Pass();
+}
+
+namespace {
+
+void TranslateClientCertType(const std::string& client_cert_type,
+ NetworkUIData* ui_data) {
+ ClientCertType type;
+ if (client_cert_type == certificate::kNone) {
+ type = CLIENT_CERT_TYPE_NONE;
+ } else if (client_cert_type == certificate::kRef) {
+ type = CLIENT_CERT_TYPE_REF;
+ } else if (client_cert_type == certificate::kPattern) {
+ type = CLIENT_CERT_TYPE_PATTERN;
+ } else {
+ type = CLIENT_CERT_TYPE_NONE;
+ NOTREACHED();
+ }
+
+ ui_data->set_certificate_type(type);
+}
+
+void TranslateCertificatePattern(const base::DictionaryValue& onc_object,
+ NetworkUIData* ui_data) {
+ CertificatePattern pattern;
+ bool success = pattern.CopyFromDictionary(onc_object);
+ DCHECK(success);
+ ui_data->set_certificate_pattern(pattern);
+}
+
+void TranslateEAP(const base::DictionaryValue& eap,
+ NetworkUIData* ui_data) {
+ std::string client_cert_type;
+ if (eap.GetStringWithoutPathExpansion(eap::kClientCertType,
+ &client_cert_type)) {
+ TranslateClientCertType(client_cert_type, ui_data);
+ }
+}
+
+void TranslateIPsec(const base::DictionaryValue& ipsec,
+ NetworkUIData* ui_data) {
+ std::string client_cert_type;
+ if (ipsec.GetStringWithoutPathExpansion(vpn::kClientCertType,
+ &client_cert_type)) {
+ TranslateClientCertType(client_cert_type, ui_data);
+ }
+}
+
+void TranslateOpenVPN(const base::DictionaryValue& openvpn,
+ NetworkUIData* ui_data) {
+ std::string client_cert_type;
+ if (openvpn.GetStringWithoutPathExpansion(vpn::kClientCertType,
+ &client_cert_type)) {
+ TranslateClientCertType(client_cert_type, ui_data);
+ }
+}
+
+void TranslateONCHierarchy(const OncValueSignature& signature,
+ const base::DictionaryValue& onc_object,
+ NetworkUIData* ui_data) {
+ if (&signature == &kCertificatePatternSignature)
+ TranslateCertificatePattern(onc_object, ui_data);
+ else if (&signature == &kEAPSignature)
+ TranslateEAP(onc_object, ui_data);
+ else if (&signature == &kIPsecSignature)
+ TranslateIPsec(onc_object, ui_data);
+ else if (&signature == &kOpenVPNSignature)
+ TranslateOpenVPN(onc_object, ui_data);
+
+ // Recurse into nested objects.
+ for (base::DictionaryValue::Iterator it(onc_object); it.HasNext();
+ it.Advance()) {
+ const base::DictionaryValue* inner_object;
+ if (!it.value().GetAsDictionary(&inner_object))
+ continue;
+
+ const OncFieldSignature* field_signature =
+ GetFieldSignature(signature, it.key());
+
+ TranslateONCHierarchy(*field_signature->value_signature, *inner_object,
+ ui_data);
+ }
+}
+
+} // namespace
+
+scoped_ptr<NetworkUIData> CreateUIData(
+ ONCSource onc_source,
+ const base::DictionaryValue& onc_network) {
+ scoped_ptr<NetworkUIData> ui_data(new NetworkUIData());
+ TranslateONCHierarchy(kNetworkConfigurationSignature, onc_network,
+ ui_data.get());
+
+ ui_data->set_onc_source(onc_source);
+
+ return ui_data.Pass();
+}
+
+} // namespace onc
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/onc_utils.h b/chrome/browser/chromeos/net/onc_utils.h
new file mode 100644
index 0000000..a1ddb32
--- /dev/null
+++ b/chrome/browser/chromeos/net/onc_utils.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NET_ONC_UTILS_H_
+#define CHROME_BROWSER_CHROMEOS_NET_ONC_UTILS_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/network/onc/onc_constants.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+class NetworkUIData;
+
+namespace onc {
+
+// Translates |onc_proxy_settings|, which has to be a valid ONC ProxySettings
+// dictionary, to a ProxyConfig dictionary (see
+// chrome/browser/prefs/proxy_config_dictionary.h).
+//
+// This function is used to translate ONC ProxySettings to the "ProxyConfig"
+// field of the Shill configuration.
+scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
+ const base::DictionaryValue& onc_proxy_settings);
+
+// Creates a NetworkUIData object from |onc_network|, which has to be a valid
+// ONC NetworkConfiguration dictionary.
+//
+// This function is used to create the "UIData" field of the Shill
+// configuration.
+scoped_ptr<NetworkUIData> CreateUIData(
+ ONCSource onc_source,
+ const base::DictionaryValue& onc_network);
+
+} // namespace onc
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_NET_ONC_UTILS_H_
diff --git a/chrome/browser/chromeos/net/onc_utils_unittest.cc b/chrome/browser/chromeos/net/onc_utils_unittest.cc
new file mode 100644
index 0000000..9d0de2d
--- /dev/null
+++ b/chrome/browser/chromeos/net/onc_utils_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/onc_utils.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/cros/network_ui_data.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "chromeos/network/onc/onc_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace onc {
+
+TEST(ONCUtils, ProxySettingsToProxyConfig) {
+ scoped_ptr<base::Value> test_data =
+ google_apis::test_util::LoadJSONFile("net/proxy_config.json");
+
+ base::ListValue* list_of_tests;
+ test_data->GetAsList(&list_of_tests);
+
+ int index = 0;
+ for (base::ListValue::iterator it = list_of_tests->begin();
+ it != list_of_tests->end(); ++it, ++index) {
+ SCOPED_TRACE("Test case #" + base::IntToString(index));
+
+ base::DictionaryValue* test_case;
+ (*it)->GetAsDictionary(&test_case);
+
+ base::DictionaryValue* onc_proxy_settings;
+ test_case->GetDictionary("ONC_ProxySettings", &onc_proxy_settings);
+
+ base::DictionaryValue* expected_proxy_config;
+ test_case->GetDictionary("ProxyConfig", &expected_proxy_config);
+
+ scoped_ptr<base::DictionaryValue> actual_proxy_config =
+ ConvertOncProxySettingsToProxyConfig(*onc_proxy_settings);
+ EXPECT_TRUE(test_utils::Equals(expected_proxy_config,
+ actual_proxy_config.get()));
+ }
+}
+
+class ONCCreateUIDataTest
+ : public ::testing::TestWithParam<std::pair<std::string, std::string> > {
+};
+
+TEST_P(ONCCreateUIDataTest, CreateUIData) {
+ scoped_ptr<base::DictionaryValue> onc_network =
+ test_utils::ReadTestDictionary(GetParam().first);
+
+ scoped_ptr<base::Value> expected_uidata =
+ google_apis::test_util::LoadJSONFile(GetParam().second);
+ const base::DictionaryValue* expected_uidata_dict;
+ expected_uidata->GetAsDictionary(&expected_uidata_dict);
+
+ scoped_ptr<NetworkUIData> actual_uidata =
+ CreateUIData(ONC_SOURCE_USER_POLICY, *onc_network);
+ EXPECT_TRUE(actual_uidata != NULL);
+
+ base::DictionaryValue actual_uidata_dict;
+ actual_uidata->FillDictionary(&actual_uidata_dict);
+ EXPECT_TRUE(test_utils::Equals(&actual_uidata_dict, expected_uidata_dict));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ ONCCreateUIDataTest,
+ ONCCreateUIDataTest,
+ ::testing::Values(
+ std::make_pair("valid_wifi_clientcert.onc",
+ "net/uidata_for_wifi_clientcert.json"),
+ std::make_pair("valid_wifi_clientref.onc",
+ "net/uidata_for_wifi_clientref.json"),
+ std::make_pair("valid_wifi_psk.onc", "net/uidata_for_wifi_psk.json"),
+ std::make_pair("valid_openvpn_clientcert.onc",
+ "net/uidata_for_openvpn_clientcert.json"),
+ std::make_pair("valid_l2tpipsec_clientcert.onc",
+ "net/uidata_for_l2tpipsec_clientcert.json")));
+
+} // namespace onc
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.cc b/chrome/browser/chromeos/proxy_config_service_impl.cc
index eee5875..23e91fe 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl.cc
@@ -363,7 +363,7 @@ bool ProxyConfigServiceImpl::ProxyConfig::SerializeForNetwork(
// static
void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
- const std::string& scheme,
+ const std::string& url_scheme,
const net::ProxyServer& server,
std::string* spec) {
if (!server.is_valid())
@@ -372,8 +372,8 @@ void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
if (!spec->empty())
*spec += ';';
- if (!scheme.empty()) {
- *spec += scheme;
+ if (!url_scheme.empty()) {
+ *spec += url_scheme;
*spec += "=";
}
*spec += server.ToURI();
diff --git a/chrome/browser/chromeos/proxy_config_service_impl.h b/chrome/browser/chromeos/proxy_config_service_impl.h
index bb95ee2..6f4271c 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl.h
+++ b/chrome/browser/chromeos/proxy_config_service_impl.h
@@ -106,7 +106,7 @@ class ProxyConfigServiceImpl
bool SerializeForNetwork(std::string* output);
// Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>"
- static void EncodeAndAppendProxyServer(const std::string& scheme,
+ static void EncodeAndAppendProxyServer(const std::string& url_scheme,
const net::ProxyServer& server,
std::string* spec);
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index ac15e55..c2d1b71 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -506,6 +506,8 @@
'browser/chromeos/net/network_change_notifier_network_library.h',
'browser/chromeos/net/network_portal_detector.cc',
'browser/chromeos/net/network_portal_detector.h',
+ 'browser/chromeos/net/onc_utils.cc',
+ 'browser/chromeos/net/onc_utils.h',
'browser/chromeos/network_login_observer.cc',
'browser/chromeos/network_login_observer.h',
'browser/chromeos/network_message_observer.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 1a2302e..78166d1 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -594,6 +594,7 @@
'browser/chromeos/memory/oom_priority_manager_unittest.cc',
'browser/chromeos/mobile_config_unittest.cc',
'browser/chromeos/net/network_portal_detector_unittest.cc',
+ 'browser/chromeos/net/onc_utils_unittest.cc',
'browser/chromeos/offline/offline_load_page_unittest.cc',
'browser/chromeos/power/session_length_limiter_unittest.cc',
'browser/chromeos/preferences_unittest.cc',
diff --git a/chrome/test/data/chromeos/net/proxy_config.json b/chrome/test/data/chromeos/net/proxy_config.json
new file mode 100644
index 0000000..8e122d4
--- /dev/null
+++ b/chrome/test/data/chromeos/net/proxy_config.json
@@ -0,0 +1,84 @@
+[
+ { "ONC_ProxySettings": {
+ "Manual": {
+ "FTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "HTTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "SOCKS": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "SecureHTTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ }
+ },
+ "Type": "Manual"
+ },
+ "ProxyConfig": {
+ "mode":"fixed_servers",
+ "server":"ftp=192.168.2.1:8889;http=192.168.2.1:8889;socks=socks4://192.168.2.1:8889;https=192.168.2.1:8889"
+ }
+ },
+ {
+ "ONC_ProxySettings": {
+ "Type": "Manual",
+ "Manual": {
+ "HTTPProxy" : {
+ "Host" : "http.example.com",
+ "Port" : 1234
+ },
+ "SecureHTTPProxy" : {
+ "Host" : "https.example.com",
+ "Port" : 3456
+ },
+ "FTPProxy" : {
+ "Host" : "ftp.example.com",
+ "Port" : 5678
+ },
+ "SOCKS" : {
+ "Host" : "socks5://socks.example.com",
+ "Port" : 7890
+ }
+ },
+ "ExcludeDomains": [
+ "google.com",
+ "<local>"
+ ]
+ },
+ "ProxyConfig": {
+ "bypass_list":"google.com;\u003Clocal\u003E;",
+ "mode":"fixed_servers",
+ "server":"ftp=ftp.example.com:5678;http=http.example.com:1234;socks=socks5://socks.example.com:7890;https=https.example.com:3456"
+ }
+ },
+ { "ONC_ProxySettings": {
+ "Type": "PAC",
+ "PAC": "https://proxycfg.my.domain.com/proxy.dat"
+ },
+ "ProxyConfig": {
+ "mode":"pac_script",
+ "pac_mandatory":false,
+ "pac_url":"https://proxycfg.my.domain.com/proxy.dat"
+ }
+ },
+ { "ONC_ProxySettings": {
+ "Type": "WPAD"
+ },
+ "ProxyConfig": {
+ "mode": "auto_detect"
+ }
+ },
+ { "ONC_ProxySettings": {
+ "Type": "Direct"
+ },
+ "ProxyConfig": {
+ "mode": "direct"
+ }
+ }
+]
diff --git a/chrome/test/data/chromeos/net/uidata_for_l2tpipsec_clientcert.json b/chrome/test/data/chromeos/net/uidata_for_l2tpipsec_clientcert.json
new file mode 100644
index 0000000..58c1429
--- /dev/null
+++ b/chrome/test/data/chromeos/net/uidata_for_l2tpipsec_clientcert.json
@@ -0,0 +1,19 @@
+{
+ "certificate_pattern": {
+ "EnrollmentURI": [
+ "my.enrollment.url"
+ ],
+ "IssuerCARef": [
+ "def",
+ "abc"
+ ],
+ "Issuer": {
+ "CommonName": "common_name",
+ "Locality": "locality",
+ "Organization": "organization",
+ "OrganizationalUnit": "unit"
+ }
+ },
+ "certificate_type": "pattern",
+ "onc_source": "user_policy"
+}
diff --git a/chrome/test/data/chromeos/net/uidata_for_openvpn_clientcert.json b/chrome/test/data/chromeos/net/uidata_for_openvpn_clientcert.json
new file mode 100644
index 0000000..2b98506
--- /dev/null
+++ b/chrome/test/data/chromeos/net/uidata_for_openvpn_clientcert.json
@@ -0,0 +1,19 @@
+{
+ "certificate_pattern": {
+ "EnrollmentURI": [
+ "my.enrollment.url"
+ ],
+ "IssuerCARef": [
+ "def",
+ "abc"
+ ],
+ "Subject": {
+ "CommonName": "common_name",
+ "Locality": "locality",
+ "Organization": "organization",
+ "OrganizationalUnit": "unit"
+ }
+ },
+ "certificate_type": "pattern",
+ "onc_source": "user_policy"
+}
diff --git a/chrome/test/data/chromeos/net/uidata_for_wifi_clientcert.json b/chrome/test/data/chromeos/net/uidata_for_wifi_clientcert.json
new file mode 100644
index 0000000..f8ec949
--- /dev/null
+++ b/chrome/test/data/chromeos/net/uidata_for_wifi_clientcert.json
@@ -0,0 +1,13 @@
+{
+ "certificate_pattern": {
+ "EnrollmentURI": [
+ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html"
+ ],
+ "IssuerCARef": [
+ "{58ac1967-a0e7-49e9-be68-123abc}",
+ "{42cb13cd-140c-4941-9fb6-456def}"
+ ]
+ },
+ "certificate_type": "pattern",
+ "onc_source": "user_policy"
+}
diff --git a/chrome/test/data/chromeos/net/uidata_for_wifi_clientref.json b/chrome/test/data/chromeos/net/uidata_for_wifi_clientref.json
new file mode 100644
index 0000000..d8a8bc0
--- /dev/null
+++ b/chrome/test/data/chromeos/net/uidata_for_wifi_clientref.json
@@ -0,0 +1,4 @@
+{
+ "certificate_type": "ref",
+ "onc_source": "user_policy"
+}
diff --git a/chrome/test/data/chromeos/net/uidata_for_wifi_psk.json b/chrome/test/data/chromeos/net/uidata_for_wifi_psk.json
new file mode 100644
index 0000000..f4edf00
--- /dev/null
+++ b/chrome/test/data/chromeos/net/uidata_for_wifi_psk.json
@@ -0,0 +1,3 @@
+{
+ "onc_source": "user_policy"
+}
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 7122fc6..61ca41a 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -262,6 +262,8 @@
'dbus/mock_update_engine_client.h',
'disks/mock_disk_mount_manager.cc',
'disks/mock_disk_mount_manager.h',
+ 'network/onc/onc_test_utils.cc',
+ 'network/onc/onc_test_utils.h',
],
'include_dirs': [
'..',
@@ -346,8 +348,6 @@
'network/onc/onc_certificate_importer_unittest.cc',
'network/onc/onc_merger_unittest.cc',
'network/onc/onc_normalizer_unittest.cc',
- 'network/onc/onc_test_utils.cc',
- 'network/onc/onc_test_utils.h',
'network/onc/onc_translator_unittest.cc',
'network/onc/onc_utils_unittest.cc',
'network/onc/onc_validator_unittest.cc',
diff --git a/chromeos/network/onc/onc_certificate_importer.cc b/chromeos/network/onc/onc_certificate_importer.cc
index e1ae94b..451c6d9 100644
--- a/chromeos/network/onc/onc_certificate_importer.cc
+++ b/chromeos/network/onc/onc_certificate_importer.cc
@@ -370,5 +370,5 @@ bool CertificateImporter::ParseClientCertificate(
return true;
}
-} // chromeos
-} // onc
+} // namespace onc
+} // namespace chromeos
diff --git a/chromeos/network/onc/onc_certificate_importer.h b/chromeos/network/onc/onc_certificate_importer.h
index bb64f81..1fed941 100644
--- a/chromeos/network/onc/onc_certificate_importer.h
+++ b/chromeos/network/onc/onc_certificate_importer.h
@@ -85,7 +85,7 @@ class CHROMEOS_EXPORT CertificateImporter {
DISALLOW_COPY_AND_ASSIGN(CertificateImporter);
};
-} // chromeos
-} // onc
+} // namespace onc
+} // namespace chromeos
#endif // CHROMEOS_NETWORK_ONC_ONC_CERTIFICATE_IMPORTER_H_
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc
index 974df42..1603c57 100644
--- a/chromeos/network/onc/onc_signature.cc
+++ b/chromeos/network/onc/onc_signature.cc
@@ -37,6 +37,8 @@ const OncFieldSignature issuer_subject_pattern_fields[] = {
{ NULL }
};
+// CertificatePattern is converted with function CreateUIData(...) to UIData
+// stored in Shill.
const OncFieldSignature certificate_pattern_fields[] = {
{ kRecommended, NULL, &kRecommendedSignature },
{ certificate::kEnrollmentURI, NULL, &kStringListSignature },
@@ -54,8 +56,10 @@ const OncFieldSignature eap_fields[] = {
{ eap::kClientCertRef, NULL, &kStringSignature },
{ eap::kClientCertType, NULL, &kStringSignature },
{ eap::kIdentity, flimflam::kEapIdentityProperty, &kStringSignature },
- { eap::kInner, flimflam::kEapPhase2AuthProperty, &kStringSignature },
- { eap::kOuter, flimflam::kEapMethodProperty, &kStringSignature },
+ // This field is converted during translation, see onc_translator_*.
+ { eap::kInner, NULL, &kStringSignature },
+ // This field is converted during translation, see onc_translator_*.
+ { eap::kOuter, NULL, &kStringSignature },
{ eap::kPassword, flimflam::kEapPasswordProperty, &kStringSignature },
{ eap::kSaveCredentials, flimflam::kSaveCredentialsProperty,
&kBoolSignature },
@@ -126,6 +130,7 @@ const OncFieldSignature openvpn_fields[] = {
{ vpn::kSaveCredentials, flimflam::kSaveCredentialsProperty,
&kBoolSignature },
{ vpn::kServerCARef, flimflam::kOpenVPNCaCertNSSProperty, &kStringSignature },
+ // Not supported, yet.
{ vpn::kServerCertRef, NULL, &kStringSignature },
{ vpn::kServerPollTimeout, flimflam::kOpenVPNServerPollTimeoutProperty,
&kIntegerSignature },
@@ -136,6 +141,7 @@ const OncFieldSignature openvpn_fields[] = {
&kStringSignature },
{ vpn::kTLSRemote, flimflam::kOpenVPNTLSRemoteProperty, &kStringSignature },
{ vpn::kUsername, flimflam::kOpenVPNUserProperty, &kStringSignature },
+ // Not supported, yet.
{ vpn::kVerb, NULL, &kStringSignature },
{ NULL }
};
@@ -147,25 +153,26 @@ const OncFieldSignature vpn_fields[] = {
{ vpn::kL2TP, NULL, &kL2TPSignature },
{ vpn::kOpenVPN, NULL, &kOpenVPNSignature },
// This field is converted during translation, see onc_translator_*.
- { kType, NULL, &kStringSignature },
+ { vpn::kType, NULL, &kStringSignature },
{ NULL }
};
const OncFieldSignature ethernet_fields[] = {
{ kRecommended, NULL, &kRecommendedSignature },
+ // Not supported, yet.
{ ethernet::kAuthentication, NULL, &kStringSignature },
{ ethernet::kEAP, NULL, &kEAPSignature },
{ NULL }
};
+// Not supported, yet.
const OncFieldSignature ipconfig_fields[] = {
{ ipconfig::kGateway, NULL, &kStringSignature },
{ ipconfig::kIPAddress, NULL, &kStringSignature },
{ kNameServers, NULL, &kStringSignature },
{ ipconfig::kRoutingPrefix, NULL, &kIntegerSignature },
{ kSearchDomains, NULL, &kStringListSignature },
- // This field is converted during translation, see onc_translator_*.
- { kType, NULL, &kStringSignature },
+ { ipconfig::kType, NULL, &kStringSignature },
{ NULL }
};
@@ -183,12 +190,14 @@ const OncFieldSignature proxy_manual_fields[] = {
{ NULL }
};
+// Proxy settings are converted to Shill by
+// function ConvertOncProxySettingsToProxyConfig(...).
const OncFieldSignature proxy_settings_fields[] = {
{ kRecommended, NULL, &kRecommendedSignature },
{ proxy::kExcludeDomains, NULL, &kStringListSignature },
{ proxy::kManual, NULL, &kProxyManualSignature },
{ proxy::kPAC, NULL, &kStringSignature },
- { kType, NULL, &kStringSignature },
+ { proxy::kType, NULL, &kStringSignature },
{ NULL }
};
@@ -199,7 +208,8 @@ const OncFieldSignature wifi_fields[] = {
{ wifi::kHiddenSSID, flimflam::kWifiHiddenSsid, &kBoolSignature },
{ wifi::kPassphrase, flimflam::kPassphraseProperty, &kStringSignature },
{ wifi::kSSID, flimflam::kSSIDProperty, &kStringSignature },
- { wifi::kSecurity, flimflam::kSecurityProperty, &kStringSignature },
+ // This field is converted during translation, see onc_translator_*.
+ { wifi::kSecurity, NULL, &kStringSignature },
{ NULL }
};
@@ -208,10 +218,15 @@ const OncFieldSignature network_configuration_fields[] = {
{ kEthernet, NULL, &kEthernetSignature },
{ kGUID, flimflam::kGuidProperty, &kStringSignature },
{ kIPConfigs, NULL, &kIPConfigListSignature },
- { kName, flimflam::kNameProperty, &kStringSignature },
+ // Shill doesn't allow setting the name for non-VPN networks.
+ // This field is conditionally translated, see onc_translator_*.
+ { kName, NULL, &kStringSignature },
+ // Not supported, yet.
{ kNameServers, NULL, &kStringListSignature },
{ kProxySettings, NULL, &kProxySettingsSignature },
+ // No need to translate.
{ kRemove, NULL, &kBoolSignature },
+ // Not supported, yet.
{ kSearchDomains, NULL, &kStringListSignature },
// This field is converted during translation, see onc_translator_*.
{ kType, NULL, &kStringSignature },
@@ -220,12 +235,13 @@ const OncFieldSignature network_configuration_fields[] = {
{ NULL }
};
+// Certificates are not translated to Shill.
const OncFieldSignature certificate_fields[] = {
- { kGUID, flimflam::kGuidProperty, &kStringSignature },
+ { kGUID, NULL, &kStringSignature },
{ certificate::kPKCS12, NULL, &kStringSignature },
{ kRemove, NULL, &kBoolSignature },
{ certificate::kTrust, NULL, &kStringListSignature },
- { kType, NULL, &kStringSignature },
+ { certificate::kType, NULL, &kStringSignature },
{ certificate::kX509, NULL, &kStringSignature },
{ NULL }
};
diff --git a/chromeos/network/onc/onc_signature.h b/chromeos/network/onc/onc_signature.h
index 7ef17c0..71ab0af 100644
--- a/chromeos/network/onc/onc_signature.h
+++ b/chromeos/network/onc/onc_signature.h
@@ -27,8 +27,9 @@ struct CHROMEOS_EXPORT OncValueSignature {
const OncValueSignature* onc_array_entry_signature;
};
-const OncFieldSignature* GetFieldSignature(const OncValueSignature& signature,
- const std::string& onc_field_name);
+CHROMEOS_EXPORT const OncFieldSignature* GetFieldSignature(
+ const OncValueSignature& signature,
+ const std::string& onc_field_name);
CHROMEOS_EXPORT extern const OncValueSignature kRecommendedSignature;
CHROMEOS_EXPORT extern const OncValueSignature kEAPSignature;
diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc
index abe978f..6dc4a8f 100644
--- a/chromeos/network/onc/onc_translation_tables.cc
+++ b/chromeos/network/onc/onc_translation_tables.cc
@@ -26,5 +26,37 @@ const StringTranslationEntry kVPNTypeTable[] = {
{ NULL }
};
+const StringTranslationEntry kWiFiSecurityTable[] = {
+ { wifi::kNone, flimflam::kSecurityNone },
+ { wifi::kWEP_PSK, flimflam::kSecurityWep },
+ { wifi::kWPA_PSK, flimflam::kSecurityPsk },
+ { wifi::kWPA_EAP, flimflam::kSecurity8021x },
+ { NULL }
+};
+
+const StringTranslationEntry kEAPOuterTable[] = {
+ { eap::kPEAP, flimflam::kEapMethodPEAP },
+ { eap::kEAP_TLS, flimflam::kEapMethodTLS },
+ { eap::kEAP_TTLS, flimflam::kEapMethodTTLS },
+ { eap::kLEAP, flimflam::kEapMethodLEAP },
+ { NULL }
+};
+
+// Translation of the EAP.Inner field in case of EAP.Outer == PEAP
+const StringTranslationEntry kEAP_PEAP_InnerTable[] = {
+ { eap::kMD5, flimflam::kEapPhase2AuthPEAPMD5 },
+ { eap::kMSCHAPv2, flimflam::kEapPhase2AuthPEAPMSCHAPV2 },
+ { NULL }
+};
+
+// Translation of the EAP.Inner field in case of EAP.Outer == TTLS
+const StringTranslationEntry kEAP_TTLS_InnerTable[] = {
+ { eap::kMD5, flimflam::kEapPhase2AuthTTLSMD5 },
+ { eap::kMSCHAPv2, flimflam::kEapPhase2AuthTTLSMSCHAPV2 },
+ { eap::kPAP, flimflam::kEapPhase2AuthTTLSPAP },
+ { NULL }
+};
+
+
} // namespace onc
} // namespace chromeos
diff --git a/chromeos/network/onc/onc_translation_tables.h b/chromeos/network/onc/onc_translation_tables.h
index f9b54a8..276b132 100644
--- a/chromeos/network/onc/onc_translation_tables.h
+++ b/chromeos/network/onc/onc_translation_tables.h
@@ -17,6 +17,10 @@ struct StringTranslationEntry {
// These are NULL-terminated arrays.
extern const StringTranslationEntry kNetworkTypeTable[];
extern const StringTranslationEntry kVPNTypeTable[];
+extern const StringTranslationEntry kWiFiSecurityTable[];
+extern const StringTranslationEntry kEAPOuterTable[];
+extern const StringTranslationEntry kEAP_PEAP_InnerTable[];
+extern const StringTranslationEntry kEAP_TTLS_InnerTable[];
} // namespace onc
} // namespace chromeos
diff --git a/chromeos/network/onc/onc_translator_onc_to_shill.cc b/chromeos/network/onc/onc_translator_onc_to_shill.cc
index cd8a4eb..6f38700 100644
--- a/chromeos/network/onc/onc_translator_onc_to_shill.cc
+++ b/chromeos/network/onc/onc_translator_onc_to_shill.cc
@@ -53,6 +53,8 @@ class LocalTranslator {
private:
void TranslateOpenVPN();
void TranslateVPN();
+ void TranslateWiFi();
+ void TranslateEAP();
void TranslateNetworkConfiguration();
// Copies all entries from |onc_object_| to |shill_dictionary_| for which a
@@ -86,6 +88,10 @@ void LocalTranslator::TranslateFields() {
TranslateVPN();
else if (onc_signature_ == &kOpenVPNSignature)
TranslateOpenVPN();
+ else if (onc_signature_ == &kWiFiSignature)
+ TranslateWiFi();
+ else if (onc_signature_ == &kEAPSignature)
+ TranslateEAP();
else
CopyFieldsAccordingToSignature();
}
@@ -115,13 +121,58 @@ void LocalTranslator::TranslateOpenVPN() {
}
void LocalTranslator::TranslateVPN() {
- TranslateWithTableAndSet(kType, kVPNTypeTable,
+ std::string type;
+ onc_object_->GetStringWithoutPathExpansion(kType, &type);
+ TranslateWithTableAndSet(type, kVPNTypeTable,
flimflam::kProviderTypeProperty);
+
+ CopyFieldsAccordingToSignature();
+}
+
+void LocalTranslator::TranslateWiFi() {
+ std::string security;
+ onc_object_->GetStringWithoutPathExpansion(wifi::kSecurity, &security);
+ TranslateWithTableAndSet(security, kWiFiSecurityTable,
+ flimflam::kSecurityProperty);
+
+ CopyFieldsAccordingToSignature();
+}
+
+void LocalTranslator::TranslateEAP() {
+ std::string outer;
+ onc_object_->GetStringWithoutPathExpansion(eap::kOuter, &outer);
+ TranslateWithTableAndSet(outer, kEAPOuterTable, flimflam::kEapMethodProperty);
+
+ // Translate the inner protocol only for outer tunneling protocols.
+ if (outer == eap::kPEAP || outer == eap::kEAP_TTLS) {
+ // In ONC the Inner protocol defaults to "Automatic".
+ std::string inner = eap::kAutomatic;
+ // ONC's Inner == "Automatic" translates to omitting the Phase2 property in
+ // Shill.
+ onc_object_->GetStringWithoutPathExpansion(eap::kInner, &inner);
+ if (inner != eap::kAutomatic) {
+ const StringTranslationEntry* table =
+ outer == eap::kPEAP ? kEAP_PEAP_InnerTable : kEAP_TTLS_InnerTable;
+ TranslateWithTableAndSet(inner, table, flimflam::kEapPhase2AuthProperty);
+ }
+ }
+
CopyFieldsAccordingToSignature();
}
void LocalTranslator::TranslateNetworkConfiguration() {
- TranslateWithTableAndSet(kType, kNetworkTypeTable, flimflam::kTypeProperty);
+ std::string type;
+ onc_object_->GetStringWithoutPathExpansion(kType, &type);
+ TranslateWithTableAndSet(type, kNetworkTypeTable, flimflam::kTypeProperty);
+
+ // Shill doesn't allow setting the name for non-VPN networks.
+ if (type == kVPN) {
+ std::string name;
+ onc_object_->GetStringWithoutPathExpansion(kName, &name);
+ shill_dictionary_->SetStringWithoutPathExpansion(
+ flimflam::kNameProperty, name);
+ }
+
CopyFieldsAccordingToSignature();
}
@@ -149,13 +200,9 @@ void LocalTranslator::AddValueAccordingToSignature(
}
void LocalTranslator::TranslateWithTableAndSet(
- const std::string& onc_field_name,
+ const std::string& onc_value,
const StringTranslationEntry table[],
const std::string& shill_property_name) {
- std::string onc_value;
- if (!onc_object_->GetStringWithoutPathExpansion(onc_field_name, &onc_value))
- return;
-
for (int i = 0; table[i].onc_value != NULL; ++i) {
if (onc_value != table[i].onc_value)
continue;
@@ -166,8 +213,7 @@ void LocalTranslator::TranslateWithTableAndSet(
// As we previously validate ONC, this case should never occur. If it still
// occurs, we should check here. Otherwise the failure will only show up much
// later in Shill.
- LOG(ERROR) << "Value '" << onc_value << "' for field '"
- << onc_field_name << "' cannot be translated to Shill";
+ LOG(ERROR) << "Value '" << onc_value << "cannot be translated to Shill";
}
// Iterates recursively over |onc_object| and its |signature|. At each object
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc
index c33e0a9..afdbaaf 100644
--- a/chromeos/network/onc/onc_translator_shill_to_onc.cc
+++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -179,6 +179,13 @@ void ShillToONCTranslator::TranslateNetworkConfiguration() {
std::string network_type;
if (onc_object_->GetStringWithoutPathExpansion(kType, &network_type))
TranslateAndAddNestedObject(network_type);
+
+ if (network_type == kVPN) {
+ std::string name;
+ shill_dictionary_->GetStringWithoutPathExpansion(flimflam::kNameProperty,
+ &name);
+ onc_object_->SetStringWithoutPathExpansion(kName, name);
+ }
}
void ShillToONCTranslator::CopyPropertiesAccordingToSignature() {
diff --git a/chromeos/network/onc/onc_translator_unittest.cc b/chromeos/network/onc/onc_translator_unittest.cc
index da9e658..2a256e2 100644
--- a/chromeos/network/onc/onc_translator_unittest.cc
+++ b/chromeos/network/onc/onc_translator_unittest.cc
@@ -42,8 +42,17 @@ INSTANTIATE_TEST_CASE_P(
ONCTranslatorOncToShillTest,
::testing::Values(
std::make_pair("managed_ethernet.onc", "shill_ethernet.json"),
+ std::make_pair("valid_wifi_psk.onc", "shill_wifi_psk.json"),
+ std::make_pair("valid_wifi_clientcert.onc",
+ "shill_wifi_clientcert.json"),
+ std::make_pair("valid_wifi_clientref.onc",
+ "shill_wifi_clientref.json"),
std::make_pair("valid_l2tpipsec.onc", "shill_l2tpipsec.json"),
- std::make_pair("valid_openvpn.onc", "shill_openvpn.json")));
+ std::make_pair("valid_l2tpipsec_clientcert.onc",
+ "shill_l2tpipsec_clientcert.json"),
+ std::make_pair("valid_openvpn.onc", "shill_openvpn.json"),
+ std::make_pair("valid_openvpn_clientcert.onc",
+ "shill_openvpn_clientcert.json")));
// Test the translation from Shill json to ONC.
//
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 85cfe64..c66d1e8 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -7,9 +7,9 @@
#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
+#include "base/string_util.h"
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
-#include "chromeos/network/onc/onc_constants.h"
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
@@ -164,5 +164,56 @@ std::string GetSourceAsString(ONCSource source) {
return "unknown";
}
-} // chromeos
-} // onc
+void ExpandField(const std::string fieldname,
+ const StringSubstitution& substitution,
+ base::DictionaryValue* onc_object) {
+ std::string user_string;
+ if (!onc_object->GetStringWithoutPathExpansion(fieldname, &user_string))
+ return;
+
+ std::string login_id;
+ if (substitution.GetSubstitute(substitutes::kLoginIDField, &login_id)) {
+ ReplaceSubstringsAfterOffset(&user_string, 0,
+ onc::substitutes::kLoginIDField,
+ login_id);
+ }
+
+ std::string email;
+ if (substitution.GetSubstitute(substitutes::kEmailField, &email)) {
+ ReplaceSubstringsAfterOffset(&user_string, 0,
+ onc::substitutes::kEmailField,
+ email);
+ }
+
+ onc_object->SetStringWithoutPathExpansion(fieldname, user_string);
+}
+
+void ExpandStringsInOncObject(
+ const OncValueSignature& signature,
+ const StringSubstitution& substitution,
+ base::DictionaryValue* onc_object) {
+ if (&signature == &kEAPSignature) {
+ ExpandField(eap::kAnonymousIdentity, substitution, onc_object);
+ ExpandField(eap::kIdentity, substitution, onc_object);
+ } else if (&signature == &kL2TPSignature ||
+ &signature == &kOpenVPNSignature) {
+ ExpandField(vpn::kUsername, substitution, onc_object);
+ }
+
+ // Recurse into nested objects.
+ for (base::DictionaryValue::key_iterator it = onc_object->begin_keys();
+ it != onc_object->end_keys(); ++it) {
+ base::DictionaryValue* inner_object;
+ if (!onc_object->GetDictionaryWithoutPathExpansion(*it, &inner_object))
+ continue;
+
+ const OncFieldSignature* field_signature =
+ GetFieldSignature(signature, *it);
+
+ ExpandStringsInOncObject(*field_signature->value_signature,
+ substitution, inner_object);
+ }
+}
+
+} // namespace onc
+} // namespace chromeos
diff --git a/chromeos/network/onc/onc_utils.h b/chromeos/network/onc/onc_utils.h
index 13263a8..61ab3a4 100644
--- a/chromeos/network/onc/onc_utils.h
+++ b/chromeos/network/onc/onc_utils.h
@@ -7,9 +7,11 @@
#include <string>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/network/onc/onc_constants.h"
+#include "chromeos/network/onc/onc_signature.h"
namespace base {
class DictionaryValue;
@@ -28,7 +30,7 @@ CHROMEOS_EXPORT extern const char kEmptyUnencryptedConfiguration[];
CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> ReadDictionaryFromJson(
const std::string& json);
-// Decrypt the given EncryptedConfiguration |onc| (see the ONC specification)
+// Decrypts the given EncryptedConfiguration |onc| (see the ONC specification)
// using |passphrase|. The resulting UnencryptedConfiguration is returned. If an
// error occurs, returns NULL.
CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> Decrypt(
@@ -38,7 +40,31 @@ CHROMEOS_EXPORT scoped_ptr<base::DictionaryValue> Decrypt(
// For logging only: strings not user facing.
CHROMEOS_EXPORT std::string GetSourceAsString(ONCSource source);
-} // chromeos
-} // onc
+// Used for string expansion with function ExpandStringInOncObject(...).
+class CHROMEOS_EXPORT StringSubstitution {
+ public:
+ StringSubstitution() {}
+ virtual ~StringSubstitution() {}
+
+ // Returns the replacement string for |placeholder| in
+ // |substitute|. Currently, onc::substitutes::kLoginIDField and
+ // onc::substitutes::kEmailField are supported.
+ virtual bool GetSubstitute(std::string placeholder,
+ std::string* substitute) const = 0;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(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|.
+CHROMEOS_EXPORT void ExpandStringsInOncObject(
+ const OncValueSignature& signature,
+ const StringSubstitution& substitution,
+ base::DictionaryValue* onc_object);
+
+} // namespace onc
+} // namespace chromeos
#endif // CHROMEOS_NETWORK_ONC_ONC_UTILS_H_
diff --git a/chromeos/network/onc/onc_utils_unittest.cc b/chromeos/network/onc/onc_utils_unittest.cc
index 93ed390..f2226b1 100644
--- a/chromeos/network/onc/onc_utils_unittest.cc
+++ b/chromeos/network/onc/onc_utils_unittest.cc
@@ -49,5 +49,55 @@ TEST(ONCDecrypterTest, LoadEncryptedOnc) {
actual_decrypted_onc.get()));
}
+namespace {
+
+const char* kLoginId = "hans";
+const char* kLoginEmail = "hans@my.domain.com";
+
+class StringSubstitutionStub : public StringSubstitution {
+ public:
+ StringSubstitutionStub() {}
+ virtual bool GetSubstitute(std::string placeholder,
+ std::string* substitute) const {
+ if (placeholder == substitutes::kLoginIDField)
+ *substitute = kLoginId;
+ else if (placeholder == substitutes::kEmailField)
+ *substitute = kLoginEmail;
+ else
+ return false;
+ return true;
+ }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StringSubstitutionStub);
+};
+
+} // namespace
+
+TEST(ONCStringExpansion, OpenVPN) {
+ scoped_ptr<base::DictionaryValue> vpn_onc =
+ test_utils::ReadTestDictionary("valid_openvpn.onc");
+
+ StringSubstitutionStub substitution;
+ ExpandStringsInOncObject(kNetworkConfigurationSignature, substitution,
+ vpn_onc.get());
+
+ std::string actual_expanded;
+ vpn_onc->GetString("VPN.OpenVPN.Username", &actual_expanded);
+ EXPECT_EQ(actual_expanded, std::string("abc ") + kLoginEmail + " def");
+}
+
+TEST(ONCStringExpansion, WiFi_EAP) {
+ scoped_ptr<base::DictionaryValue> wifi_onc =
+ test_utils::ReadTestDictionary("valid_wifi_clientcert.onc");
+
+ StringSubstitutionStub substitution;
+ ExpandStringsInOncObject(kNetworkConfigurationSignature, substitution,
+ wifi_onc.get());
+
+ std::string actual_expanded;
+ wifi_onc->GetString("WiFi.EAP.Identity", &actual_expanded);
+ EXPECT_EQ(actual_expanded, std::string("abc ") + kLoginId + "@my.domain.com");
+}
+
} // namespace onc
} // namespace chromeos
diff --git a/chromeos/test/data/network/shill_ethernet.json b/chromeos/test/data/network/shill_ethernet.json
index 7754932..19e0cc4 100644
--- a/chromeos/test/data/network/shill_ethernet.json
+++ b/chromeos/test/data/network/shill_ethernet.json
@@ -1,4 +1,3 @@
{ "GUID": "guid",
"Type": "ethernet",
- "Name": "name",
}
diff --git a/chromeos/test/data/network/shill_l2tpipsec_clientcert.json b/chromeos/test/data/network/shill_l2tpipsec_clientcert.json
new file mode 100644
index 0000000..3c47214
--- /dev/null
+++ b/chromeos/test/data/network/shill_l2tpipsec_clientcert.json
@@ -0,0 +1,10 @@
+{
+ "GUID": "guid",
+ "L2TPIPsec.Password": "some password",
+ "L2TPIPsec.User": "some username",
+ "Name": "MyL2TPVPN",
+ "Provider.Host": "some.host.org",
+ "Provider.Type": "l2tpipsec",
+ "SaveCredentials": true,
+ "Type": "vpn",
+}
diff --git a/chromeos/test/data/network/shill_openvpn.json b/chromeos/test/data/network/shill_openvpn.json
index 08650df..2468863 100644
--- a/chromeos/test/data/network/shill_openvpn.json
+++ b/chromeos/test/data/network/shill_openvpn.json
@@ -6,7 +6,7 @@
"Provider.Type": "openvpn",
"Provider.Host": "vpn.my.domain.com",
"OpenVPN.AuthRetry": "interact",
- "OpenVPN.User": "some username",
+ "OpenVPN.User": "abc ${LOGIN_EMAIL} def",
"OpenVPN.Password": "some password",
"OpenVPN.StaticChallenge": "Please enter token OTP",
"OpenVPN.CompLZO": "true",
diff --git a/chromeos/test/data/network/shill_openvpn_clientcert.json b/chromeos/test/data/network/shill_openvpn_clientcert.json
new file mode 100644
index 0000000..7210401
--- /dev/null
+++ b/chromeos/test/data/network/shill_openvpn_clientcert.json
@@ -0,0 +1,13 @@
+{
+ "GUID": "{84391467-dd8b-4c66-9b52-860583038351}",
+ "Name": "TestOpenVPN",
+ "OpenVPN.CACertNSS": "{126ea985-9ece-4250-8a32-6badf52a99e5}",
+ "OpenVPN.Password": "********",
+ "OpenVPN.Port": "1234",
+ "OpenVPN.Proto": "udp",
+ "OpenVPN.User": "hans",
+ "Provider.Host": "terminus.muc",
+ "Provider.Type": "openvpn",
+ "SaveCredentials": true,
+ "Type": "vpn",
+}
diff --git a/chromeos/test/data/network/shill_wifi_clientcert.json b/chromeos/test/data/network/shill_wifi_clientcert.json
new file mode 100644
index 0000000..5936934
--- /dev/null
+++ b/chromeos/test/data/network/shill_wifi_clientcert.json
@@ -0,0 +1,10 @@
+{
+ "EAP.EAP": "TLS",
+ "EAP.Identity": "abc ${LOGIN_ID}@my.domain.com",
+ "EAP.UseSystemCAs": true,
+ "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+ "SSID": "SomeWifi-XY",
+ "SaveCredentials": true,
+ "Security": "802_1x",
+ "Type": "wifi"
+}
diff --git a/chromeos/test/data/network/shill_wifi_clientref.json b/chromeos/test/data/network/shill_wifi_clientref.json
new file mode 100644
index 0000000..d7cca33
--- /dev/null
+++ b/chromeos/test/data/network/shill_wifi_clientref.json
@@ -0,0 +1,10 @@
+{
+ "EAP.EAP": "TLS",
+ "EAP.Identity": "${LOGIN_ID}@my.domain.com",
+ "EAP.UseSystemCAs": true,
+ "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+ "SSID": "SomeWifi-XY",
+ "SaveCredentials": true,
+ "Security": "802_1x",
+ "Type": "wifi"
+}
diff --git a/chromeos/test/data/network/shill_wifi_psk.json b/chromeos/test/data/network/shill_wifi_psk.json
new file mode 100644
index 0000000..572c4ac
--- /dev/null
+++ b/chromeos/test/data/network/shill_wifi_psk.json
@@ -0,0 +1,9 @@
+{
+ "AutoConnect": true,
+ "GUID": "{64c4f86b-cf6a-4e4a-8eff-456def}",
+ "Passphrase": "some passphrase",
+ "SSID": "OpenWrt",
+ "Security": "psk",
+ "Type": "wifi",
+ "WiFi.HiddenSSID": false
+}
diff --git a/chromeos/test/data/network/valid_l2tpipsec_clientcert.onc b/chromeos/test/data/network/valid_l2tpipsec_clientcert.onc
new file mode 100644
index 0000000..6f20b18
--- /dev/null
+++ b/chromeos/test/data/network/valid_l2tpipsec_clientcert.onc
@@ -0,0 +1,31 @@
+{ "GUID": "guid",
+ "Type": "VPN",
+ "Name": "MyL2TPVPN",
+ "VPN": {
+ "Type": "L2TP-IPsec",
+ "Host": "some.host.org",
+ "IPsec": {
+ "AuthenticationType": "Cert",
+ "ClientCertType": "Pattern",
+ "ClientCertPattern": {
+ "EnrollmentURI": [ "my.enrollment.url" ],
+ "IssuerCARef": [
+ "def",
+ "abc"
+ ],
+ "Issuer": {
+ "CommonName": "common_name",
+ "Locality": "locality",
+ "Organization": "organization",
+ "OrganizationalUnit": "unit"
+ }
+ },
+ "IKEVersion": 1,
+ "SaveCredentials": true
+ },
+ "L2TP": {
+ "Username": "some username",
+ "Password": "some password"
+ }
+ }
+}
diff --git a/chromeos/test/data/network/valid_openvpn.onc b/chromeos/test/data/network/valid_openvpn.onc
index 2e0daca..ce80409 100644
--- a/chromeos/test/data/network/valid_openvpn.onc
+++ b/chromeos/test/data/network/valid_openvpn.onc
@@ -25,7 +25,7 @@
"StaticChallenge": "Please enter token OTP",
"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": "some username",
+ "Username": "abc ${LOGIN_EMAIL} def",
}
}
}
diff --git a/chromeos/test/data/network/valid_openvpn_clientcert.onc b/chromeos/test/data/network/valid_openvpn_clientcert.onc
new file mode 100644
index 0000000..0a09327
--- /dev/null
+++ b/chromeos/test/data/network/valid_openvpn_clientcert.onc
@@ -0,0 +1,35 @@
+{
+ "GUID": "{84391467-dd8b-4c66-9b52-860583038351}",
+ "Name": "TestOpenVPN",
+ "ProxySettings": {
+ "Type": "Direct"
+ },
+ "Type": "VPN",
+ "VPN": {
+ "Host": "terminus.muc",
+ "OpenVPN": {
+ "ClientCertPattern": {
+ "EnrollmentURI": [ "my.enrollment.url" ],
+ "IssuerCARef": [
+ "def",
+ "abc"
+ ],
+ "Subject": {
+ "CommonName": "common_name",
+ "Locality": "locality",
+ "Organization": "organization",
+ "OrganizationalUnit": "unit"
+ }
+ },
+ "ClientCertType": "Pattern",
+ "Password": "********",
+ "Port": 1234,
+ "Proto": "udp",
+ "Recommended": [ "Username", "Password" ],
+ "SaveCredentials": true,
+ "ServerCARef": "{126ea985-9ece-4250-8a32-6badf52a99e5}",
+ "Username": "hans"
+ },
+ "Type": "OpenVPN"
+ }
+}
diff --git a/chromeos/test/data/network/valid_wifi_clientcert.onc b/chromeos/test/data/network/valid_wifi_clientcert.onc
new file mode 100644
index 0000000..c246a39
--- /dev/null
+++ b/chromeos/test/data/network/valid_wifi_clientcert.onc
@@ -0,0 +1,29 @@
+{
+ "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+ "Type": "WiFi",
+ "Name": "SomeWifi-XY",
+ "WiFi": {
+ "SSID": "SomeWifi-XY",
+ "Security": "WPA-EAP",
+ "Recommended": [ "AutoConnect" ],
+ "EAP": {
+ "Outer": "EAP-TLS",
+ "Identity": "abc ${LOGIN_ID}@my.domain.com",
+ "UseSystemCAs": true,
+ "ClientCertType": "Pattern",
+ "ClientCertPattern": {
+ "IssuerCARef": [
+ "{58ac1967-a0e7-49e9-be68-123abc}",
+ "{42cb13cd-140c-4941-9fb6-456def}"
+ ],
+ "EnrollmentURI": [ "chrome-extension://delkjfjibodjclmdijflfnimdmgdagfk/generate-cert.html" ]
+ },
+ "Recommended": [ "Identity" ],
+ "SaveCredentials": true
+ }
+ },
+ "ProxySettings": {
+ "Type": "PAC",
+ "PAC": "https://proxycfg.my.domain.com/proxy.dat"
+ }
+}
diff --git a/chromeos/test/data/network/valid_wifi_clientref.onc b/chromeos/test/data/network/valid_wifi_clientref.onc
new file mode 100644
index 0000000..259ff76
--- /dev/null
+++ b/chromeos/test/data/network/valid_wifi_clientref.onc
@@ -0,0 +1,23 @@
+{
+ "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
+ "Type": "WiFi",
+ "Name": "SomeWifi-XY",
+ "WiFi": {
+ "SSID": "SomeWifi-XY",
+ "Security": "WPA-EAP",
+ "Recommended": [ "AutoConnect" ],
+ "EAP": {
+ "Outer": "EAP-TLS",
+ "Identity": "${LOGIN_ID}@my.domain.com",
+ "UseSystemCAs": true,
+ "ClientCertType": "Ref",
+ "ClientCertRef": "{58ac1967-a0e7-49e9-be68-123abc}",
+ "Recommended": [ "Identity" ],
+ "SaveCredentials": true
+ }
+ },
+ "ProxySettings": {
+ "Type": "PAC",
+ "PAC": "https://proxycfg.my.domain.com/proxy.dat"
+ }
+}
diff --git a/chromeos/test/data/network/valid_wifi_psk.onc b/chromeos/test/data/network/valid_wifi_psk.onc
new file mode 100644
index 0000000..bbcca3b
--- /dev/null
+++ b/chromeos/test/data/network/valid_wifi_psk.onc
@@ -0,0 +1,33 @@
+{
+ "GUID": "{64c4f86b-cf6a-4e4a-8eff-456def}",
+ "Name": "OpenWrt",
+ "ProxySettings": {
+ "Manual": {
+ "FTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "HTTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "SOCKS": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ },
+ "SecureHTTPProxy": {
+ "Host": "192.168.2.1",
+ "Port": 8889
+ }
+ },
+ "Type": "Manual"
+ },
+ "Type": "WiFi",
+ "WiFi": {
+ "AutoConnect": true,
+ "HiddenSSID": false,
+ "Passphrase": "some passphrase",
+ "SSID": "OpenWrt",
+ "Security": "WPA-PSK"
+ }
+}