| 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_writer.h" | 8 #include "base/json/json_writer.h" |
| 9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/metrics/histogram.h" | |
| 11 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 12 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 13 #include "chrome/browser/chromeos/cros/network_constants.h" | 12 #include "chrome/browser/chromeos/cros/network_constants.h" |
| 14 #include "chrome/browser/chromeos/login/user_manager.h" | 13 #include "chrome/browser/chromeos/login/user_manager.h" |
| 15 #include "chrome/browser/chromeos/net/onc_utils.h" | 14 #include "chrome/browser/chromeos/net/onc_utils.h" |
| 16 #include "chrome/browser/chromeos/network_login_observer.h" | 15 #include "chrome/browser/chromeos/network_login_observer.h" |
| 17 #include "chromeos/network/network_ui_data.h" | 16 #include "chromeos/network/network_ui_data.h" |
| 18 #include "chromeos/network/onc/onc_certificate_importer.h" | |
| 19 #include "chromeos/network/onc/onc_constants.h" | 17 #include "chromeos/network/onc/onc_constants.h" |
| 20 #include "chromeos/network/onc/onc_normalizer.h" | 18 #include "chromeos/network/onc/onc_normalizer.h" |
| 21 #include "chromeos/network/onc/onc_signature.h" | 19 #include "chromeos/network/onc/onc_signature.h" |
| 22 #include "chromeos/network/onc/onc_translator.h" | 20 #include "chromeos/network/onc/onc_translator.h" |
| 23 #include "chromeos/network/onc/onc_utils.h" | 21 #include "chromeos/network/onc/onc_utils.h" |
| 24 #include "chromeos/network/onc/onc_validator.h" | |
| 25 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 26 #include "crypto/nss_util.h" // crypto::GetTPMTokenInfo() for 802.1X and VPN. | 23 #include "crypto/nss_util.h" // crypto::GetTPMTokenInfo() for 802.1X and VPN. |
| 27 #include "third_party/cros_system_api/dbus/service_constants.h" | 24 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 28 | 25 |
| 29 using content::BrowserThread; | 26 using content::BrowserThread; |
| 30 | 27 |
| 31 namespace chromeos { | 28 namespace chromeos { |
| 32 | 29 |
| 33 namespace { | 30 namespace { |
| 34 | 31 |
| (...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 else if (placeholder == onc::substitutes::kEmailField) | 1053 else if (placeholder == onc::substitutes::kEmailField) |
| 1057 *substitute = logged_in_user->email(); | 1054 *substitute = logged_in_user->email(); |
| 1058 else | 1055 else |
| 1059 return false; | 1056 return false; |
| 1060 return true; | 1057 return true; |
| 1061 } | 1058 } |
| 1062 }; | 1059 }; |
| 1063 | 1060 |
| 1064 } // namespace | 1061 } // namespace |
| 1065 | 1062 |
| 1066 bool NetworkLibraryImplBase::LoadOncNetworks( | 1063 void NetworkLibraryImplBase::LoadOncNetworks( |
| 1067 const std::string& onc_blob, | 1064 const base::ListValue& network_configs, |
| 1068 const std::string& passphrase, | 1065 onc::ONCSource source) { |
| 1069 onc::ONCSource source, | 1066 VLOG(2) << __func__ << ": called on " << network_configs; |
| 1070 net::CertificateList* onc_trusted_certificates) { | |
| 1071 VLOG(2) << __func__ << ": called on " << onc_blob; | |
| 1072 NetworkProfile* profile = NULL; | 1067 NetworkProfile* profile = NULL; |
| 1073 bool from_policy = (source == onc::ONC_SOURCE_USER_POLICY || | 1068 bool from_policy = (source == onc::ONC_SOURCE_USER_POLICY || |
| 1074 source == onc::ONC_SOURCE_DEVICE_POLICY); | 1069 source == onc::ONC_SOURCE_DEVICE_POLICY); |
| 1075 | 1070 |
| 1076 // Policies are applied to a specific Shill profile. User ONC import however | 1071 // Policies are applied to a specific Shill profile. User ONC import however |
| 1077 // is applied to whatever profile Shill chooses. This should be the profile | 1072 // is applied to whatever profile Shill chooses. This should be the profile |
| 1078 // that is already associated with a network and if no profile is associated | 1073 // that is already associated with a network and if no profile is associated |
| 1079 // yet, it should be the user profile. | 1074 // yet, it should be the user profile. |
| 1080 if (from_policy) { | 1075 if (from_policy) { |
| 1081 profile = GetProfileForType(GetProfileTypeForSource(source)); | 1076 profile = GetProfileForType(GetProfileTypeForSource(source)); |
| 1082 if (profile == NULL) { | 1077 if (profile == NULL) { |
| 1083 VLOG(2) << "Profile for ONC source " << onc::GetSourceAsString(source) | 1078 VLOG(2) << "Profile for ONC source " << onc::GetSourceAsString(source) |
| 1084 << " doesn't exist."; | 1079 << " doesn't exist."; |
| 1085 return true; | 1080 return; |
| 1086 } | |
| 1087 } | |
| 1088 | |
| 1089 scoped_ptr<base::DictionaryValue> root_dict = | |
| 1090 onc::ReadDictionaryFromJson(onc_blob); | |
| 1091 if (root_dict.get() == NULL) { | |
| 1092 LOG(ERROR) << "ONC loaded from " << onc::GetSourceAsString(source) | |
| 1093 << " is not a valid JSON dictionary."; | |
| 1094 return false; | |
| 1095 } | |
| 1096 | |
| 1097 // Check and see if this is an encrypted ONC file. If so, decrypt it. | |
| 1098 std::string onc_type; | |
| 1099 root_dict->GetStringWithoutPathExpansion(onc::toplevel_config::kType, | |
| 1100 &onc_type); | |
| 1101 if (onc_type == onc::toplevel_config::kEncryptedConfiguration) { | |
| 1102 root_dict = onc::Decrypt(passphrase, *root_dict); | |
| 1103 if (root_dict.get() == NULL) { | |
| 1104 LOG(ERROR) << "Couldn't decrypt the ONC from " | |
| 1105 << onc::GetSourceAsString(source); | |
| 1106 return false; | |
| 1107 } | |
| 1108 } | |
| 1109 | |
| 1110 // Validate the ONC dictionary. We are liberal and ignore unknown field | |
| 1111 // names and ignore invalid field names in kRecommended arrays. | |
| 1112 onc::Validator validator(false, // Ignore unknown fields. | |
| 1113 false, // Ignore invalid recommended field names. | |
| 1114 true, // Fail on missing fields. | |
| 1115 from_policy); | |
| 1116 validator.SetOncSource(source); | |
| 1117 | |
| 1118 onc::Validator::Result validation_result; | |
| 1119 root_dict = validator.ValidateAndRepairObject( | |
| 1120 &onc::kToplevelConfigurationSignature, | |
| 1121 *root_dict, | |
| 1122 &validation_result); | |
| 1123 | |
| 1124 if (from_policy) { | |
| 1125 UMA_HISTOGRAM_BOOLEAN("Enterprise.ONC.PolicyValidation", | |
| 1126 validation_result == onc::Validator::VALID); | |
| 1127 } | |
| 1128 | |
| 1129 bool success = true; | |
| 1130 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { | |
| 1131 LOG(WARNING) << "ONC from " << onc::GetSourceAsString(source) | |
| 1132 << " produced warnings."; | |
| 1133 success = false; | |
| 1134 } else if (validation_result == onc::Validator::INVALID || | |
| 1135 root_dict == NULL) { | |
| 1136 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(source) | |
| 1137 << " is invalid and couldn't be repaired."; | |
| 1138 return false; | |
| 1139 } | |
| 1140 | |
| 1141 const base::ListValue* certificates; | |
| 1142 bool has_certificates = | |
| 1143 root_dict->GetListWithoutPathExpansion( | |
| 1144 onc::toplevel_config::kCertificates, | |
| 1145 &certificates); | |
| 1146 | |
| 1147 const base::ListValue* network_configs; | |
| 1148 bool has_network_configurations = root_dict->GetListWithoutPathExpansion( | |
| 1149 onc::toplevel_config::kNetworkConfigurations, | |
| 1150 &network_configs); | |
| 1151 | |
| 1152 if (has_certificates) { | |
| 1153 VLOG(2) << "ONC file has " << certificates->GetSize() << " certificates"; | |
| 1154 | |
| 1155 // Web trust is only granted to certificates imported by the user. | |
| 1156 bool allow_trust_imports = source == onc::ONC_SOURCE_USER_IMPORT; | |
| 1157 onc::CertificateImporter cert_importer(allow_trust_imports); | |
| 1158 if (cert_importer.ParseAndStoreCertificates( | |
| 1159 *certificates, onc_trusted_certificates) != | |
| 1160 onc::CertificateImporter::IMPORT_OK) { | |
| 1161 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " | |
| 1162 << onc::GetSourceAsString(source); | |
| 1163 success = false; | |
| 1164 } | 1081 } |
| 1165 } | 1082 } |
| 1166 | 1083 |
| 1167 std::set<std::string> removal_ids; | 1084 std::set<std::string> removal_ids; |
| 1168 std::set<std::string>& network_ids(network_source_map_[source]); | 1085 std::set<std::string>& network_ids(network_source_map_[source]); |
| 1169 network_ids.clear(); | 1086 network_ids.clear(); |
| 1170 if (has_network_configurations) { | 1087 VLOG(2) << "ONC file has " << network_configs.GetSize() << " networks"; |
| 1171 VLOG(2) << "ONC file has " << network_configs->GetSize() << " networks"; | 1088 for (base::ListValue::const_iterator it(network_configs.begin()); |
| 1172 for (base::ListValue::const_iterator it(network_configs->begin()); | 1089 it != network_configs.end(); ++it) { |
| 1173 it != network_configs->end(); ++it) { | 1090 const base::DictionaryValue* network; |
| 1174 const base::DictionaryValue* network; | 1091 (*it)->GetAsDictionary(&network); |
| 1175 (*it)->GetAsDictionary(&network); | |
| 1176 | 1092 |
| 1177 bool marked_for_removal = false; | 1093 bool marked_for_removal = false; |
| 1178 network->GetBooleanWithoutPathExpansion(onc::kRemove, | 1094 network->GetBooleanWithoutPathExpansion(onc::kRemove, |
| 1179 &marked_for_removal); | 1095 &marked_for_removal); |
| 1180 | 1096 |
| 1181 std::string type; | 1097 std::string type; |
| 1182 network->GetStringWithoutPathExpansion(onc::network_config::kType, &type); | 1098 network->GetStringWithoutPathExpansion(onc::network_config::kType, &type); |
| 1183 | 1099 |
| 1184 std::string guid; | 1100 std::string guid; |
| 1185 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); | 1101 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); |
| 1186 | 1102 |
| 1187 if (source == onc::ONC_SOURCE_USER_IMPORT && marked_for_removal) { | 1103 if (source == onc::ONC_SOURCE_USER_IMPORT && marked_for_removal) { |
| 1188 // User import supports the removal of networks by ID. | 1104 // User import supports the removal of networks by ID. |
| 1189 removal_ids.insert(guid); | 1105 removal_ids.insert(guid); |
| 1190 continue; | 1106 continue; |
| 1107 } |
| 1108 |
| 1109 // Don't configure a network that is supposed to be removed. For |
| 1110 // policy-managed networks, the "remove" functionality of ONC is |
| 1111 // irrelevant. Instead, in general, all previously configured networks |
| 1112 // that are no longer configured are removed. |
| 1113 if (marked_for_removal) |
| 1114 continue; |
| 1115 |
| 1116 // Expand strings like LoginID |
| 1117 base::DictionaryValue* expanded_network = network->DeepCopy(); |
| 1118 UserStringSubstitution substitution; |
| 1119 onc::ExpandStringsInOncObject(onc::kNetworkConfigurationSignature, |
| 1120 substitution, |
| 1121 expanded_network); |
| 1122 |
| 1123 // Update the ONC map. |
| 1124 const base::DictionaryValue*& entry = network_onc_map_[guid]; |
| 1125 delete entry; |
| 1126 entry = expanded_network; |
| 1127 |
| 1128 // Normalize the ONC: Remove irrelevant fields. |
| 1129 onc::Normalizer normalizer(true /* remove recommended fields */); |
| 1130 scoped_ptr<base::DictionaryValue> normalized_network = |
| 1131 normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature, |
| 1132 *expanded_network); |
| 1133 |
| 1134 // Configure the network. |
| 1135 scoped_ptr<base::DictionaryValue> shill_dict = |
| 1136 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, |
| 1137 *normalized_network); |
| 1138 |
| 1139 // Set the ProxyConfig. |
| 1140 const base::DictionaryValue* proxy_settings; |
| 1141 if (normalized_network->GetDictionaryWithoutPathExpansion( |
| 1142 onc::network_config::kProxySettings, |
| 1143 &proxy_settings)) { |
| 1144 scoped_ptr<base::DictionaryValue> proxy_config = |
| 1145 onc::ConvertOncProxySettingsToProxyConfig(*proxy_settings); |
| 1146 std::string proxy_json; |
| 1147 base::JSONWriter::Write(proxy_config.get(), &proxy_json); |
| 1148 shill_dict->SetStringWithoutPathExpansion( |
| 1149 flimflam::kProxyConfigProperty, |
| 1150 proxy_json); |
| 1151 } |
| 1152 |
| 1153 // Set the UIData. |
| 1154 scoped_ptr<NetworkUIData> ui_data = |
| 1155 chromeos::CreateUIDataFromONC(source, *normalized_network); |
| 1156 base::DictionaryValue ui_data_dict; |
| 1157 ui_data->FillDictionary(&ui_data_dict); |
| 1158 std::string ui_data_json; |
| 1159 base::JSONWriter::Write(&ui_data_dict, &ui_data_json); |
| 1160 shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, |
| 1161 ui_data_json); |
| 1162 |
| 1163 // Set the appropriate profile for |source|. |
| 1164 if (profile != NULL) { |
| 1165 shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty, |
| 1166 profile->path); |
| 1167 } |
| 1168 |
| 1169 // For Ethernet networks, apply them to the current Ethernet service. |
| 1170 if (type == onc::network_type::kEthernet) { |
| 1171 const EthernetNetwork* ethernet = ethernet_network(); |
| 1172 if (ethernet) { |
| 1173 CallConfigureService(ethernet->unique_id(), shill_dict.get()); |
| 1174 } else { |
| 1175 LOG(WARNING) << "Tried to import ONC with an Ethernet network when " |
| 1176 << "there is no active Ethernet connection."; |
| 1191 } | 1177 } |
| 1178 } else { |
| 1179 CallConfigureService(guid, shill_dict.get()); |
| 1180 } |
| 1192 | 1181 |
| 1193 // Don't configure a network that is supposed to be removed. For | 1182 // Store the network's identifier. The identifiers are later used to clean |
| 1194 // policy-managed networks, the "remove" functionality of ONC is | 1183 // out any previously-existing networks that had been configured through |
| 1195 // irrelevant. Instead, in general, all previously configured networks | 1184 // policy but are no longer specified in the updated ONC blob. |
| 1196 // that are no longer configured are removed. | 1185 network_ids.insert(guid); |
| 1197 if (marked_for_removal) | |
| 1198 continue; | |
| 1199 | |
| 1200 // Expand strings like LoginID | |
| 1201 base::DictionaryValue* expanded_network = network->DeepCopy(); | |
| 1202 UserStringSubstitution substitution; | |
| 1203 onc::ExpandStringsInOncObject(onc::kNetworkConfigurationSignature, | |
| 1204 substitution, | |
| 1205 expanded_network); | |
| 1206 | |
| 1207 // Update the ONC map. | |
| 1208 const base::DictionaryValue*& entry = network_onc_map_[guid]; | |
| 1209 delete entry; | |
| 1210 entry = expanded_network; | |
| 1211 | |
| 1212 // Normalize the ONC: Remove irrelevant fields. | |
| 1213 onc::Normalizer normalizer(true /* remove recommended fields */); | |
| 1214 scoped_ptr<base::DictionaryValue> normalized_network = | |
| 1215 normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature, | |
| 1216 *expanded_network); | |
| 1217 | |
| 1218 // Configure the network. | |
| 1219 scoped_ptr<base::DictionaryValue> shill_dict = | |
| 1220 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | |
| 1221 *normalized_network); | |
| 1222 | |
| 1223 // Set the ProxyConfig. | |
| 1224 const base::DictionaryValue* proxy_settings; | |
| 1225 if (normalized_network->GetDictionaryWithoutPathExpansion( | |
| 1226 onc::network_config::kProxySettings, | |
| 1227 &proxy_settings)) { | |
| 1228 scoped_ptr<base::DictionaryValue> proxy_config = | |
| 1229 onc::ConvertOncProxySettingsToProxyConfig(*proxy_settings); | |
| 1230 std::string proxy_json; | |
| 1231 base::JSONWriter::Write(proxy_config.get(), &proxy_json); | |
| 1232 shill_dict->SetStringWithoutPathExpansion( | |
| 1233 flimflam::kProxyConfigProperty, | |
| 1234 proxy_json); | |
| 1235 } | |
| 1236 | |
| 1237 // Set the UIData. | |
| 1238 scoped_ptr<NetworkUIData> ui_data = | |
| 1239 chromeos::CreateUIDataFromONC(source, *normalized_network); | |
| 1240 base::DictionaryValue ui_data_dict; | |
| 1241 ui_data->FillDictionary(&ui_data_dict); | |
| 1242 std::string ui_data_json; | |
| 1243 base::JSONWriter::Write(&ui_data_dict, &ui_data_json); | |
| 1244 shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, | |
| 1245 ui_data_json); | |
| 1246 | |
| 1247 // Set the appropriate profile for |source|. | |
| 1248 if (profile != NULL) { | |
| 1249 shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty, | |
| 1250 profile->path); | |
| 1251 } | |
| 1252 | |
| 1253 // For Ethernet networks, apply them to the current Ethernet service. | |
| 1254 if (type == onc::network_type::kEthernet) { | |
| 1255 const EthernetNetwork* ethernet = ethernet_network(); | |
| 1256 if (ethernet) { | |
| 1257 CallConfigureService(ethernet->unique_id(), shill_dict.get()); | |
| 1258 } else { | |
| 1259 LOG(WARNING) << "Tried to import ONC with an Ethernet network when " | |
| 1260 << "there is no active Ethernet connection."; | |
| 1261 } | |
| 1262 } else { | |
| 1263 CallConfigureService(guid, shill_dict.get()); | |
| 1264 } | |
| 1265 | |
| 1266 // Store the network's identifier. The identifiers are later used to clean | |
| 1267 // out any previously-existing networks that had been configured through | |
| 1268 // policy but are no longer specified in the updated ONC blob. | |
| 1269 network_ids.insert(guid); | |
| 1270 } | |
| 1271 } | 1186 } |
| 1272 | 1187 |
| 1273 if (from_policy) { | 1188 if (from_policy) { |
| 1274 // For policy-managed networks, go through the list of existing remembered | 1189 // For policy-managed networks, go through the list of existing remembered |
| 1275 // networks and clean out the ones that no longer have a definition in the | 1190 // networks and clean out the ones that no longer have a definition in the |
| 1276 // ONC blob. We first collect the networks and do the actual deletion later | 1191 // ONC blob. We first collect the networks and do the actual deletion later |
| 1277 // because ForgetNetwork() changes the remembered network vectors. | 1192 // because ForgetNetwork() changes the remembered network vectors. |
| 1278 ForgetNetworksById(source, network_ids, false); | 1193 ForgetNetworksById(source, network_ids, false); |
| 1279 } else if (source == onc::ONC_SOURCE_USER_IMPORT && !removal_ids.empty()) { | 1194 } else if (source == onc::ONC_SOURCE_USER_IMPORT && !removal_ids.empty()) { |
| 1280 ForgetNetworksById(source, removal_ids, true); | 1195 ForgetNetworksById(source, removal_ids, true); |
| 1281 } | 1196 } |
| 1282 | |
| 1283 return success; | |
| 1284 } | 1197 } |
| 1285 | 1198 |
| 1286 //////////////////////////////////////////////////////////////////////////// | 1199 //////////////////////////////////////////////////////////////////////////// |
| 1287 // Testing functions. | 1200 // Testing functions. |
| 1288 | 1201 |
| 1289 bool NetworkLibraryImplBase::SetActiveNetwork( | 1202 bool NetworkLibraryImplBase::SetActiveNetwork( |
| 1290 ConnectionType type, const std::string& service_path) { | 1203 ConnectionType type, const std::string& service_path) { |
| 1291 Network* network = NULL; | 1204 Network* network = NULL; |
| 1292 if (!service_path.empty()) | 1205 if (!service_path.empty()) |
| 1293 network = FindNetworkByPath(service_path); | 1206 network = FindNetworkByPath(service_path); |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1797 GetTpmInfo(); | 1710 GetTpmInfo(); |
| 1798 return tpm_slot_; | 1711 return tpm_slot_; |
| 1799 } | 1712 } |
| 1800 | 1713 |
| 1801 const std::string& NetworkLibraryImplBase::GetTpmPin() { | 1714 const std::string& NetworkLibraryImplBase::GetTpmPin() { |
| 1802 GetTpmInfo(); | 1715 GetTpmInfo(); |
| 1803 return tpm_pin_; | 1716 return tpm_pin_; |
| 1804 } | 1717 } |
| 1805 | 1718 |
| 1806 } // namespace chromeos | 1719 } // namespace chromeos |
| OLD | NEW |