onc_utils.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/net/onc_utils.h"
6
7#include "base/values.h"
8#include "chrome/browser/chromeos/cros/network_ui_data.h"
9#include "chrome/browser/chromeos/proxy_config_service_impl.h"
10#include "chrome/browser/prefs/proxy_config_dictionary.h"
11#include "chromeos/network/onc/onc_signature.h"
12#include "chromeos/network/onc/onc_utils.h"
13#include "googleurl/src/gurl.h"
14#include "net/proxy/proxy_server.h"
15
16namespace chromeos {
17namespace onc {
18
19namespace {
20
21net::ProxyServer ConvertOncProxyLocationToHostPort(
22    net::ProxyServer::Scheme default_proxy_scheme,
23    const base::DictionaryValue& onc_proxy_location) {
24  std::string host;
25  onc_proxy_location.GetStringWithoutPathExpansion(onc::proxy::kHost, &host);
26  // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>].
27  net::ProxyServer proxy_server =
28      net::ProxyServer::FromURI(host, default_proxy_scheme);
29  int port = 0;
30  onc_proxy_location.GetIntegerWithoutPathExpansion(onc::proxy::kPort, &port);
31
32  // Replace the port parsed from |host| by the provided |port|.
33  return net::ProxyServer(
34      proxy_server.scheme(),
35      net::HostPortPair(proxy_server.host_port_pair().host(),
36                        static_cast<uint16>(port)));
37}
38
39void AppendProxyServerForScheme(
40    const base::DictionaryValue& onc_manual,
41    const std::string& onc_scheme,
42    std::string* spec) {
43  const base::DictionaryValue* onc_proxy_location = NULL;
44  if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme,
45                                                    &onc_proxy_location)) {
46    return;
47  }
48
49  net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP;
50  std::string url_scheme;
51  if (onc_scheme == proxy::kFtp) {
52    url_scheme = "ftp";
53  } else if (onc_scheme == proxy::kHttp) {
54    url_scheme = "http";
55  } else if (onc_scheme == proxy::kHttps) {
56    url_scheme = "https";
57  } else if (onc_scheme == proxy::kSocks) {
58    default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4;
59    url_scheme = "socks";
60  } else {
61    NOTREACHED();
62  }
63
64  net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort(
65      default_proxy_scheme, *onc_proxy_location);
66
67  ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
68      url_scheme, proxy_server, spec);
69}
70
71net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules(
72    const base::ListValue& onc_exclude_domains) {
73  net::ProxyBypassRules rules;
74  for (base::ListValue::const_iterator it = onc_exclude_domains.begin();
75       it != onc_exclude_domains.end(); ++it) {
76    std::string rule;
77    (*it)->GetAsString(&rule);
78    rules.AddRuleFromString(rule);
79  }
80  return rules;
81}
82
83}  // namespace
84
85scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig(
86    const base::DictionaryValue& onc_proxy_settings) {
87  std::string type;
88  onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kType, &type);
89  scoped_ptr<DictionaryValue> proxy_dict;
90
91  if (type == proxy::kDirect) {
92    proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
93  } else if (type == proxy::kWPAD) {
94    proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
95  } else if (type == proxy::kPAC) {
96    std::string pac_url;
97    onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kPAC, &pac_url);
98    GURL url(pac_url);
99    DCHECK(url.is_valid())
100        << "PAC field is invalid for this ProxySettings.Type";
101    proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
102                                                            false));
103  } else if (type == proxy::kManual) {
104    const base::DictionaryValue* manual_dict = NULL;
105    onc_proxy_settings.GetDictionaryWithoutPathExpansion(proxy::kManual,
106                                                         &manual_dict);
107    std::string manual_spec;
108    AppendProxyServerForScheme(*manual_dict, proxy::kFtp, &manual_spec);
109    AppendProxyServerForScheme(*manual_dict, proxy::kHttp, &manual_spec);
110    AppendProxyServerForScheme(*manual_dict, proxy::kSocks, &manual_spec);
111    AppendProxyServerForScheme(*manual_dict, proxy::kHttps, &manual_spec);
112
113    const base::ListValue* exclude_domains = NULL;
114    net::ProxyBypassRules bypass_rules;
115    if (onc_proxy_settings.GetListWithoutPathExpansion(proxy::kExcludeDomains,
116                                                       &exclude_domains)) {
117      bypass_rules.AssignFrom(
118          ConvertOncExcludeDomainsToBypassRules(*exclude_domains));
119    }
120    proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
121        manual_spec, bypass_rules.ToString()));
122  } else {
123    NOTREACHED();
124  }
125  return proxy_dict.Pass();
126}
127
128namespace {
129
130void TranslateClientCertType(const std::string& client_cert_type,
131                             NetworkUIData* ui_data) {
132  ClientCertType type;
133  if (client_cert_type == certificate::kNone) {
134    type = CLIENT_CERT_TYPE_NONE;
135  } else if (client_cert_type == certificate::kRef) {
136    type = CLIENT_CERT_TYPE_REF;
137  } else if (client_cert_type == certificate::kPattern) {
138    type = CLIENT_CERT_TYPE_PATTERN;
139  } else {
140    type = CLIENT_CERT_TYPE_NONE;
141    NOTREACHED();
142  }
143
144  ui_data->set_certificate_type(type);
145}
146
147void TranslateCertificatePattern(const base::DictionaryValue& onc_object,
148                                 NetworkUIData* ui_data) {
149  CertificatePattern pattern;
150  bool success = pattern.CopyFromDictionary(onc_object);
151  DCHECK(success);
152  ui_data->set_certificate_pattern(pattern);
153}
154
155void TranslateEAP(const base::DictionaryValue& eap,
156                  NetworkUIData* ui_data) {
157  std::string client_cert_type;
158  if (eap.GetStringWithoutPathExpansion(eap::kClientCertType,
159                                        &client_cert_type)) {
160    TranslateClientCertType(client_cert_type, ui_data);
161  }
162}
163
164void TranslateIPsec(const base::DictionaryValue& ipsec,
165                    NetworkUIData* ui_data) {
166  std::string client_cert_type;
167  if (ipsec.GetStringWithoutPathExpansion(vpn::kClientCertType,
168                                          &client_cert_type)) {
169    TranslateClientCertType(client_cert_type, ui_data);
170  }
171}
172
173void TranslateOpenVPN(const base::DictionaryValue& openvpn,
174                      NetworkUIData* ui_data) {
175  std::string client_cert_type;
176  if (openvpn.GetStringWithoutPathExpansion(vpn::kClientCertType,
177                                            &client_cert_type)) {
178    TranslateClientCertType(client_cert_type, ui_data);
179  }
180}
181
182void TranslateONCHierarchy(const OncValueSignature& signature,
183                           const base::DictionaryValue& onc_object,
184                           NetworkUIData* ui_data) {
185  if (&signature == &kCertificatePatternSignature)
186    TranslateCertificatePattern(onc_object, ui_data);
187  else if (&signature == &kEAPSignature)
188    TranslateEAP(onc_object, ui_data);
189  else if (&signature == &kIPsecSignature)
190    TranslateIPsec(onc_object, ui_data);
191  else if (&signature == &kOpenVPNSignature)
192    TranslateOpenVPN(onc_object, ui_data);
193
194  // Recurse into nested objects.
195  for (base::DictionaryValue::Iterator it(onc_object); it.HasNext();
196       it.Advance()) {
197    const base::DictionaryValue* inner_object;
198    if (!it.value().GetAsDictionary(&inner_object))
199      continue;
200
201    const OncFieldSignature* field_signature =
202        GetFieldSignature(signature, it.key());
203
204    TranslateONCHierarchy(*field_signature->value_signature, *inner_object,
205                          ui_data);
206  }
207}
208
209}  // namespace
210
211scoped_ptr<NetworkUIData> CreateUIData(
212    ONCSource onc_source,
213    const base::DictionaryValue& onc_network) {
214  scoped_ptr<NetworkUIData> ui_data(new NetworkUIData());
215  TranslateONCHierarchy(kNetworkConfigurationSignature, onc_network,
216                        ui_data.get());
217
218  ui_data->set_onc_source(onc_source);
219
220  return ui_data.Pass();
221}
222
223}  // namespace onc
224}  // namespace chromeos
225