| OLD | NEW |
| (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 | |
| OLD | NEW |