Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: chrome/browser/chromeos/cros/onc_network_parser.cc

Issue 11578052: Replace OncNetworkParser by the new ONC translator. (Closed) Base URL: http://git.chromium.org/chromium/src.git@extend_onc_to_shill
Patch Set: Rebased. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/cros/onc_network_parser.h"
6
7 #include <keyhi.h>
8 #include <pk11pub.h>
9
10 #include "base/base64.h"
11 #include "base/json/json_string_value_serializer.h"
12 #include "base/json/json_writer.h" // for debug output only.
13 #include "base/stringprintf.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/cros/certificate_pattern.h"
16 #include "chrome/browser/chromeos/cros/cros_library.h"
17 #include "chrome/browser/chromeos/cros/native_network_constants.h"
18 #include "chrome/browser/chromeos/cros/native_network_parser.h"
19 #include "chrome/browser/chromeos/cros/network_library.h"
20 #include "chrome/browser/chromeos/login/user_manager.h"
21 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
22 #include "chrome/browser/prefs/proxy_config_dictionary.h"
23 #include "chrome/common/net/x509_certificate_model.h"
24 #include "chromeos/network/onc/onc_certificate_importer.h"
25 #include "chromeos/network/onc/onc_constants.h"
26 #include "chromeos/network/onc/onc_signature.h"
27 #include "chromeos/network/onc/onc_validator.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "crypto/encryptor.h"
30 #include "crypto/hmac.h"
31 #include "crypto/scoped_nss_types.h"
32 #include "crypto/symmetric_key.h"
33 #include "grit/generated_resources.h"
34 #include "net/base/crypto_module.h"
35 #include "net/base/net_errors.h"
36 #include "net/base/nss_cert_database.h"
37 #include "net/base/pem_tokenizer.h"
38 #include "net/base/x509_certificate.h"
39 #include "net/proxy/proxy_bypass_rules.h"
40 #include "third_party/cros_system_api/dbus/service_constants.h"
41 #include "ui/base/l10n/l10n_util.h"
42
43 namespace chromeos {
44
45 // Local constants.
46 namespace {
47
48 // The PEM block header used for DER certificates
49 const char kCertificateHeader[] = "CERTIFICATE";
50 // This is an older PEM marker for DER certificates.
51 const char kX509CertificateHeader[] = "X509 CERTIFICATE";
52
53 const base::Value::Type TYPE_BOOLEAN = base::Value::TYPE_BOOLEAN;
54 const base::Value::Type TYPE_DICTIONARY = base::Value::TYPE_DICTIONARY;
55 const base::Value::Type TYPE_INTEGER = base::Value::TYPE_INTEGER;
56 const base::Value::Type TYPE_LIST = base::Value::TYPE_LIST;
57 const base::Value::Type TYPE_STRING = base::Value::TYPE_STRING;
58
59 // Only used currently to keep NetworkParser superclass happy.
60 EnumMapper<PropertyIndex>::Pair network_configuration_table[] = {
61 { "GUID", PROPERTY_INDEX_GUID }
62 };
63
64 OncValueSignature network_configuration_signature[] = {
65 { onc::kGUID, PROPERTY_INDEX_GUID, TYPE_STRING },
66 { onc::kProxySettings, PROPERTY_INDEX_ONC_PROXY_SETTINGS, TYPE_DICTIONARY },
67 { onc::kName, PROPERTY_INDEX_NAME, TYPE_STRING },
68 { onc::kRemove, PROPERTY_INDEX_ONC_REMOVE, TYPE_BOOLEAN },
69 { onc::kType, PROPERTY_INDEX_TYPE, TYPE_STRING },
70 { onc::kEthernet, PROPERTY_INDEX_ONC_ETHERNET, TYPE_DICTIONARY },
71 { onc::kWiFi, PROPERTY_INDEX_ONC_WIFI, TYPE_DICTIONARY },
72 { onc::kVPN, PROPERTY_INDEX_ONC_VPN, TYPE_DICTIONARY },
73 { NULL }
74 };
75
76 OncValueSignature ethernet_signature[] = {
77 { onc::ethernet::kAuthentication, PROPERTY_INDEX_AUTHENTICATION,
78 TYPE_STRING },
79 { onc::ethernet::kEAP, PROPERTY_INDEX_EAP, TYPE_DICTIONARY },
80 { NULL }
81 };
82
83 OncValueSignature wifi_signature[] = {
84 { onc::wifi::kAutoConnect, PROPERTY_INDEX_AUTO_CONNECT, TYPE_BOOLEAN },
85 { onc::wifi::kEAP, PROPERTY_INDEX_EAP, TYPE_DICTIONARY },
86 { onc::wifi::kHiddenSSID, PROPERTY_INDEX_WIFI_HIDDEN_SSID, TYPE_BOOLEAN },
87 { onc::wifi::kPassphrase, PROPERTY_INDEX_PASSPHRASE, TYPE_STRING },
88 { onc::wifi::kSecurity, PROPERTY_INDEX_SECURITY, TYPE_STRING },
89 { onc::wifi::kSSID, PROPERTY_INDEX_SSID, TYPE_STRING },
90 { NULL }
91 };
92
93 OncValueSignature issuer_subject_pattern_signature[] = {
94 { onc::certificate::kCommonName,
95 PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_COMMON_NAME, TYPE_STRING },
96 { onc::certificate::kLocality,
97 PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_LOCALITY, TYPE_STRING },
98 { onc::certificate::kOrganization,
99 PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATION, TYPE_STRING },
100 { onc::certificate::kOrganizationalUnit,
101 PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATIONAL_UNIT,
102 TYPE_STRING },
103 };
104
105 OncValueSignature certificate_pattern_signature[] = {
106 { onc::certificate::kIssuerCARef,
107 PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ISSUER_CA_REF, TYPE_LIST },
108 { onc::certificate::kIssuer,
109 PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ISSUER, TYPE_DICTIONARY },
110 { onc::certificate::kSubject,
111 PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_SUBJECT, TYPE_DICTIONARY },
112 { onc::certificate::kEnrollmentURI,
113 PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ENROLLMENT_URI, TYPE_LIST },
114 };
115
116 OncValueSignature eap_signature[] = {
117 { onc::eap::kAnonymousIdentity, PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY,
118 TYPE_STRING },
119 { onc::eap::kClientCertPattern, PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN,
120 TYPE_DICTIONARY },
121 { onc::eap::kClientCertRef, PROPERTY_INDEX_ONC_CLIENT_CERT_REF, TYPE_STRING },
122 { onc::eap::kClientCertType, PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE,
123 TYPE_STRING },
124 { onc::eap::kIdentity, PROPERTY_INDEX_EAP_IDENTITY, TYPE_STRING },
125 { onc::eap::kInner, PROPERTY_INDEX_EAP_PHASE_2_AUTH, TYPE_STRING },
126 { onc::eap::kOuter, PROPERTY_INDEX_EAP_METHOD, TYPE_STRING },
127 { onc::eap::kPassword, PROPERTY_INDEX_EAP_PASSWORD, TYPE_STRING },
128 { onc::eap::kServerCARef, PROPERTY_INDEX_EAP_CA_CERT_NSS, TYPE_STRING },
129 { onc::eap::kUseSystemCAs, PROPERTY_INDEX_EAP_USE_SYSTEM_CAS, TYPE_BOOLEAN },
130 { onc::eap::kSaveCredentials, PROPERTY_INDEX_SAVE_CREDENTIALS, TYPE_BOOLEAN },
131 { NULL }
132 };
133
134 OncValueSignature vpn_signature[] = {
135 { onc::vpn::kHost, PROPERTY_INDEX_PROVIDER_HOST, TYPE_STRING },
136 { onc::vpn::kIPsec, PROPERTY_INDEX_ONC_IPSEC, TYPE_DICTIONARY },
137 { onc::vpn::kL2TP, PROPERTY_INDEX_ONC_L2TP, TYPE_DICTIONARY },
138 { onc::vpn::kOpenVPN, PROPERTY_INDEX_ONC_OPENVPN, TYPE_DICTIONARY },
139 { onc::vpn::kType, PROPERTY_INDEX_PROVIDER_TYPE, TYPE_STRING },
140 { NULL }
141 };
142
143 OncValueSignature ipsec_signature[] = {
144 { onc::vpn::kAuthenticationType, PROPERTY_INDEX_IPSEC_AUTHENTICATIONTYPE,
145 TYPE_STRING },
146 { onc::vpn::kGroup, PROPERTY_INDEX_L2TPIPSEC_GROUP_NAME, TYPE_STRING },
147 { onc::vpn::kIKEVersion, PROPERTY_INDEX_IPSEC_IKEVERSION, TYPE_INTEGER },
148 { onc::vpn::kClientCertPattern, PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN,
149 TYPE_DICTIONARY },
150 { onc::vpn::kClientCertRef, PROPERTY_INDEX_ONC_CLIENT_CERT_REF, TYPE_STRING },
151 { onc::vpn::kClientCertType, PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE,
152 TYPE_STRING },
153 // Note: EAP and XAUTH not yet supported.
154 { onc::vpn::kPSK, PROPERTY_INDEX_L2TPIPSEC_PSK, TYPE_STRING },
155 { onc::vpn::kSaveCredentials, PROPERTY_INDEX_SAVE_CREDENTIALS, TYPE_BOOLEAN },
156 { onc::vpn::kServerCARef, PROPERTY_INDEX_L2TPIPSEC_CA_CERT_NSS, TYPE_STRING },
157 { NULL }
158 };
159
160 OncValueSignature l2tp_signature[] = {
161 { onc::vpn::kPassword, PROPERTY_INDEX_L2TPIPSEC_PASSWORD, TYPE_STRING },
162 { onc::vpn::kSaveCredentials, PROPERTY_INDEX_SAVE_CREDENTIALS, TYPE_BOOLEAN },
163 { onc::vpn::kUsername, PROPERTY_INDEX_L2TPIPSEC_USER, TYPE_STRING },
164 { NULL }
165 };
166
167 OncValueSignature openvpn_signature[] = {
168 { onc::vpn::kAuth, PROPERTY_INDEX_OPEN_VPN_AUTH, TYPE_STRING },
169 { onc::vpn::kAuthRetry, PROPERTY_INDEX_OPEN_VPN_AUTHRETRY, TYPE_STRING },
170 { onc::vpn::kAuthNoCache, PROPERTY_INDEX_OPEN_VPN_AUTHNOCACHE, TYPE_BOOLEAN },
171 { onc::vpn::kCipher, PROPERTY_INDEX_OPEN_VPN_CIPHER, TYPE_STRING },
172 { onc::vpn::kClientCertPattern, PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN,
173 TYPE_DICTIONARY },
174 { onc::vpn::kClientCertRef, PROPERTY_INDEX_ONC_CLIENT_CERT_REF, TYPE_STRING },
175 { onc::vpn::kClientCertType, PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE,
176 TYPE_STRING },
177 { onc::vpn::kCompLZO, PROPERTY_INDEX_OPEN_VPN_COMPLZO, TYPE_STRING },
178 { onc::vpn::kCompNoAdapt, PROPERTY_INDEX_OPEN_VPN_COMPNOADAPT, TYPE_BOOLEAN },
179 { onc::vpn::kKeyDirection, PROPERTY_INDEX_OPEN_VPN_KEYDIRECTION,
180 TYPE_STRING },
181 { onc::vpn::kNsCertType, PROPERTY_INDEX_OPEN_VPN_NSCERTTYPE, TYPE_STRING },
182 { onc::vpn::kPassword, PROPERTY_INDEX_OPEN_VPN_PASSWORD, TYPE_STRING },
183 { onc::vpn::kPort, PROPERTY_INDEX_OPEN_VPN_PORT, TYPE_INTEGER },
184 { onc::vpn::kProto, PROPERTY_INDEX_OPEN_VPN_PROTO, TYPE_STRING },
185 { onc::vpn::kPushPeerInfo, PROPERTY_INDEX_OPEN_VPN_PUSHPEERINFO,
186 TYPE_BOOLEAN },
187 { onc::vpn::kRemoteCertEKU, PROPERTY_INDEX_OPEN_VPN_REMOTECERTEKU,
188 TYPE_STRING },
189 { onc::vpn::kRemoteCertKU, PROPERTY_INDEX_OPEN_VPN_REMOTECERTKU, TYPE_LIST },
190 { onc::vpn::kRemoteCertTLS, PROPERTY_INDEX_OPEN_VPN_REMOTECERTTLS,
191 TYPE_STRING },
192 { onc::vpn::kRenegSec, PROPERTY_INDEX_OPEN_VPN_RENEGSEC, TYPE_INTEGER },
193 { onc::vpn::kSaveCredentials, PROPERTY_INDEX_SAVE_CREDENTIALS, TYPE_BOOLEAN },
194 { onc::vpn::kServerCARef, PROPERTY_INDEX_OPEN_VPN_CACERT, TYPE_STRING },
195 { onc::vpn::kServerCertRef, PROPERTY_INDEX_OPEN_VPN_CERT, TYPE_STRING },
196 { onc::vpn::kServerPollTimeout, PROPERTY_INDEX_OPEN_VPN_SERVERPOLLTIMEOUT,
197 TYPE_INTEGER },
198 { onc::vpn::kShaper, PROPERTY_INDEX_OPEN_VPN_SHAPER, TYPE_INTEGER },
199 { onc::vpn::kStaticChallenge, PROPERTY_INDEX_OPEN_VPN_STATICCHALLENGE,
200 TYPE_STRING },
201 { onc::vpn::kTLSAuthContents, PROPERTY_INDEX_OPEN_VPN_TLSAUTHCONTENTS,
202 TYPE_STRING },
203 { onc::vpn::kTLSRemote, PROPERTY_INDEX_OPEN_VPN_TLSREMOTE, TYPE_STRING },
204 { onc::vpn::kUsername, PROPERTY_INDEX_OPEN_VPN_USER, TYPE_STRING },
205 { NULL }
206 };
207
208 OncValueSignature proxy_settings_signature[] = {
209 { onc::proxy::kType, PROPERTY_INDEX_ONC_PROXY_TYPE, TYPE_STRING },
210 { onc::proxy::kPAC, PROPERTY_INDEX_ONC_PROXY_PAC, TYPE_STRING },
211 { onc::proxy::kManual, PROPERTY_INDEX_ONC_PROXY_MANUAL, TYPE_DICTIONARY },
212 { onc::proxy::kExcludeDomains, PROPERTY_INDEX_ONC_PROXY_EXCLUDE_DOMAINS,
213 TYPE_LIST },
214 { NULL },
215 };
216
217 OncValueSignature proxy_manual_signature[] = {
218 { onc::proxy::kHttp, PROPERTY_INDEX_ONC_PROXY_HTTP, TYPE_DICTIONARY },
219 { onc::proxy::kHttps, PROPERTY_INDEX_ONC_PROXY_HTTPS, TYPE_DICTIONARY },
220 { onc::proxy::kFtp, PROPERTY_INDEX_ONC_PROXY_FTP, TYPE_DICTIONARY },
221 { onc::proxy::kSocks, PROPERTY_INDEX_ONC_PROXY_SOCKS, TYPE_DICTIONARY },
222 { NULL },
223 };
224
225 // Serve the singleton mapper instance.
226 const EnumMapper<PropertyIndex>* get_onc_mapper() {
227 CR_DEFINE_STATIC_LOCAL(const EnumMapper<PropertyIndex>, mapper,
228 (network_configuration_table,
229 arraysize(network_configuration_table),
230 PROPERTY_INDEX_UNKNOWN));
231 return &mapper;
232 }
233
234 ConnectionType ParseNetworkType(const std::string& type) {
235 static EnumMapper<ConnectionType>::Pair table[] = {
236 { "Ethernet", TYPE_ETHERNET },
237 { "WiFi", TYPE_WIFI },
238 { "VPN", TYPE_VPN },
239 };
240 CR_DEFINE_STATIC_LOCAL(EnumMapper<ConnectionType>, parser,
241 (table, arraysize(table), TYPE_UNKNOWN));
242 return parser.Get(type);
243 }
244
245 std::string GetStringValue(const base::Value& value) {
246 std::string string_value;
247 value.GetAsString(&string_value);
248 return string_value;
249 }
250
251 const bool GetBooleanValue(const base::Value& value) {
252 bool bool_value = false;
253 value.GetAsBoolean(&bool_value);
254 return bool_value;
255 }
256
257 std::string ConvertValueToString(const base::Value& value) {
258 std::string value_json;
259 base::JSONWriter::Write(&value, &value_json);
260 return value_json;
261 }
262
263 bool GetAsListOfStrings(const base::Value& value,
264 std::vector<std::string>* result) {
265 const base::ListValue* list = NULL;
266 if (!value.GetAsList(&list))
267 return false;
268 result->clear();
269 result->reserve(list->GetSize());
270 for (size_t i = 0; i < list->GetSize(); i++) {
271 std::string item;
272 if (!list->GetString(i, &item))
273 return false;
274 result->push_back(item);
275 }
276 return true;
277 }
278
279 } // namespace
280
281 // -------------------- OncNetworkParser --------------------
282
283 OncNetworkParser::OncNetworkParser(const base::ListValue& network_configs,
284 onc::ONCSource onc_source)
285 : NetworkParser(get_onc_mapper()),
286 onc_source_(onc_source),
287 network_configs_(network_configs.DeepCopy()) {
288 }
289
290 OncNetworkParser::OncNetworkParser()
291 : NetworkParser(get_onc_mapper()),
292 network_configs_(NULL) {
293 }
294
295 OncNetworkParser::~OncNetworkParser() {
296 }
297
298 // static
299 const EnumMapper<PropertyIndex>* OncNetworkParser::property_mapper() {
300 return get_onc_mapper();
301 }
302
303 int OncNetworkParser::GetNetworkConfigsSize() const {
304 return network_configs_ ? network_configs_->GetSize() : 0;
305 }
306
307 const base::DictionaryValue* OncNetworkParser::GetNetworkConfig(int n) {
308 CHECK(network_configs_);
309 CHECK(static_cast<size_t>(n) < network_configs_->GetSize());
310 CHECK_GE(n, 0);
311 base::DictionaryValue* info = NULL;
312 if (!network_configs_->GetDictionary(n, &info)) {
313 parse_error_ = l10n_util::GetStringUTF8(
314 IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED);
315 return NULL;
316 }
317
318 return info;
319 }
320
321 Network* OncNetworkParser::ParseNetwork(int n, bool* marked_for_removal) {
322 const base::DictionaryValue* info = GetNetworkConfig(n);
323 if (!info)
324 return NULL;
325
326 if (VLOG_IS_ON(2)) {
327 std::string network_json;
328 base::JSONWriter::WriteWithOptions(static_cast<const base::Value*>(info),
329 base::JSONWriter::OPTIONS_PRETTY_PRINT,
330 &network_json);
331 VLOG(2) << "Parsing network at index " << n << ": " << network_json;
332 }
333
334 if (marked_for_removal) {
335 if (!info->GetBoolean(onc::kRemove, marked_for_removal))
336 *marked_for_removal = false;
337 }
338
339 return CreateNetworkFromInfo(std::string(), *info);
340 }
341
342 Network* OncNetworkParser::CreateNetworkFromInfo(
343 const std::string& service_path,
344 const DictionaryValue& info) {
345 ConnectionType type = ParseTypeFromDictionary(info);
346 if (type == TYPE_UNKNOWN) { // Return NULL if cannot parse network type.
347 parse_error_ = l10n_util::GetStringUTF8(
348 IDS_NETWORK_CONFIG_ERROR_NETWORK_TYPE_MISSING);
349 return NULL;
350 }
351 scoped_ptr<Network> network(CreateNewNetwork(type, service_path));
352
353 // Initialize ONC source.
354 NetworkUIData ui_data = network->ui_data();
355 ui_data.set_onc_source(onc_source_);
356 network->set_ui_data(ui_data);
357
358 // Parse all properties recursively.
359 if (!ParseNestedObject(network.get(),
360 onc::kNetworkConfiguration,
361 static_cast<const base::Value&>(info),
362 network_configuration_signature,
363 ParseNetworkConfigurationValue)) {
364 LOG(WARNING) << "Network " << network->name() << " failed to parse.";
365 if (parse_error_.empty())
366 parse_error_ = l10n_util::GetStringUTF8(
367 IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED);
368 return NULL;
369 }
370
371 // Update the UI data property in shill.
372 std::string ui_data_json;
373 base::DictionaryValue ui_data_dict;
374 network->ui_data().FillDictionary(&ui_data_dict);
375 base::JSONWriter::Write(&ui_data_dict, &ui_data_json);
376 base::StringValue ui_data_string_value(ui_data_json);
377 network->UpdatePropertyMap(PROPERTY_INDEX_UI_DATA, &ui_data_string_value);
378
379 if (VLOG_IS_ON(2)) {
380 VLOG(2) << "Created Network '" << network->name()
381 << "' from info. Path:" << service_path
382 << " Type:" << ConnectionTypeToString(type);
383 }
384
385 return network.release();
386 }
387
388 bool OncNetworkParser::ParseNestedObject(Network* network,
389 const std::string& onc_type,
390 const base::Value& value,
391 OncValueSignature* signature,
392 ParserPointer parser) {
393 bool any_errors = false;
394 if (!value.IsType(base::Value::TYPE_DICTIONARY)) {
395 VLOG(1) << network->name() << ": expected object of type " << onc_type;
396 parse_error_ = l10n_util::GetStringUTF8(
397 IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED);
398 return false;
399 }
400 VLOG(2) << "Parsing nested object of type " << onc_type;
401 const DictionaryValue* dict = NULL;
402 value.GetAsDictionary(&dict);
403 for (DictionaryValue::key_iterator iter = dict->begin_keys();
404 iter != dict->end_keys(); ++iter) {
405 const std::string& key = *iter;
406
407 // Recommended keys are only of interest to the UI code and the UI reads it
408 // directly from the ONC blob.
409 if (key == onc::kRecommended)
410 continue;
411
412 const base::Value* inner_value = NULL;
413 dict->GetWithoutPathExpansion(key, &inner_value);
414 CHECK(inner_value != NULL);
415 int field_index;
416 for (field_index = 0; signature[field_index].field != NULL; ++field_index) {
417 if (key == signature[field_index].field)
418 break;
419 }
420 if (signature[field_index].field == NULL) {
421 LOG(WARNING) << network->name() << ": unexpected field: "
422 << key << ", in type: " << onc_type;
423 continue;
424 }
425 if (!inner_value->IsType(signature[field_index].type)) {
426 LOG(ERROR) << network->name() << ": field with wrong type: " << key
427 << ", actual type: " << inner_value->GetType()
428 << ", expected type: " << signature[field_index].type;
429 any_errors = true;
430 continue;
431 }
432 PropertyIndex index = signature[field_index].index;
433 // We need to UpdatePropertyMap now since parser might want to
434 // change the mapped value.
435 network->UpdatePropertyMap(index, inner_value);
436 if (!parser(this, index, *inner_value, network)) {
437 LOG(ERROR) << network->name() << ": field in " << onc_type
438 << " not parsed: " << key;
439 any_errors = true;
440 continue;
441 }
442 if (VLOG_IS_ON(2)) {
443 std::string value_json;
444 base::JSONWriter::WriteWithOptions(inner_value,
445 base::JSONWriter::OPTIONS_PRETTY_PRINT,
446 &value_json);
447 VLOG(2) << network->name() << ": Successfully parsed [" << key
448 << "(" << index << ")] = " << value_json;
449 }
450 }
451 if (any_errors) {
452 parse_error_ = l10n_util::GetStringUTF8(
453 IDS_NETWORK_CONFIG_ERROR_NETWORK_PROP_DICT_MALFORMED);
454 }
455 return !any_errors;
456 }
457
458 // static
459 std::string OncNetworkParser::GetUserExpandedValue(
460 const base::Value& value,
461 onc::ONCSource source) {
462 std::string string_value;
463 if (!value.GetAsString(&string_value))
464 return string_value;
465
466 // If running unit test, just return the original value.
467 if (!content::BrowserThread::IsMessageLoopValid(content::BrowserThread::UI))
468 return string_value;
469
470 if (source != onc::ONC_SOURCE_USER_POLICY &&
471 source != onc::ONC_SOURCE_USER_IMPORT) {
472 return string_value;
473 }
474
475 if (!UserManager::Get()->IsUserLoggedIn())
476 return string_value;
477
478 const User* logged_in_user = UserManager::Get()->GetLoggedInUser();
479 ReplaceSubstringsAfterOffset(&string_value, 0,
480 onc::substitutes::kLoginIDField,
481 logged_in_user->GetAccountName(false));
482 ReplaceSubstringsAfterOffset(&string_value, 0,
483 onc::substitutes::kEmailField,
484 logged_in_user->email());
485 return string_value;
486 }
487
488 Network* OncNetworkParser::CreateNewNetwork(
489 ConnectionType type, const std::string& service_path) {
490 Network* network = NetworkParser::CreateNewNetwork(type, service_path);
491 if (network) {
492 if (type == TYPE_ETHERNET)
493 network->SetNetworkParser(new OncEthernetNetworkParser());
494 else if (type == TYPE_WIFI)
495 network->SetNetworkParser(new OncWifiNetworkParser());
496 else if (type == TYPE_VPN)
497 network->SetNetworkParser(new OncVirtualNetworkParser());
498 }
499 return network;
500 }
501
502 ConnectionType OncNetworkParser::ParseType(const std::string& type) {
503 return ParseNetworkType(type);
504 }
505
506 ConnectionType OncNetworkParser::ParseTypeFromDictionary(
507 const DictionaryValue& info) {
508 return ParseType(GetTypeFromDictionary(info));
509 }
510
511 std::string OncNetworkParser::GetTypeFromDictionary(
512 const base::DictionaryValue& info) {
513 std::string type_string;
514 info.GetString("Type", &type_string);
515 return type_string;
516 }
517
518 std::string OncNetworkParser::GetGuidFromDictionary(
519 const base::DictionaryValue& info) {
520 std::string guid_string;
521 info.GetString("GUID", &guid_string);
522 return guid_string;
523 }
524
525 // static
526 bool OncNetworkParser::ParseNetworkConfigurationValue(
527 OncNetworkParser* parser,
528 PropertyIndex index,
529 const base::Value& value,
530 Network* network) {
531 switch (index) {
532 case PROPERTY_INDEX_ONC_ETHERNET:
533 return parser->ParseNestedObject(network, "Ethernet", value,
534 ethernet_signature, OncEthernetNetworkParser::ParseEthernetValue);
535 case PROPERTY_INDEX_ONC_WIFI:
536 return parser->ParseNestedObject(network,
537 onc::kWiFi,
538 value,
539 wifi_signature,
540 OncWifiNetworkParser::ParseWifiValue);
541 case PROPERTY_INDEX_ONC_VPN: {
542 if (!CheckNetworkType(network, TYPE_VPN, onc::kVPN))
543 return false;
544 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
545 // Got the "VPN" field. Immediately store the VPN.Type field
546 // value so that we can properly validate fields in the VPN
547 // object based on the type.
548 const DictionaryValue* dict = NULL;
549 CHECK(value.GetAsDictionary(&dict));
550 std::string provider_type_string;
551 if (!dict->GetString("Type", &provider_type_string)) {
552 VLOG(1) << network->name() << ": VPN.Type is missing";
553 return false;
554 }
555 ProviderType provider_type =
556 OncVirtualNetworkParser::ParseProviderType(provider_type_string);
557 virtual_network->set_provider_type(provider_type);
558 return parser->ParseNestedObject(network,
559 onc::kVPN,
560 value,
561 vpn_signature,
562 OncVirtualNetworkParser::ParseVPNValue);
563 }
564 case PROPERTY_INDEX_ONC_PROXY_SETTINGS:
565 return ProcessProxySettings(parser, value, network);
566 case PROPERTY_INDEX_ONC_REMOVE:
567 // Removal is handled in ParseNetwork, and so is ignored here.
568 return true;
569 case PROPERTY_INDEX_TYPE: {
570 // Update property with native value for type.
571 std::string str =
572 NativeNetworkParser::network_type_mapper()->GetKey(network->type());
573 base::StringValue val(str);
574 network->UpdatePropertyMap(PROPERTY_INDEX_TYPE, &val);
575 return true;
576 }
577 case PROPERTY_INDEX_GUID:
578 // Fall back to generic parser.
579 return parser->ParseValue(index, value, network);
580 case PROPERTY_INDEX_NAME:
581 // shill doesn't allow setting name for non-VPN networks.
582 if (network->type() != TYPE_VPN) {
583 network->UpdatePropertyMap(PROPERTY_INDEX_NAME, NULL);
584 return true;
585 }
586
587 // Fall back to generic parser.
588 return parser->ParseValue(index, value, network);
589 default:
590 break;
591 }
592 return false;
593 }
594
595 // static
596 bool OncNetworkParser::CheckNetworkType(Network* network,
597 ConnectionType expected,
598 const std::string& onc_type) {
599 if (expected != network->type()) {
600 LOG(WARNING) << network->name() << ": "
601 << onc_type << " field unexpected for this type network";
602 return false;
603 }
604 return true;
605 }
606
607 // static
608 ClientCertType OncNetworkParser::ParseClientCertType(
609 const std::string& type) {
610 static EnumMapper<ClientCertType>::Pair table[] = {
611 { onc::certificate::kNone, CLIENT_CERT_TYPE_NONE },
612 { onc::certificate::kRef, CLIENT_CERT_TYPE_REF },
613 { onc::certificate::kPattern, CLIENT_CERT_TYPE_PATTERN },
614 };
615 CR_DEFINE_STATIC_LOCAL(EnumMapper<ClientCertType>, parser,
616 (table, arraysize(table), CLIENT_CERT_TYPE_NONE));
617 return parser.Get(type);
618 }
619
620 // static
621 std::string OncNetworkParser::GetPkcs11IdFromCertGuid(const std::string& guid) {
622 // We have to look up the GUID to find the PKCS#11 ID that is needed.
623 net::CertificateList cert_list;
624 onc::CertificateImporter::ListCertsWithNickname(guid, &cert_list);
625 DCHECK_EQ(1ul, cert_list.size());
626 if (cert_list.size() == 1)
627 return x509_certificate_model::GetPkcs11Id(cert_list[0]->os_cert_handle());
628 return std::string();
629 }
630
631 // static
632 bool OncNetworkParser::ProcessProxySettings(OncNetworkParser* parser,
633 const base::Value& value,
634 Network* network) {
635 VLOG(1) << "Processing ProxySettings: " << ConvertValueToString(value);
636
637 // Got "ProxySettings" field. Immediately store the ProxySettings.Type
638 // field value so that we can properly validate fields in the ProxySettings
639 // object based on the type.
640 const DictionaryValue* dict = NULL;
641 CHECK(value.GetAsDictionary(&dict));
642 std::string proxy_type_string;
643 if (!dict->GetString(onc::proxy::kType, &proxy_type_string)) {
644 VLOG(1) << network->name() << ": ProxySettings.Type is missing";
645 return false;
646 }
647 Network::ProxyOncConfig& config = network->proxy_onc_config();
648 config.type = ParseProxyType(proxy_type_string);
649
650 // For Direct and WPAD, all other fields are ignored.
651 // Otherwise, recursively parse the children of ProxySettings dictionary.
652 if (config.type != PROXY_ONC_DIRECT && config.type != PROXY_ONC_WPAD) {
653 if (!parser->ParseNestedObject(network,
654 onc::kProxySettings,
655 value,
656 proxy_settings_signature,
657 OncNetworkParser::ParseProxySettingsValue)) {
658 return false;
659 }
660 }
661
662 // Create ProxyConfigDictionary based on parsed values.
663 scoped_ptr<DictionaryValue> proxy_dict;
664 switch (config.type) {
665 case PROXY_ONC_DIRECT: {
666 proxy_dict.reset(ProxyConfigDictionary::CreateDirect());
667 break;
668 }
669 case PROXY_ONC_WPAD: {
670 proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect());
671 break;
672 }
673 case PROXY_ONC_PAC: {
674 if (config.pac_url.empty()) {
675 VLOG(1) << "PAC field is required for this ProxySettings.Type";
676 return false;
677 }
678 GURL url(config.pac_url);
679 if (!url.is_valid()) {
680 VLOG(1) << "PAC field is invalid for this ProxySettings.Type";
681 return false;
682 }
683 proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(),
684 false));
685 break;
686 }
687 case PROXY_ONC_MANUAL: {
688 if (config.manual_spec.empty()) {
689 VLOG(1) << "Manual field is required for this ProxySettings.Type";
690 return false;
691 }
692 proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers(
693 config.manual_spec, config.bypass_rules));
694 break;
695 }
696 default:
697 break;
698 }
699 if (!proxy_dict.get())
700 return false;
701
702 // Serialize ProxyConfigDictionary into a string.
703 std::string proxy_dict_str = ConvertValueToString(*proxy_dict.get());
704
705 // Add ProxyConfig property to property map so that it will be updated in
706 // shill in NetworkLibraryImplCros::CallConfigureService after all parsing
707 // has completed.
708 base::StringValue val(proxy_dict_str);
709 network->UpdatePropertyMap(PROPERTY_INDEX_PROXY_CONFIG, &val);
710
711 // If |network| is currently being connected to or it exists in memory,
712 // shill will fire PropertyChanged notification in ConfigureService,
713 // chromeos::ProxyConfigServiceImpl will get OnNetworkChanged notification
714 // and, if necessary, activate |proxy_dict_str| on network stack and reflect
715 // it in UI via "Change proxy settings" button.
716 network->set_proxy_config(proxy_dict_str);
717 VLOG(1) << "Parsed ProxyConfig: " << network->proxy_config();
718
719 return true;
720 }
721
722 // static
723 bool OncNetworkParser::ParseProxySettingsValue(OncNetworkParser* parser,
724 PropertyIndex index,
725 const base::Value& value,
726 Network* network) {
727 Network::ProxyOncConfig& config = network->proxy_onc_config();
728 switch (index) {
729 case PROPERTY_INDEX_ONC_PROXY_PAC: {
730 if (config.type == PROXY_ONC_PAC) {
731 // This is a string specifying the url.
732 config.pac_url = GetStringValue(value);
733 return true;
734 }
735 break;
736 }
737 case PROPERTY_INDEX_ONC_PROXY_MANUAL: {
738 if (config.type == PROXY_ONC_MANUAL) {
739 // Recursively parse the children of Manual dictionary.
740 return parser->ParseNestedObject(network,
741 onc::proxy::kManual,
742 value,
743 proxy_manual_signature,
744 ParseProxyManualValue);
745 }
746 break;
747 }
748 case PROPERTY_INDEX_ONC_PROXY_EXCLUDE_DOMAINS: {
749 if (config.type == PROXY_ONC_MANUAL) {
750 // This is a list of rules, parse them into ProxyBypassRules.
751 net::ProxyBypassRules rules;
752 const ListValue* list = NULL;
753 CHECK(value.GetAsList(&list));
754 for (size_t i = 0; i < list->GetSize(); ++i) {
755 std::string val;
756 if (!list->GetString(i, &val))
757 return false;
758 rules.AddRuleFromString(val);
759 }
760 config.bypass_rules = rules.ToString();
761 return true;
762 }
763 break;
764 }
765 default:
766 break;
767 }
768 return true;
769 }
770
771 // static
772 ProxyOncType OncNetworkParser::ParseProxyType(const std::string& type) {
773 static EnumMapper<ProxyOncType>::Pair table[] = {
774 { onc::proxy::kDirect, PROXY_ONC_DIRECT },
775 { onc::proxy::kWPAD, PROXY_ONC_WPAD },
776 { onc::proxy::kPAC, PROXY_ONC_PAC },
777 { onc::proxy::kManual, PROXY_ONC_MANUAL },
778 };
779
780 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProxyOncType>, parser,
781 (table, arraysize(table), PROXY_ONC_MAX));
782
783 return parser.Get(type);
784 }
785
786 // static
787 bool OncNetworkParser::ParseProxyManualValue(OncNetworkParser* parser,
788 PropertyIndex index,
789 const base::Value& value,
790 Network* network) {
791 switch (index) {
792 case PROPERTY_INDEX_ONC_PROXY_HTTP:
793 return ParseProxyServer(index, value, "http", network);
794 break;
795 case PROPERTY_INDEX_ONC_PROXY_HTTPS:
796 return ParseProxyServer(index, value, "https", network);
797 break;
798 case PROPERTY_INDEX_ONC_PROXY_FTP:
799 return ParseProxyServer(index, value, "ftp", network);
800 break;
801 case PROPERTY_INDEX_ONC_PROXY_SOCKS:
802 return ParseProxyServer(index, value, "socks", network);
803 break;
804 default:
805 break;
806 }
807 return false;
808 }
809
810 // static
811 bool OncNetworkParser::ParseProxyServer(int property_index,
812 const base::Value& value,
813 const std::string& scheme,
814 Network* network) {
815 // Parse the ProxyLocation dictionary that specifies the proxy server.
816 net::ProxyServer server = ParseProxyLocationValue(property_index, value);
817 if (!server.is_valid())
818 return false;
819
820 // Append proxy server info to manual spec string.
821 ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(scheme,
822 server, &network->proxy_onc_config().manual_spec);
823 return true;
824 }
825
826 // static
827 net::ProxyServer OncNetworkParser::ParseProxyLocationValue(
828 int property_index,
829 const base::Value& value) {
830 // Extract the values of Host and Port keys in ProxyLocation dictionary.
831 const DictionaryValue* dict = NULL;
832 CHECK(value.GetAsDictionary(&dict));
833 std::string host;
834 int port = 0;
835 if (!(dict->GetString(onc::proxy::kHost, &host) &&
836 dict->GetInteger(onc::proxy::kPort, &port))) {
837 return net::ProxyServer();
838 }
839
840 // Determine the scheme for the proxy server.
841 net::ProxyServer::Scheme scheme = net::ProxyServer::SCHEME_HTTP;
842 if (property_index == PROPERTY_INDEX_ONC_PROXY_SOCKS) {
843 scheme = StartsWithASCII(host, "socks5://", false) ?
844 net::ProxyServer::SCHEME_SOCKS5 : net::ProxyServer::SCHEME_SOCKS4;
845 }
846
847 // Process the Host and Port values into net::HostPortPair, and then
848 // net::ProxyServer for the specific scheme.
849 net::HostPortPair host_port(host, static_cast<uint16>(port));
850 return net::ProxyServer(scheme, host_port);
851 }
852
853 // static
854 bool OncNetworkParser::ParseClientCertPattern(OncNetworkParser* parser,
855 PropertyIndex index,
856 const base::Value& value,
857 Network* network) {
858 // Ignore certificate patterns for device policy ONC so that an unmanaged user
859 // won't have a certificate presented for them involuntarily.
860 if (parser->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY)
861 return false;
862
863 // Only WiFi and VPN have this type.
864 if (network->type() != TYPE_WIFI &&
865 network->type() != TYPE_VPN) {
866 LOG(WARNING) << "Tried to parse a ClientCertPattern from something "
867 << "that wasn't a WiFi or VPN network.";
868 return false;
869 }
870
871
872 switch (index) {
873 case PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ENROLLMENT_URI: {
874 std::vector<std::string> resulting_list;
875 if (!GetAsListOfStrings(value, &resulting_list))
876 return false;
877 CertificatePattern pattern = network->client_cert_pattern();
878 pattern.set_enrollment_uri_list(resulting_list);
879 network->set_client_cert_pattern(pattern);
880 return true;
881 }
882 case PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ISSUER_CA_REF: {
883 std::vector<std::string> resulting_list;
884 if (!GetAsListOfStrings(value, &resulting_list))
885 return false;
886 CertificatePattern pattern = network->client_cert_pattern();
887 pattern.set_issuer_ca_ref_list(resulting_list);
888 network->set_client_cert_pattern(pattern);
889 return true;
890 }
891 case PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_ISSUER:
892 return parser->ParseNestedObject(network,
893 onc::certificate::kIssuer,
894 value,
895 issuer_subject_pattern_signature,
896 ParseIssuerPattern);
897 case PROPERTY_INDEX_ONC_CERTIFICATE_PATTERN_SUBJECT:
898 return parser->ParseNestedObject(network,
899 onc::certificate::kSubject,
900 value,
901 issuer_subject_pattern_signature,
902 ParseSubjectPattern);
903 default:
904 break;
905 }
906 return false;
907 }
908
909 // static
910 bool OncNetworkParser::ParseIssuerPattern(OncNetworkParser* parser,
911 PropertyIndex index,
912 const base::Value& value,
913 Network* network) {
914 IssuerSubjectPattern pattern;
915 if (ParseIssuerSubjectPattern(&pattern, parser, index, value, network)) {
916 CertificatePattern cert_pattern = network->client_cert_pattern();
917 cert_pattern.set_issuer(pattern);
918 network->set_client_cert_pattern(cert_pattern);
919 return true;
920 }
921 return false;
922 }
923
924 // static
925 bool OncNetworkParser::ParseSubjectPattern(OncNetworkParser* parser,
926 PropertyIndex index,
927 const base::Value& value,
928 Network* network) {
929 IssuerSubjectPattern pattern;
930 if (ParseIssuerSubjectPattern(&pattern, parser, index, value, network)) {
931 CertificatePattern cert_pattern = network->client_cert_pattern();
932 cert_pattern.set_subject(pattern);
933 network->set_client_cert_pattern(cert_pattern);
934 return true;
935 }
936 return false;
937 }
938
939 // static
940 bool OncNetworkParser::ParseIssuerSubjectPattern(IssuerSubjectPattern* pattern,
941 OncNetworkParser* parser,
942 PropertyIndex index,
943 const base::Value& value,
944 Network* network) {
945 // Only WiFi and VPN have this type.
946 if (network->type() != TYPE_WIFI &&
947 network->type() != TYPE_VPN) {
948 LOG(WARNING) << "Tried to parse an IssuerSubjectPattern from something "
949 << "that wasn't a WiFi or VPN network.";
950 return false;
951 }
952 std::string value_str;
953 if (!value.GetAsString(&value_str))
954 return false;
955
956 bool result = false;
957 switch (index) {
958 case PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_COMMON_NAME:
959 pattern->set_common_name(value_str);
960 result = true;
961 break;
962 case PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_LOCALITY:
963 pattern->set_locality(value_str);
964 result = true;
965 break;
966 case PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATION:
967 pattern->set_organization(value_str);
968 result = true;
969 break;
970 case PROPERTY_INDEX_ISSUER_SUBJECT_PATTERN_ORGANIZATIONAL_UNIT:
971 pattern->set_organizational_unit(value_str);
972 result = true;
973 break;
974 default:
975 break;
976 }
977 return result;
978 }
979
980 // -------------------- OncEthernetNetworkParser --------------------
981
982 OncEthernetNetworkParser::OncEthernetNetworkParser() {}
983 OncEthernetNetworkParser::~OncEthernetNetworkParser() {}
984
985 bool OncEthernetNetworkParser::ParseEthernetValue(OncNetworkParser* parser,
986 PropertyIndex index,
987 const base::Value& value,
988 Network* network) {
989 if (!CheckNetworkType(network, TYPE_ETHERNET, "Ethernet"))
990 return false;
991 // EthernetNetwork* ethernet_network = static_cast<EthernetNetwork*>(network);
992 switch (index) {
993 case PROPERTY_INDEX_AUTHENTICATION:
994 // TODO(chocobo): Handle authentication.
995 return true;
996 case PROPERTY_INDEX_EAP:
997 // TODO(chocobo): Implement EAP authentication.
998 return true;
999 default:
1000 break;
1001 }
1002 return false;
1003 }
1004
1005 // -------------------- OncWirelessNetworkParser --------------------
1006
1007 OncWirelessNetworkParser::OncWirelessNetworkParser() {}
1008 OncWirelessNetworkParser::~OncWirelessNetworkParser() {}
1009
1010 // -------------------- OncWifiNetworkParser --------------------
1011
1012 OncWifiNetworkParser::OncWifiNetworkParser() {}
1013 OncWifiNetworkParser::~OncWifiNetworkParser() {}
1014
1015 // static
1016 bool OncWifiNetworkParser::ParseWifiValue(OncNetworkParser* parser,
1017 PropertyIndex index,
1018 const base::Value& value,
1019 Network* network) {
1020 if (!CheckNetworkType(network, TYPE_WIFI, "WiFi"))
1021 return false;
1022 WifiNetwork* wifi_network = static_cast<WifiNetwork*>(network);
1023 switch (index) {
1024 case PROPERTY_INDEX_SSID:
1025 wifi_network->SetName(GetStringValue(value));
1026 return true;
1027 case PROPERTY_INDEX_SECURITY: {
1028 ConnectionSecurity security = ParseSecurity(GetStringValue(value));
1029 wifi_network->set_encryption(security);
1030 // Also update property with native value for security.
1031 base::StringValue val(
1032 NativeNetworkParser::network_security_mapper()->GetKey(security));
1033 wifi_network->UpdatePropertyMap(index, &val);
1034 return true;
1035 }
1036 case PROPERTY_INDEX_PASSPHRASE:
1037 wifi_network->set_passphrase(GetStringValue(value));
1038 return true;
1039 case PROPERTY_INDEX_IDENTITY:
1040 wifi_network->set_identity(GetStringValue(value));
1041 return true;
1042 case PROPERTY_INDEX_EAP:
1043 parser->ParseNestedObject(wifi_network,
1044 onc::wifi::kEAP,
1045 value,
1046 eap_signature,
1047 ParseEAPValue);
1048 return true;
1049 case PROPERTY_INDEX_AUTO_CONNECT:
1050 network->set_auto_connect(GetBooleanValue(value));
1051 return true;
1052 case PROPERTY_INDEX_WIFI_HIDDEN_SSID:
1053 wifi_network->set_hidden_ssid(GetBooleanValue(value));
1054 return true;
1055 default:
1056 break;
1057 }
1058 return false;
1059 }
1060
1061 // static
1062 bool OncWifiNetworkParser::ParseEAPValue(OncNetworkParser* parser,
1063 PropertyIndex index,
1064 const base::Value& value,
1065 Network* network) {
1066 if (!CheckNetworkType(network, TYPE_WIFI, onc::wifi::kEAP))
1067 return false;
1068 WifiNetwork* wifi_network = static_cast<WifiNetwork*>(network);
1069 switch (index) {
1070 case PROPERTY_INDEX_EAP_IDENTITY: {
1071 const std::string expanded_identity(
1072 GetUserExpandedValue(value, parser->onc_source()));
1073 wifi_network->set_eap_identity(expanded_identity);
1074 const StringValue expanded_identity_value(expanded_identity);
1075 wifi_network->UpdatePropertyMap(index, &expanded_identity_value);
1076 return true;
1077 }
1078 case PROPERTY_INDEX_EAP_METHOD: {
1079 EAPMethod eap_method = ParseEAPMethod(GetStringValue(value));
1080 wifi_network->set_eap_method(eap_method);
1081 // Also update property with native value for EAP method.
1082 base::StringValue val(
1083 NativeNetworkParser::network_eap_method_mapper()->GetKey(eap_method));
1084 wifi_network->UpdatePropertyMap(index, &val);
1085 return true;
1086 }
1087 case PROPERTY_INDEX_EAP_PHASE_2_AUTH: {
1088 EAPPhase2Auth eap_phase_2_auth = ParseEAPPhase2Auth(
1089 GetStringValue(value));
1090 wifi_network->set_eap_phase_2_auth(eap_phase_2_auth);
1091 // Also update property with native value for EAP phase 2 auth.
1092 base::StringValue val(
1093 NativeNetworkParser::network_eap_auth_mapper()->GetKey(
1094 eap_phase_2_auth));
1095 wifi_network->UpdatePropertyMap(index, &val);
1096 return true;
1097 }
1098 case PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY: {
1099 const std::string expanded_identity(
1100 GetUserExpandedValue(value, parser->onc_source()));
1101 wifi_network->set_eap_anonymous_identity(expanded_identity);
1102 const StringValue expanded_identity_value(expanded_identity);
1103 wifi_network->UpdatePropertyMap(index, &expanded_identity_value);
1104 return true;
1105 }
1106 case PROPERTY_INDEX_EAP_CERT_ID:
1107 wifi_network->set_eap_client_cert_pkcs11_id(GetStringValue(value));
1108 return true;
1109 case PROPERTY_INDEX_EAP_CA_CERT_NSS:
1110 wifi_network->set_eap_server_ca_cert_nss_nickname(GetStringValue(value));
1111 return true;
1112 case PROPERTY_INDEX_EAP_USE_SYSTEM_CAS:
1113 wifi_network->set_eap_use_system_cas(GetBooleanValue(value));
1114 return true;
1115 case PROPERTY_INDEX_EAP_PASSWORD:
1116 wifi_network->set_eap_passphrase(GetStringValue(value));
1117 return true;
1118 case PROPERTY_INDEX_ONC_CLIENT_CERT_REF: {
1119 std::string cert_id = GetPkcs11IdFromCertGuid(GetStringValue(value));
1120 if (cert_id.empty())
1121 return false;
1122 wifi_network->set_eap_client_cert_pkcs11_id(cert_id);
1123 return true;
1124 }
1125 case PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN:
1126 return parser->ParseNestedObject(
1127 wifi_network,
1128 onc::eap::kClientCertPattern,
1129 value,
1130 certificate_pattern_signature,
1131 OncNetworkParser::ParseClientCertPattern);
1132 case PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE: {
1133 ClientCertType type = ParseClientCertType(GetStringValue(value));
1134 wifi_network->set_client_cert_type(type);
1135 return true;
1136 }
1137 case PROPERTY_INDEX_SAVE_CREDENTIALS:
1138 wifi_network->set_eap_save_credentials(GetBooleanValue(value));
1139 return true;
1140 default:
1141 break;
1142 }
1143 return false;
1144 }
1145
1146 // static
1147 ConnectionSecurity OncWifiNetworkParser::ParseSecurity(
1148 const std::string& security) {
1149 static EnumMapper<ConnectionSecurity>::Pair table[] = {
1150 { "None", SECURITY_NONE },
1151 { "WEP-PSK", SECURITY_WEP },
1152 { "WPA-PSK", SECURITY_PSK },
1153 { "WPA-EAP", SECURITY_8021X },
1154 };
1155 CR_DEFINE_STATIC_LOCAL(EnumMapper<ConnectionSecurity>, parser,
1156 (table, arraysize(table), SECURITY_UNKNOWN));
1157 return parser.Get(security);
1158 }
1159
1160 // static
1161 EAPMethod OncWifiNetworkParser::ParseEAPMethod(const std::string& method) {
1162 static EnumMapper<EAPMethod>::Pair table[] = {
1163 { "PEAP", EAP_METHOD_PEAP },
1164 { "EAP-TLS", EAP_METHOD_TLS },
1165 { "EAP-TTLS", EAP_METHOD_TTLS },
1166 { "LEAP", EAP_METHOD_LEAP },
1167 };
1168 CR_DEFINE_STATIC_LOCAL(EnumMapper<EAPMethod>, parser,
1169 (table, arraysize(table), EAP_METHOD_UNKNOWN));
1170 return parser.Get(method);
1171 }
1172
1173 // static
1174 EAPPhase2Auth OncWifiNetworkParser::ParseEAPPhase2Auth(
1175 const std::string& auth) {
1176 static EnumMapper<EAPPhase2Auth>::Pair table[] = {
1177 { "MD5", EAP_PHASE_2_AUTH_MD5 },
1178 { "MSCHAPV2", EAP_PHASE_2_AUTH_MSCHAPV2 },
1179 { "MSCHAP", EAP_PHASE_2_AUTH_MSCHAP },
1180 { "PAP", EAP_PHASE_2_AUTH_PAP },
1181 };
1182 CR_DEFINE_STATIC_LOCAL(EnumMapper<EAPPhase2Auth>, parser,
1183 (table, arraysize(table), EAP_PHASE_2_AUTH_AUTO));
1184 return parser.Get(auth);
1185 }
1186
1187 // -------------------- OncVirtualNetworkParser --------------------
1188
1189
1190 OncVirtualNetworkParser::OncVirtualNetworkParser() {}
1191 OncVirtualNetworkParser::~OncVirtualNetworkParser() {}
1192
1193 bool OncVirtualNetworkParser::UpdateNetworkFromInfo(
1194 const DictionaryValue& info,
1195 Network* network) {
1196 DCHECK_EQ(TYPE_VPN, network->type());
1197 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
1198 if (!OncNetworkParser::UpdateNetworkFromInfo(info, network))
1199 return false;
1200 VLOG(1) << "Updating VPN '" << virtual_network->name()
1201 << "': Server: " << virtual_network->server_hostname()
1202 << " Type: "
1203 << ProviderTypeToString(virtual_network->provider_type());
1204 return true;
1205 }
1206
1207 // static
1208 bool OncVirtualNetworkParser::ParseVPNValue(OncNetworkParser* parser,
1209 PropertyIndex index,
1210 const base::Value& value,
1211 Network* network) {
1212 if (!CheckNetworkType(network, TYPE_VPN, onc::kVPN))
1213 return false;
1214 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
1215 switch (index) {
1216 case PROPERTY_INDEX_PROVIDER_HOST: {
1217 base::StringValue empty_value("");
1218 virtual_network->set_server_hostname(GetStringValue(value));
1219 // Shill requires a domain property which is unused.
1220 network->UpdatePropertyMap(PROPERTY_INDEX_VPN_DOMAIN, &empty_value);
1221 return true;
1222 }
1223 case PROPERTY_INDEX_ONC_IPSEC:
1224 if (virtual_network->provider_type() != PROVIDER_TYPE_L2TP_IPSEC_PSK &&
1225 virtual_network->provider_type() !=
1226 PROVIDER_TYPE_L2TP_IPSEC_USER_CERT) {
1227 VLOG(1) << "IPsec field not allowed with this VPN type";
1228 return false;
1229 }
1230 return parser->ParseNestedObject(network,
1231 onc::vpn::kIPsec,
1232 value,
1233 ipsec_signature,
1234 ParseIPsecValue);
1235 case PROPERTY_INDEX_ONC_L2TP:
1236 if (virtual_network->provider_type() != PROVIDER_TYPE_L2TP_IPSEC_PSK) {
1237 VLOG(1) << "L2TP field not allowed with this VPN type";
1238 return false;
1239 }
1240 return parser->ParseNestedObject(network,
1241 onc::vpn::kL2TP,
1242 value,
1243 l2tp_signature,
1244 ParseL2TPValue);
1245 case PROPERTY_INDEX_ONC_OPENVPN: {
1246 if (virtual_network->provider_type() != PROVIDER_TYPE_OPEN_VPN) {
1247 VLOG(1) << "OpenVPN field not allowed with this VPN type";
1248 return false;
1249 }
1250 // The following are needed by shill to set up the OpenVPN
1251 // management channel which every ONC OpenVPN configuration will
1252 // use.
1253 base::StringValue empty_value("");
1254 network->UpdatePropertyMap(PROPERTY_INDEX_OPEN_VPN_AUTHUSERPASS,
1255 &empty_value);
1256 network->UpdatePropertyMap(PROPERTY_INDEX_OPEN_VPN_MGMT_ENABLE,
1257 &empty_value);
1258 return parser->ParseNestedObject(network,
1259 onc::vpn::kOpenVPN,
1260 value,
1261 openvpn_signature,
1262 ParseOpenVPNValue);
1263 }
1264 case PROPERTY_INDEX_PROVIDER_TYPE: {
1265 // Update property with native value for provider type.
1266 ProviderType provider_type = GetCanonicalProviderType(
1267 virtual_network->provider_type());
1268 std::string str =
1269 NativeVirtualNetworkParser::provider_type_mapper()->GetKey(
1270 provider_type);
1271 base::StringValue val(str);
1272 network->UpdatePropertyMap(PROPERTY_INDEX_PROVIDER_TYPE, &val);
1273 return true;
1274 }
1275 default:
1276 break;
1277 }
1278 return false;
1279 }
1280
1281 bool OncVirtualNetworkParser::ParseIPsecValue(OncNetworkParser* parser,
1282 PropertyIndex index,
1283 const base::Value& value,
1284 Network* network) {
1285 if (!CheckNetworkType(network, TYPE_VPN, onc::vpn::kIPsec))
1286 return false;
1287 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
1288 switch (index) {
1289 case PROPERTY_INDEX_IPSEC_AUTHENTICATIONTYPE:
1290 virtual_network->set_provider_type(
1291 UpdateProviderTypeWithAuthType(virtual_network->provider_type(),
1292 GetStringValue(value)));
1293 return true;
1294 case PROPERTY_INDEX_L2TPIPSEC_CA_CERT_NSS:
1295 virtual_network->set_ca_cert_nss(GetStringValue(value));
1296 return true;
1297 case PROPERTY_INDEX_L2TPIPSEC_PSK:
1298 virtual_network->set_psk_passphrase(GetStringValue(value));
1299 return true;
1300 case PROPERTY_INDEX_L2TPIPSEC_GROUP_NAME:
1301 virtual_network->set_group_name(GetStringValue(value));
1302 return true;
1303 case PROPERTY_INDEX_SAVE_CREDENTIALS:
1304 // Note that the specification allows different settings for
1305 // IPsec credentials (PSK) and L2TP credentials (username and
1306 // password) but we merge them in our implementation as is required
1307 // with the current connection manager.
1308 virtual_network->set_save_credentials(GetBooleanValue(value));
1309 return true;
1310 case PROPERTY_INDEX_ONC_CLIENT_CERT_REF: {
1311 std::string cert_id = GetPkcs11IdFromCertGuid(GetStringValue(value));
1312 if (cert_id.empty())
1313 return false;
1314 virtual_network->set_client_cert_id(cert_id);
1315 return true;
1316 }
1317 case PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN: {
1318 return parser->ParseNestedObject(virtual_network,
1319 onc::vpn::kClientCertPattern,
1320 value,
1321 certificate_pattern_signature,
1322 ParseClientCertPattern);
1323 }
1324 case PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE: {
1325 ClientCertType type = ParseClientCertType(GetStringValue(value));
1326 virtual_network->set_client_cert_type(type);
1327 return true;
1328 }
1329 case PROPERTY_INDEX_IPSEC_IKEVERSION: {
1330 if (!value.IsType(TYPE_STRING)) {
1331 // Shill wants all provider properties to be strings.
1332 base::StringValue string_value(ConvertValueToString(value));
1333 virtual_network->UpdatePropertyMap(index, &string_value);
1334 }
1335 return true;
1336 }
1337 default:
1338 break;
1339 }
1340 return false;
1341 }
1342
1343 // static
1344 ProviderType OncVirtualNetworkParser::UpdateProviderTypeWithAuthType(
1345 ProviderType provider,
1346 const std::string& auth_type) {
1347 switch (provider) {
1348 case PROVIDER_TYPE_L2TP_IPSEC_PSK:
1349 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
1350 if (auth_type == "Cert") {
1351 return PROVIDER_TYPE_L2TP_IPSEC_USER_CERT;
1352 } else {
1353 if (auth_type != "PSK") {
1354 VLOG(1) << "Unexpected authentication type " << auth_type;
1355 break;
1356 }
1357 return PROVIDER_TYPE_L2TP_IPSEC_PSK;
1358 }
1359 default:
1360 VLOG(1) << "Unexpected provider type with authentication type "
1361 << auth_type;
1362 break;
1363 }
1364 return provider;
1365 }
1366
1367 // static
1368 ProviderType OncVirtualNetworkParser::GetCanonicalProviderType(
1369 ProviderType provider_type) {
1370 if (provider_type == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT)
1371 return PROVIDER_TYPE_L2TP_IPSEC_PSK;
1372 return provider_type;
1373 }
1374
1375 // static
1376 bool OncVirtualNetworkParser::ParseL2TPValue(OncNetworkParser* parser,
1377 PropertyIndex index,
1378 const base::Value& value,
1379 Network* network) {
1380 if (!CheckNetworkType(network, TYPE_VPN, "L2TP"))
1381 return false;
1382 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
1383 switch (index) {
1384 case PROPERTY_INDEX_L2TPIPSEC_PASSWORD:
1385 virtual_network->set_user_passphrase(GetStringValue(value));
1386 return true;
1387 case PROPERTY_INDEX_L2TPIPSEC_USER: {
1388 const std::string expanded_user(
1389 GetUserExpandedValue(value, parser->onc_source()));
1390 virtual_network->set_username(expanded_user);
1391 const StringValue expanded_user_value(expanded_user);
1392 virtual_network->UpdatePropertyMap(index, &expanded_user_value);
1393 return true;
1394 }
1395 case PROPERTY_INDEX_SAVE_CREDENTIALS:
1396 // Note that the specification allows different settings for
1397 // IPsec credentials (PSK) and L2TP credentials (username and
1398 // password) but we merge them in our implementation as is required
1399 // with the current connection manager.
1400 virtual_network->set_save_credentials(GetBooleanValue(value));
1401 return true;
1402 default:
1403 break;
1404 }
1405 return false;
1406 }
1407
1408 // static
1409 bool OncVirtualNetworkParser::ParseOpenVPNValue(OncNetworkParser* parser,
1410 PropertyIndex index,
1411 const base::Value& value,
1412 Network* network) {
1413 if (!CheckNetworkType(network, TYPE_VPN, "OpenVPN"))
1414 return false;
1415 VirtualNetwork* virtual_network = static_cast<VirtualNetwork*>(network);
1416 switch (index) {
1417 case PROPERTY_INDEX_OPEN_VPN_PASSWORD:
1418 virtual_network->set_user_passphrase(GetStringValue(value));
1419 return true;
1420 case PROPERTY_INDEX_OPEN_VPN_USER: {
1421 const std::string expanded_user(
1422 GetUserExpandedValue(value, parser->onc_source()));
1423 virtual_network->set_username(expanded_user);
1424 const StringValue expanded_user_value(expanded_user);
1425 virtual_network->UpdatePropertyMap(index, &expanded_user_value);
1426 return true;
1427 }
1428 case PROPERTY_INDEX_SAVE_CREDENTIALS:
1429 virtual_network->set_save_credentials(GetBooleanValue(value));
1430 return true;
1431 case PROPERTY_INDEX_OPEN_VPN_CACERT:
1432 virtual_network->set_ca_cert_nss(GetStringValue(value));
1433 return true;
1434 case PROPERTY_INDEX_OPEN_VPN_REMOTECERTKU: {
1435 // ONC supports a list of these, but we shill supports only one
1436 // today. So extract the first.
1437 const base::ListValue* value_list = NULL;
1438 value.GetAsList(&value_list);
1439 const base::Value* first_item = NULL;
1440 if (!value_list->Get(0, &first_item) ||
1441 !first_item->IsType(base::Value::TYPE_STRING)) {
1442 VLOG(1) << "RemoteCertKU must be non-empty list of strings";
1443 return false;
1444 }
1445 virtual_network->UpdatePropertyMap(index, first_item);
1446 return true;
1447 }
1448 case PROPERTY_INDEX_OPEN_VPN_AUTH:
1449 case PROPERTY_INDEX_OPEN_VPN_AUTHRETRY:
1450 case PROPERTY_INDEX_OPEN_VPN_AUTHNOCACHE:
1451 case PROPERTY_INDEX_OPEN_VPN_CERT:
1452 case PROPERTY_INDEX_OPEN_VPN_CIPHER:
1453 case PROPERTY_INDEX_OPEN_VPN_COMPLZO:
1454 case PROPERTY_INDEX_OPEN_VPN_COMPNOADAPT:
1455 case PROPERTY_INDEX_OPEN_VPN_KEYDIRECTION:
1456 case PROPERTY_INDEX_OPEN_VPN_NSCERTTYPE:
1457 case PROPERTY_INDEX_OPEN_VPN_PORT:
1458 case PROPERTY_INDEX_OPEN_VPN_PROTO:
1459 case PROPERTY_INDEX_OPEN_VPN_PUSHPEERINFO:
1460 case PROPERTY_INDEX_OPEN_VPN_REMOTECERTEKU:
1461 case PROPERTY_INDEX_OPEN_VPN_REMOTECERTTLS:
1462 case PROPERTY_INDEX_OPEN_VPN_RENEGSEC:
1463 case PROPERTY_INDEX_OPEN_VPN_SERVERPOLLTIMEOUT:
1464 case PROPERTY_INDEX_OPEN_VPN_SHAPER:
1465 case PROPERTY_INDEX_OPEN_VPN_STATICCHALLENGE:
1466 case PROPERTY_INDEX_OPEN_VPN_TLSAUTHCONTENTS:
1467 case PROPERTY_INDEX_OPEN_VPN_TLSREMOTE: {
1468 if (!value.IsType(TYPE_STRING)) {
1469 // Shill wants all provider properties to be strings.
1470 base::StringValue string_value(ConvertValueToString(value));
1471 virtual_network->UpdatePropertyMap(index, &string_value);
1472 }
1473 return true;
1474 }
1475 case PROPERTY_INDEX_ONC_CLIENT_CERT_REF: {
1476 std::string cert_id = GetPkcs11IdFromCertGuid(GetStringValue(value));
1477 if (cert_id.empty())
1478 return false;
1479 virtual_network->set_client_cert_id(cert_id);
1480 return true;
1481 }
1482 case PROPERTY_INDEX_ONC_CLIENT_CERT_PATTERN:
1483 return parser->ParseNestedObject(
1484 virtual_network,
1485 onc::eap::kClientCertPattern,
1486 value,
1487 certificate_pattern_signature,
1488 OncNetworkParser::ParseClientCertPattern);
1489 case PROPERTY_INDEX_ONC_CLIENT_CERT_TYPE: {
1490 ClientCertType type = ParseClientCertType(GetStringValue(value));
1491 virtual_network->set_client_cert_type(type);
1492 return true;
1493 }
1494
1495 default:
1496 break;
1497 }
1498 return false;
1499 }
1500
1501 // static
1502 ProviderType OncVirtualNetworkParser::ParseProviderType(
1503 const std::string& type) {
1504 static EnumMapper<ProviderType>::Pair table[] = {
1505 // We initially map to L2TP-IPsec PSK and then fix this up based
1506 // on the value of AuthenticationType.
1507 { "L2TP-IPsec", PROVIDER_TYPE_L2TP_IPSEC_PSK },
1508 { "OpenVPN", PROVIDER_TYPE_OPEN_VPN },
1509 };
1510 CR_DEFINE_STATIC_LOCAL(EnumMapper<ProviderType>, parser,
1511 (table, arraysize(table), PROVIDER_TYPE_MAX));
1512 return parser.Get(type);
1513 }
1514
1515 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/cros/onc_network_parser.h ('k') | chrome/browser/chromeos/cros/onc_network_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698