1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/components/sync_wifi/network_type_conversions.h"
6 
7 #include "base/strings/string_number_conversions.h"
8 #include "chromeos/network/network_handler.h"
9 #include "chromeos/network/network_state.h"
10 #include "chromeos/network/network_state_handler.h"
11 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
12 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
13 
14 namespace chromeos {
15 
16 namespace sync_wifi {
17 
DecodeHexString(const std::string & base_16)18 std::string DecodeHexString(const std::string& base_16) {
19   std::string decoded;
20   DCHECK_EQ(base_16.size() % 2, 0u) << "Must be a multiple of 2";
21   decoded.reserve(base_16.size() / 2);
22 
23   std::vector<uint8_t> v;
24   if (!base::HexStringToBytes(base_16, &v)) {
25     NOTREACHED();
26   }
27   decoded.assign(reinterpret_cast<const char*>(&v[0]), v.size());
28   return decoded;
29 }
30 
SecurityTypeStringFromMojo(const network_config::mojom::SecurityType & security_type)31 std::string SecurityTypeStringFromMojo(
32     const network_config::mojom::SecurityType& security_type) {
33   switch (security_type) {
34     case network_config::mojom::SecurityType::kWpaPsk:
35       return shill::kSecurityPsk;
36     case network_config::mojom::SecurityType::kWepPsk:
37       return shill::kSecurityWep;
38     default:
39       // Only PSK and WEP secured networks are supported by sync.
40       return "";
41   }
42 }
43 
SecurityTypeStringFromProto(const sync_pb::WifiConfigurationSpecifics_SecurityType & security_type)44 std::string SecurityTypeStringFromProto(
45     const sync_pb::WifiConfigurationSpecifics_SecurityType& security_type) {
46   switch (security_type) {
47     case sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_PSK:
48       return shill::kSecurityPsk;
49     case sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_WEP:
50       return shill::kSecurityWep;
51     default:
52       // Only PSK and WEP secured networks are supported by sync.
53       NOTREACHED();
54       return "";
55   }
56 }
57 
SecurityTypeProtoFromMojo(const network_config::mojom::SecurityType & security_type)58 sync_pb::WifiConfigurationSpecifics_SecurityType SecurityTypeProtoFromMojo(
59     const network_config::mojom::SecurityType& security_type) {
60   switch (security_type) {
61     case network_config::mojom::SecurityType::kWpaPsk:
62       return sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_PSK;
63     case network_config::mojom::SecurityType::kWepPsk:
64       return sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_WEP;
65     default:
66       // Only PSK and WEP secured networks are supported by sync.
67       NOTREACHED();
68       return sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_NONE;
69   }
70 }
71 
72 sync_pb::WifiConfigurationSpecifics_AutomaticallyConnectOption
AutomaticallyConnectProtoFromMojo(const network_config::mojom::ManagedBooleanPtr & auto_connect)73 AutomaticallyConnectProtoFromMojo(
74     const network_config::mojom::ManagedBooleanPtr& auto_connect) {
75   if (!auto_connect) {
76     return sync_pb::WifiConfigurationSpecifics::
77         AUTOMATICALLY_CONNECT_UNSPECIFIED;
78   }
79 
80   if (auto_connect->active_value) {
81     return sync_pb::WifiConfigurationSpecifics::AUTOMATICALLY_CONNECT_ENABLED;
82   }
83 
84   return sync_pb::WifiConfigurationSpecifics::AUTOMATICALLY_CONNECT_DISABLED;
85 }
86 
IsPreferredProtoFromMojo(const network_config::mojom::ManagedInt32Ptr & is_preferred)87 sync_pb::WifiConfigurationSpecifics_IsPreferredOption IsPreferredProtoFromMojo(
88     const network_config::mojom::ManagedInt32Ptr& is_preferred) {
89   if (!is_preferred) {
90     return sync_pb::WifiConfigurationSpecifics::IS_PREFERRED_UNSPECIFIED;
91   }
92 
93   if (is_preferred->active_value == 1) {
94     return sync_pb::WifiConfigurationSpecifics::IS_PREFERRED_ENABLED;
95   }
96 
97   return sync_pb::WifiConfigurationSpecifics::IS_PREFERRED_DISABLED;
98 }
99 
100 sync_pb::WifiConfigurationSpecifics_ProxyConfiguration_ProxyOption
ProxyOptionProtoFromMojo(const network_config::mojom::ManagedProxySettingsPtr & proxy_settings,bool is_unspecified)101 ProxyOptionProtoFromMojo(
102     const network_config::mojom::ManagedProxySettingsPtr& proxy_settings,
103     bool is_unspecified) {
104   if (!proxy_settings || is_unspecified) {
105     return sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
106         PROXY_OPTION_UNSPECIFIED;
107   }
108 
109   if (proxy_settings->type->active_value == ::onc::proxy::kPAC) {
110     return sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
111         PROXY_OPTION_AUTOMATIC;
112   }
113 
114   if (proxy_settings->type->active_value == ::onc::proxy::kWPAD) {
115     return sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
116         PROXY_OPTION_AUTODISCOVERY;
117   }
118 
119   if (proxy_settings->type->active_value == ::onc::proxy::kManual) {
120     return sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
121         PROXY_OPTION_MANUAL;
122   }
123 
124   return sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
125       PROXY_OPTION_DISABLED;
126 }
127 
128 sync_pb::WifiConfigurationSpecifics_ProxyConfiguration
ProxyConfigurationProtoFromMojo(const network_config::mojom::ManagedProxySettingsPtr & proxy_settings,bool is_unspecified)129 ProxyConfigurationProtoFromMojo(
130     const network_config::mojom::ManagedProxySettingsPtr& proxy_settings,
131     bool is_unspecified) {
132   sync_pb::WifiConfigurationSpecifics_ProxyConfiguration proto;
133   proto.set_proxy_option(
134       ProxyOptionProtoFromMojo(proxy_settings, is_unspecified));
135 
136   if (proto.proxy_option() ==
137       sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
138           PROXY_OPTION_AUTOMATIC) {
139     if (proxy_settings->pac) {
140       proto.set_autoconfiguration_url(proxy_settings->pac->active_value);
141     }
142   } else if (proto.proxy_option() ==
143              sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
144                  PROXY_OPTION_MANUAL) {
145     sync_pb::
146         WifiConfigurationSpecifics_ProxyConfiguration_ManualProxyConfiguration*
147             manual_settings = proto.mutable_manual_proxy_configuration();
148 
149     if (proxy_settings->manual->http_proxy) {
150       manual_settings->set_http_proxy_url(
151           proxy_settings->manual->http_proxy->host->active_value);
152       manual_settings->set_http_proxy_port(
153           proxy_settings->manual->http_proxy->port->active_value);
154     }
155 
156     if (proxy_settings->manual->secure_http_proxy) {
157       manual_settings->set_secure_http_proxy_url(
158           proxy_settings->manual->secure_http_proxy->host->active_value);
159       manual_settings->set_secure_http_proxy_port(
160           proxy_settings->manual->secure_http_proxy->port->active_value);
161     }
162 
163     if (proxy_settings->manual->socks) {
164       manual_settings->set_socks_host_url(
165           proxy_settings->manual->socks->host->active_value);
166       manual_settings->set_socks_host_port(
167           proxy_settings->manual->socks->port->active_value);
168     }
169 
170     if (proxy_settings->exclude_domains) {
171       for (const std::string& domain :
172            proxy_settings->exclude_domains->active_value) {
173         manual_settings->add_excluded_domains(domain);
174       }
175     }
176   }
177 
178   return proto;
179 }
180 
MojoSecurityTypeFromProto(const sync_pb::WifiConfigurationSpecifics_SecurityType & security_type)181 network_config::mojom::SecurityType MojoSecurityTypeFromProto(
182     const sync_pb::WifiConfigurationSpecifics_SecurityType& security_type) {
183   switch (security_type) {
184     case sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_PSK:
185       return network_config::mojom::SecurityType::kWpaPsk;
186     case sync_pb::WifiConfigurationSpecifics::SECURITY_TYPE_WEP:
187       return network_config::mojom::SecurityType::kWepPsk;
188     default:
189       // Only PSK and WEP secured networks are supported by sync.
190       NOTREACHED();
191       return network_config::mojom::SecurityType::kNone;
192   }
193 }
194 
MojoProxySettingsFromProto(const sync_pb::WifiConfigurationSpecifics_ProxyConfiguration & proxy_proto)195 network_config::mojom::ProxySettingsPtr MojoProxySettingsFromProto(
196     const sync_pb::WifiConfigurationSpecifics_ProxyConfiguration& proxy_proto) {
197   auto proxy_settings = network_config::mojom::ProxySettings::New();
198   switch (proxy_proto.proxy_option()) {
199     case sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
200         PROXY_OPTION_AUTOMATIC:
201       proxy_settings->type = ::onc::proxy::kPAC;
202       proxy_settings->pac = proxy_proto.autoconfiguration_url();
203       break;
204     case sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
205         PROXY_OPTION_AUTODISCOVERY:
206       proxy_settings->type = ::onc::proxy::kWPAD;
207       break;
208     case sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
209         PROXY_OPTION_MANUAL: {
210       auto manual_settings = network_config::mojom::ManualProxySettings::New();
211       auto synced_manual_configuration =
212           proxy_proto.manual_proxy_configuration();
213       proxy_settings->type = ::onc::proxy::kManual;
214 
215       manual_settings->http_proxy = network_config::mojom::ProxyLocation::New();
216       manual_settings->http_proxy->host =
217           synced_manual_configuration.http_proxy_url();
218       manual_settings->http_proxy->port =
219           synced_manual_configuration.http_proxy_port();
220 
221       manual_settings->secure_http_proxy =
222           network_config::mojom::ProxyLocation::New();
223       manual_settings->secure_http_proxy->host =
224           synced_manual_configuration.secure_http_proxy_url();
225       manual_settings->secure_http_proxy->port =
226           synced_manual_configuration.secure_http_proxy_port();
227 
228       manual_settings->socks = network_config::mojom::ProxyLocation::New();
229       manual_settings->socks->host =
230           synced_manual_configuration.socks_host_url();
231       manual_settings->socks->port =
232           synced_manual_configuration.socks_host_port();
233 
234       proxy_settings->manual = std::move(manual_settings);
235 
236       std::vector<std::string> exclude_domains;
237       for (const std::string& domain :
238            synced_manual_configuration.excluded_domains()) {
239         exclude_domains.push_back(domain);
240       }
241       proxy_settings->exclude_domains = std::move(exclude_domains);
242       break;
243     }
244     case sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
245         PROXY_OPTION_DISABLED:
246       proxy_settings->type = ::onc::proxy::kDirect;
247       break;
248     case sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
249         PROXY_OPTION_UNSPECIFIED:
250       break;
251   }
252 
253   return proxy_settings;
254 }
255 
MojoNetworkConfigFromProto(const sync_pb::WifiConfigurationSpecifics & specifics)256 network_config::mojom::ConfigPropertiesPtr MojoNetworkConfigFromProto(
257     const sync_pb::WifiConfigurationSpecifics& specifics) {
258   auto config = network_config::mojom::ConfigProperties::New();
259   auto wifi = network_config::mojom::WiFiConfigProperties::New();
260 
261   wifi->ssid = DecodeHexString(specifics.hex_ssid());
262   wifi->security = MojoSecurityTypeFromProto(specifics.security_type());
263   wifi->passphrase = specifics.passphrase();
264 
265   config->type_config =
266       network_config::mojom::NetworkTypeConfigProperties::NewWifi(
267           std::move(wifi));
268 
269   config->auto_connect = network_config::mojom::AutoConnectConfig::New(
270       specifics.automatically_connect() ==
271       sync_pb::WifiConfigurationSpecifics::AUTOMATICALLY_CONNECT_ENABLED);
272 
273   config->priority = network_config::mojom::PriorityConfig::New(
274       specifics.is_preferred() ==
275               sync_pb::WifiConfigurationSpecifics::IS_PREFERRED_ENABLED
276           ? 1
277           : 0);
278 
279   if (specifics.has_metered() &&
280       specifics.metered() !=
281           sync_pb::
282               WifiConfigurationSpecifics_MeteredOption_METERED_OPTION_UNSPECIFIED &&
283       specifics.metered() !=
284           sync_pb::
285               WifiConfigurationSpecifics_MeteredOption_METERED_OPTION_AUTO) {
286     config->metered = network_config::mojom::MeteredConfig::New(
287         specifics.metered() ==
288         sync_pb::WifiConfigurationSpecifics_MeteredOption_METERED_OPTION_YES);
289   }
290 
291   // For backwards compatibility, any available custom nameservers are still
292   // applied when the dns_option is not set.
293   if (specifics.dns_option() ==
294           sync_pb::WifiConfigurationSpecifics_DnsOption_DNS_OPTION_CUSTOM ||
295       (specifics.dns_option() ==
296            sync_pb::
297                WifiConfigurationSpecifics_DnsOption_DNS_OPTION_UNSPECIFIED &&
298        specifics.custom_dns().size())) {
299     auto ip_config = network_config::mojom::IPConfigProperties::New();
300     std::vector<std::string> custom_dns;
301     for (const std::string& nameserver : specifics.custom_dns()) {
302       custom_dns.push_back(nameserver);
303     }
304     ip_config->name_servers = std::move(custom_dns);
305     config->static_ip_config = std::move(ip_config);
306     config->name_servers_config_type = onc::network_config::kIPConfigTypeStatic;
307   } else if (specifics.dns_option() ==
308              sync_pb::
309                  WifiConfigurationSpecifics_DnsOption_DNS_OPTION_DEFAULT_DHCP) {
310     config->name_servers_config_type = onc::network_config::kIPConfigTypeDHCP;
311   }
312 
313   if (specifics.has_proxy_configuration() &&
314       specifics.proxy_configuration().proxy_option() !=
315           sync_pb::WifiConfigurationSpecifics_ProxyConfiguration::
316               PROXY_OPTION_UNSPECIFIED) {
317     config->proxy_settings =
318         MojoProxySettingsFromProto(specifics.proxy_configuration());
319   }
320 
321   return config;
322 }
323 
NetworkStateFromNetworkIdentifier(const NetworkIdentifier & id)324 const NetworkState* NetworkStateFromNetworkIdentifier(
325     const NetworkIdentifier& id) {
326   NetworkStateHandler::NetworkStateList networks;
327   NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
328       NetworkTypePattern::WiFi(), /*configured_only=*/true,
329       /*visibleOnly=*/false, /*limit=*/0, &networks);
330   for (const NetworkState* network : networks) {
331     if (NetworkIdentifier::FromNetworkState(network) == id) {
332       return network;
333     }
334   }
335   return nullptr;
336 }
337 
338 }  // namespace sync_wifi
339 
340 }  // namespace chromeos
341