OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/cros/network_library_impl_base.h" | 5 #include "chrome/browser/chromeos/cros/network_library_impl_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 9 #include "base/json/json_writer.h" |
9 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
12 #include "chrome/browser/chromeos/cros/native_network_parser.h" | |
13 #include "chrome/browser/chromeos/cros/network_constants.h" | 13 #include "chrome/browser/chromeos/cros/network_constants.h" |
14 #include "chrome/browser/chromeos/cros/onc_network_parser.h" | 14 #include "chrome/browser/chromeos/login/user_manager.h" |
| 15 #include "chrome/browser/chromeos/net/onc_utils.h" |
15 #include "chrome/browser/chromeos/network_login_observer.h" | 16 #include "chrome/browser/chromeos/network_login_observer.h" |
16 #include "chromeos/network/onc/onc_certificate_importer.h" | 17 #include "chromeos/network/onc/onc_certificate_importer.h" |
17 #include "chromeos/network/onc/onc_constants.h" | 18 #include "chromeos/network/onc/onc_constants.h" |
18 #include "chromeos/network/onc/onc_signature.h" | 19 #include "chromeos/network/onc/onc_signature.h" |
| 20 #include "chromeos/network/onc/onc_translator.h" |
19 #include "chromeos/network/onc/onc_utils.h" | 21 #include "chromeos/network/onc/onc_utils.h" |
20 #include "chromeos/network/onc/onc_validator.h" | 22 #include "chromeos/network/onc/onc_validator.h" |
21 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
22 #include "crypto/nss_util.h" // crypto::GetTPMTokenInfo() for 802.1X and VPN. | 24 #include "crypto/nss_util.h" // crypto::GetTPMTokenInfo() for 802.1X and VPN. |
23 #include "grit/generated_resources.h" | 25 #include "grit/generated_resources.h" |
24 #include "third_party/cros_system_api/dbus/service_constants.h" | 26 #include "third_party/cros_system_api/dbus/service_constants.h" |
25 #include "ui/base/l10n/l10n_util.h" | 27 #include "ui/base/l10n/l10n_util.h" |
26 | 28 |
27 using content::BrowserThread; | 29 using content::BrowserThread; |
28 | 30 |
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 continue; | 1025 continue; |
1024 if (!wifi->preferred()) // All preferred networks are sorted in front. | 1026 if (!wifi->preferred()) // All preferred networks are sorted in front. |
1025 break; | 1027 break; |
1026 if (wifi->auto_connect()) { | 1028 if (wifi->auto_connect()) { |
1027 ConnectToWifiNetwork(wifi); | 1029 ConnectToWifiNetwork(wifi); |
1028 break; | 1030 break; |
1029 } | 1031 } |
1030 } | 1032 } |
1031 } | 1033 } |
1032 | 1034 |
| 1035 namespace { |
| 1036 |
| 1037 class UserStringSubstitution : public onc::StringSubstitution { |
| 1038 public: |
| 1039 UserStringSubstitution() {} |
| 1040 virtual bool GetSubstitute(std::string placeholder, |
| 1041 std::string* substitute) const { |
| 1042 if (!UserManager::Get()->IsUserLoggedIn()) |
| 1043 return false; |
| 1044 const User* logged_in_user = UserManager::Get()->GetLoggedInUser(); |
| 1045 if (placeholder == onc::substitutes::kLoginIDField) |
| 1046 *substitute = logged_in_user->GetAccountName(false); |
| 1047 else if (placeholder == onc::substitutes::kEmailField) |
| 1048 *substitute = logged_in_user->email(); |
| 1049 else |
| 1050 return false; |
| 1051 return true; |
| 1052 } |
| 1053 }; |
| 1054 |
| 1055 } // namespace |
| 1056 |
1033 bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, | 1057 bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob, |
1034 const std::string& passphrase, | 1058 const std::string& passphrase, |
1035 onc::ONCSource source, | 1059 onc::ONCSource source, |
1036 bool allow_web_trust_from_policy) { | 1060 bool allow_web_trust_from_policy) { |
1037 VLOG(2) << __func__ << ": called on " << onc_blob; | 1061 VLOG(2) << __func__ << ": called on " << onc_blob; |
1038 NetworkProfile* profile = NULL; | 1062 NetworkProfile* profile = NULL; |
1039 bool from_policy = (source == onc::ONC_SOURCE_USER_POLICY || | 1063 bool from_policy = (source == onc::ONC_SOURCE_USER_POLICY || |
1040 source == onc::ONC_SOURCE_DEVICE_POLICY); | 1064 source == onc::ONC_SOURCE_DEVICE_POLICY); |
1041 | 1065 |
1042 // Policies are applied to a specific Shill profile. User ONC import however | 1066 // Policies are applied to a specific Shill profile. User ONC import however |
(...skipping 28 matching lines...) Expand all Loading... |
1071 return false; | 1095 return false; |
1072 } | 1096 } |
1073 } | 1097 } |
1074 | 1098 |
1075 // Validate the ONC dictionary. We are liberal and ignore unknown field | 1099 // Validate the ONC dictionary. We are liberal and ignore unknown field |
1076 // names and ignore invalid field names in kRecommended arrays. | 1100 // names and ignore invalid field names in kRecommended arrays. |
1077 onc::Validator validator(false, // Ignore unknown fields. | 1101 onc::Validator validator(false, // Ignore unknown fields. |
1078 false, // Ignore invalid recommended field names. | 1102 false, // Ignore invalid recommended field names. |
1079 true, // Fail on missing fields. | 1103 true, // Fail on missing fields. |
1080 from_policy); | 1104 from_policy); |
| 1105 validator.SetOncSource(source); |
1081 | 1106 |
1082 onc::Validator::Result validation_result; | 1107 onc::Validator::Result validation_result; |
1083 validator.ValidateAndRepairObject(&onc::kToplevelConfigurationSignature, | 1108 root_dict = validator.ValidateAndRepairObject( |
1084 *root_dict, | 1109 &onc::kToplevelConfigurationSignature, |
1085 &validation_result); | 1110 *root_dict, |
| 1111 &validation_result); |
1086 | 1112 |
1087 if (from_policy) { | 1113 if (from_policy) { |
1088 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", | 1114 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", |
1089 validation_result == onc::Validator::VALID); | 1115 validation_result == onc::Validator::VALID); |
1090 } | 1116 } |
1091 | 1117 |
1092 bool success = true; | 1118 bool success = true; |
1093 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { | 1119 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { |
1094 LOG(WARNING) << "ONC from " << onc::GetSourceAsString(source) | 1120 LOG(WARNING) << "ONC from " << onc::GetSourceAsString(source) |
1095 << " produced warnings."; | 1121 << " produced warnings."; |
1096 } else if (validation_result == onc::Validator::INVALID) { | 1122 success = false; |
| 1123 } else if (validation_result == onc::Validator::INVALID || |
| 1124 root_dict == NULL) { |
1097 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(source) | 1125 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(source) |
1098 << " is invalid and couldn't be repaired."; | 1126 << " is invalid and couldn't be repaired."; |
1099 success = false; | 1127 return false; |
1100 } | 1128 } |
1101 | 1129 |
1102 const base::ListValue* certificates; | 1130 const base::ListValue* certificates; |
1103 bool has_certificates = | 1131 bool has_certificates = |
1104 root_dict->GetListWithoutPathExpansion(onc::kCertificates, &certificates); | 1132 root_dict->GetListWithoutPathExpansion(onc::kCertificates, &certificates); |
1105 | 1133 |
1106 const base::ListValue* network_configs; | 1134 const base::ListValue* network_configs; |
1107 bool has_network_configurations = root_dict->GetListWithoutPathExpansion( | 1135 bool has_network_configurations = root_dict->GetListWithoutPathExpansion( |
1108 onc::kNetworkConfigurations, | 1136 onc::kNetworkConfigurations, |
1109 &network_configs); | 1137 &network_configs); |
1110 | 1138 |
1111 if (has_certificates) { | 1139 if (has_certificates) { |
1112 VLOG(2) << "ONC file has " << certificates->GetSize() << " certificates"; | 1140 VLOG(2) << "ONC file has " << certificates->GetSize() << " certificates"; |
1113 | 1141 |
1114 onc::CertificateImporter cert_importer(source, allow_web_trust_from_policy); | 1142 onc::CertificateImporter cert_importer(source, allow_web_trust_from_policy); |
1115 if (cert_importer.ParseAndStoreCertificates(*certificates) != | 1143 if (cert_importer.ParseAndStoreCertificates(*certificates) != |
1116 onc::CertificateImporter::IMPORT_OK) { | 1144 onc::CertificateImporter::IMPORT_OK) { |
1117 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " | 1145 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " |
1118 << onc::GetSourceAsString(source); | 1146 << onc::GetSourceAsString(source); |
1119 success = false; | 1147 success = false; |
1120 } | 1148 } |
1121 } | 1149 } |
1122 | 1150 |
1123 std::set<std::string> removal_ids; | 1151 std::set<std::string> removal_ids; |
1124 std::set<std::string>& network_ids(network_source_map_[source]); | 1152 std::set<std::string>& network_ids(network_source_map_[source]); |
1125 network_ids.clear(); | 1153 network_ids.clear(); |
1126 if (has_network_configurations) { | 1154 if (has_network_configurations) { |
1127 VLOG(2) << "ONC file has " << network_configs->GetSize() << " networks"; | 1155 VLOG(2) << "ONC file has " << network_configs->GetSize() << " networks"; |
1128 OncNetworkParser parser(*network_configs, source); | 1156 for (base::ListValue::const_iterator it(network_configs->begin()); |
| 1157 it != network_configs->end(); ++it) { |
| 1158 const base::DictionaryValue* network; |
| 1159 (*it)->GetAsDictionary(&network); |
1129 | 1160 |
1130 for (int i = 0; i < parser.GetNetworkConfigsSize(); i++) { | |
1131 // Parse Open Network Configuration blob into a temporary Network object. | |
1132 bool marked_for_removal = false; | 1161 bool marked_for_removal = false; |
1133 scoped_ptr<Network> network(parser.ParseNetwork(i, &marked_for_removal)); | 1162 network->GetBooleanWithoutPathExpansion(onc::kRemove, |
1134 if (!network) { | 1163 &marked_for_removal); |
1135 LOG(ERROR) << "Error during ONC parsing network at index " << i | 1164 |
1136 << " from " << onc::GetSourceAsString(source); | 1165 std::string type; |
1137 success = false; | 1166 network->GetStringWithoutPathExpansion(onc::kType, &type); |
| 1167 |
| 1168 std::string guid; |
| 1169 network->GetStringWithoutPathExpansion(onc::kGUID, &guid); |
| 1170 |
| 1171 if (source == onc::ONC_SOURCE_USER_IMPORT && marked_for_removal) { |
| 1172 // User import supports the removal of networks by ID. |
| 1173 removal_ids.insert(guid); |
1138 continue; | 1174 continue; |
1139 } | 1175 } |
1140 | 1176 |
1141 // Disallow anything but WiFi and Ethernet for device-level policy (which | |
1142 // corresponds to shared networks). See also http://crosbug.com/28741. | |
1143 if (source == onc::ONC_SOURCE_DEVICE_POLICY && | |
1144 network->type() != TYPE_WIFI && | |
1145 network->type() != TYPE_ETHERNET) { | |
1146 LOG(WARNING) << "Ignoring device-level policy-pushed network of type " | |
1147 << network->type(); | |
1148 continue; | |
1149 } | |
1150 | |
1151 if (source == onc::ONC_SOURCE_USER_IMPORT && marked_for_removal) { | |
1152 // User import supports the removal of networks by ID. | |
1153 removal_ids.insert(network->unique_id()); | |
1154 continue; | |
1155 } | |
1156 | |
1157 // Don't configure a network that is supposed to be removed. For | 1177 // Don't configure a network that is supposed to be removed. For |
1158 // policy-managed networks, the "remove" functionality of ONC is | 1178 // policy-managed networks, the "remove" functionality of ONC is |
1159 // irrelevant. Instead, in general, all previously configured networks | 1179 // irrelevant. Instead, in general, all previously configured networks |
1160 // that are no longer configured are removed. | 1180 // that are no longer configured are removed. |
1161 if (marked_for_removal) | 1181 if (marked_for_removal) |
1162 continue; | 1182 continue; |
1163 | 1183 |
| 1184 // Expand strings like LoginID |
| 1185 base::DictionaryValue* expanded_network = network->DeepCopy(); |
| 1186 UserStringSubstitution substitution; |
| 1187 onc::ExpandStringsInOncObject(onc::kNetworkConfigurationSignature, |
| 1188 substitution, |
| 1189 expanded_network); |
| 1190 |
1164 // Update the ONC map. | 1191 // Update the ONC map. |
1165 const base::DictionaryValue*& entry = | 1192 const base::DictionaryValue*& entry = network_onc_map_[guid]; |
1166 network_onc_map_[network->unique_id()]; | |
1167 delete entry; | 1193 delete entry; |
1168 entry = parser.GetNetworkConfig(i)->DeepCopy(); | 1194 entry = expanded_network; |
1169 | 1195 |
1170 // Configure the network. | 1196 // Configure the network. |
1171 base::DictionaryValue dict; | 1197 scoped_ptr<base::DictionaryValue> shill_dict = |
1172 for (Network::PropertyMap::const_iterator props = | 1198 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, |
1173 network->property_map_.begin(); | 1199 *expanded_network); |
1174 props != network->property_map_.end(); ++props) { | 1200 |
1175 std::string key = | 1201 // Set the ProxyConfig. |
1176 NativeNetworkParser::property_mapper()->GetKey(props->first); | 1202 const base::DictionaryValue* proxy_settings; |
1177 if (!key.empty()) | 1203 if (expanded_network->GetDictionaryWithoutPathExpansion( |
1178 dict.SetWithoutPathExpansion(key, props->second->DeepCopy()); | 1204 onc::kProxySettings, |
1179 else | 1205 &proxy_settings)) { |
1180 VLOG(2) << "Property " << props->first << " will not be sent"; | 1206 scoped_ptr<base::DictionaryValue> proxy_config = |
| 1207 onc::ConvertOncProxySettingsToProxyConfig(*proxy_settings); |
| 1208 std::string proxy_json; |
| 1209 base::JSONWriter::Write(proxy_config.get(), &proxy_json); |
| 1210 shill_dict->SetStringWithoutPathExpansion( |
| 1211 flimflam::kProxyConfigProperty, |
| 1212 proxy_json); |
1181 } | 1213 } |
1182 | 1214 |
| 1215 // Set the UIData. |
| 1216 scoped_ptr<NetworkUIData> ui_data = |
| 1217 onc::CreateUIData(source, *expanded_network); |
| 1218 base::DictionaryValue ui_data_dict; |
| 1219 ui_data->FillDictionary(&ui_data_dict); |
| 1220 std::string ui_data_json; |
| 1221 base::JSONWriter::Write(&ui_data_dict, &ui_data_json); |
| 1222 shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, |
| 1223 ui_data_json); |
| 1224 |
1183 // Set the appropriate profile for |source|. | 1225 // Set the appropriate profile for |source|. |
1184 if (profile != NULL) | 1226 if (profile != NULL) { |
1185 dict.SetString(flimflam::kProfileProperty, profile->path); | 1227 shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty, |
| 1228 profile->path); |
| 1229 } |
1186 | 1230 |
1187 // For Ethernet networks, apply them to the current Ethernet service. | 1231 // For Ethernet networks, apply them to the current Ethernet service. |
1188 if (network->type() == TYPE_ETHERNET) { | 1232 if (type == onc::kEthernet) { |
1189 const EthernetNetwork* ethernet = ethernet_network(); | 1233 const EthernetNetwork* ethernet = ethernet_network(); |
1190 if (ethernet) { | 1234 if (ethernet) { |
1191 CallConfigureService(ethernet->unique_id(), &dict); | 1235 CallConfigureService(ethernet->unique_id(), shill_dict.get()); |
1192 } else { | 1236 } else { |
1193 LOG(WARNING) << "Tried to import ONC with an Ethernet network when " | 1237 LOG(WARNING) << "Tried to import ONC with an Ethernet network when " |
1194 << "there is no active Ethernet connection."; | 1238 << "there is no active Ethernet connection."; |
1195 } | 1239 } |
1196 } else { | 1240 } else { |
1197 CallConfigureService(network->unique_id(), &dict); | 1241 CallConfigureService(guid, shill_dict.get()); |
1198 } | 1242 } |
1199 | 1243 |
1200 // Store the unique identifier of the network that is defined in the ONC | 1244 // Store the network's identifier. The identifiers are later used to clean |
1201 // blob in |network_ids|. The identifiers are later used to clean out any | 1245 // out any previously-existing networks that had been configured through |
1202 // previously-existing networks that had been configured through policy | 1246 // policy but are no longer specified in the updated ONC blob. |
1203 // but are no longer specified in the updated ONC blob. | 1247 network_ids.insert(guid); |
1204 network_ids.insert(network->unique_id()); | |
1205 } | 1248 } |
1206 } | 1249 } |
1207 | 1250 |
1208 if (from_policy) { | 1251 if (from_policy) { |
1209 // For policy-managed networks, go through the list of existing remembered | 1252 // For policy-managed networks, go through the list of existing remembered |
1210 // networks and clean out the ones that no longer have a definition in the | 1253 // networks and clean out the ones that no longer have a definition in the |
1211 // ONC blob. We first collect the networks and do the actual deletion later | 1254 // ONC blob. We first collect the networks and do the actual deletion later |
1212 // because ForgetNetwork() changes the remembered network vectors. | 1255 // because ForgetNetwork() changes the remembered network vectors. |
1213 ForgetNetworksById(source, network_ids, false); | 1256 ForgetNetworksById(source, network_ids, false); |
1214 } else if (source == onc::ONC_SOURCE_USER_IMPORT && !removal_ids.empty()) { | 1257 } else if (source == onc::ONC_SOURCE_USER_IMPORT && !removal_ids.empty()) { |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 GetTpmInfo(); | 1775 GetTpmInfo(); |
1733 return tpm_slot_; | 1776 return tpm_slot_; |
1734 } | 1777 } |
1735 | 1778 |
1736 const std::string& NetworkLibraryImplBase::GetTpmPin() { | 1779 const std::string& NetworkLibraryImplBase::GetTpmPin() { |
1737 GetTpmInfo(); | 1780 GetTpmInfo(); |
1738 return tpm_pin_; | 1781 return tpm_pin_; |
1739 } | 1782 } |
1740 | 1783 |
1741 } // namespace chromeos | 1784 } // namespace chromeos |
OLD | NEW |