| 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 "chromeos/network/onc/onc_utils.h" | 5 #include "chromeos/network/onc/onc_utils.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| 11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 12 #include "base/json/json_writer.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/macros.h" | 14 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/values.h" | 19 #include "base/values.h" |
| 20 #include "chromeos/network/managed_network_configuration_handler.h" |
| 21 #include "chromeos/network/network_configuration_handler.h" |
| 19 #include "chromeos/network/network_event_log.h" | 22 #include "chromeos/network/network_event_log.h" |
| 23 #include "chromeos/network/network_profile.h" |
| 24 #include "chromeos/network/network_profile_handler.h" |
| 25 #include "chromeos/network/network_state.h" |
| 26 #include "chromeos/network/network_state_handler.h" |
| 27 #include "chromeos/network/network_ui_data.h" |
| 20 #include "chromeos/network/onc/onc_mapper.h" | 28 #include "chromeos/network/onc/onc_mapper.h" |
| 29 #include "chromeos/network/onc/onc_normalizer.h" |
| 21 #include "chromeos/network/onc/onc_signature.h" | 30 #include "chromeos/network/onc/onc_signature.h" |
| 31 #include "chromeos/network/onc/onc_translator.h" |
| 22 #include "chromeos/network/onc/onc_utils.h" | 32 #include "chromeos/network/onc/onc_utils.h" |
| 23 #include "chromeos/network/onc/onc_validator.h" | 33 #include "chromeos/network/onc/onc_validator.h" |
| 24 #include "components/device_event_log/device_event_log.h" | 34 #include "components/device_event_log/device_event_log.h" |
| 35 #include "components/onc/onc_pref_names.h" |
| 36 #include "components/prefs/pref_service.h" |
| 25 #include "components/proxy_config/proxy_config_dictionary.h" | 37 #include "components/proxy_config/proxy_config_dictionary.h" |
| 38 #include "components/user_manager/user.h" |
| 39 #include "components/user_manager/user_manager.h" |
| 26 #include "crypto/encryptor.h" | 40 #include "crypto/encryptor.h" |
| 27 #include "crypto/hmac.h" | 41 #include "crypto/hmac.h" |
| 28 #include "crypto/symmetric_key.h" | 42 #include "crypto/symmetric_key.h" |
| 29 #include "net/base/host_port_pair.h" | 43 #include "net/base/host_port_pair.h" |
| 30 #include "net/cert/pem_tokenizer.h" | 44 #include "net/cert/pem_tokenizer.h" |
| 31 #include "net/cert/x509_certificate.h" | 45 #include "net/cert/x509_certificate.h" |
| 32 #include "net/proxy/proxy_bypass_rules.h" | 46 #include "net/proxy/proxy_bypass_rules.h" |
| 33 #include "net/proxy/proxy_config.h" | 47 #include "net/proxy/proxy_config.h" |
| 34 #include "net/proxy/proxy_server.h" | 48 #include "net/proxy/proxy_server.h" |
| 49 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 50 #include "url/gurl.h" |
| 35 #include "url/url_constants.h" | 51 #include "url/url_constants.h" |
| 36 | 52 |
| 37 using namespace ::onc; | 53 using namespace ::onc; |
| 38 | 54 |
| 39 namespace chromeos { | 55 namespace chromeos { |
| 40 namespace onc { | 56 namespace onc { |
| 41 | 57 |
| 42 namespace { | 58 namespace { |
| 43 | 59 |
| 44 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; | 60 const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC"; |
| 45 const char kUnableToDecode[] = "Unable to decode encrypted ONC"; | 61 const char kUnableToDecode[] = "Unable to decode encrypted ONC"; |
| 46 | 62 |
| 63 // This class defines which string placeholders of ONC are replaced by which |
| 64 // user attribute. |
| 65 class UserStringSubstitution : public chromeos::onc::StringSubstitution { |
| 66 public: |
| 67 explicit UserStringSubstitution(const user_manager::User* user) |
| 68 : user_(user) {} |
| 69 ~UserStringSubstitution() override {} |
| 70 |
| 71 bool GetSubstitute(const std::string& placeholder, |
| 72 std::string* substitute) const override { |
| 73 if (placeholder == ::onc::substitutes::kLoginIDField) |
| 74 *substitute = user_->GetAccountName(false); |
| 75 else if (placeholder == ::onc::substitutes::kEmailField) |
| 76 *substitute = user_->email(); |
| 77 else |
| 78 return false; |
| 79 return true; |
| 80 } |
| 81 |
| 82 private: |
| 83 const user_manager::User* user_; |
| 84 |
| 85 DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution); |
| 86 }; |
| 87 |
| 47 } // namespace | 88 } // namespace |
| 48 | 89 |
| 49 const char kEmptyUnencryptedConfiguration[] = | 90 const char kEmptyUnencryptedConfiguration[] = |
| 50 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[]," | 91 "{\"Type\":\"UnencryptedConfiguration\",\"NetworkConfigurations\":[]," |
| 51 "\"Certificates\":[]}"; | 92 "\"Certificates\":[]}"; |
| 52 | 93 |
| 53 std::unique_ptr<base::DictionaryValue> ReadDictionaryFromJson( | 94 std::unique_ptr<base::DictionaryValue> ReadDictionaryFromJson( |
| 54 const std::string& json) { | 95 const std::string& json) { |
| 55 std::string error; | 96 std::string error; |
| 56 std::unique_ptr<base::Value> root = base::JSONReader::ReadAndReturnError( | 97 std::unique_ptr<base::Value> root = base::JSONReader::ReadAndReturnError( |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 break; | 1026 break; |
| 986 } | 1027 } |
| 987 default: { | 1028 default: { |
| 988 LOG(ERROR) << "Unexpected proxy mode in Shill config: " << mode; | 1029 LOG(ERROR) << "Unexpected proxy mode in Shill config: " << mode; |
| 989 return nullptr; | 1030 return nullptr; |
| 990 } | 1031 } |
| 991 } | 1032 } |
| 992 return proxy_settings; | 1033 return proxy_settings; |
| 993 } | 1034 } |
| 994 | 1035 |
| 1036 namespace { |
| 1037 |
| 1038 const base::DictionaryValue* GetNetworkConfigByGUID( |
| 1039 const base::ListValue& network_configs, |
| 1040 const std::string& guid) { |
| 1041 for (base::ListValue::const_iterator it = network_configs.begin(); |
| 1042 it != network_configs.end(); ++it) { |
| 1043 const base::DictionaryValue* network = NULL; |
| 1044 (*it)->GetAsDictionary(&network); |
| 1045 DCHECK(network); |
| 1046 |
| 1047 std::string current_guid; |
| 1048 network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, |
| 1049 ¤t_guid); |
| 1050 if (current_guid == guid) |
| 1051 return network; |
| 1052 } |
| 1053 return NULL; |
| 1054 } |
| 1055 |
| 1056 const base::DictionaryValue* GetNetworkConfigForEthernetWithoutEAP( |
| 1057 const base::ListValue& network_configs) { |
| 1058 VLOG(2) << "Search for ethernet policy without EAP."; |
| 1059 for (base::ListValue::const_iterator it = network_configs.begin(); |
| 1060 it != network_configs.end(); ++it) { |
| 1061 const base::DictionaryValue* network = NULL; |
| 1062 (*it)->GetAsDictionary(&network); |
| 1063 DCHECK(network); |
| 1064 |
| 1065 std::string type; |
| 1066 network->GetStringWithoutPathExpansion(::onc::network_config::kType, &type); |
| 1067 if (type != ::onc::network_type::kEthernet) |
| 1068 continue; |
| 1069 |
| 1070 const base::DictionaryValue* ethernet = NULL; |
| 1071 network->GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet, |
| 1072 ðernet); |
| 1073 |
| 1074 std::string auth; |
| 1075 ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, |
| 1076 &auth); |
| 1077 if (auth == ::onc::ethernet::kAuthenticationNone) |
| 1078 return network; |
| 1079 } |
| 1080 return NULL; |
| 1081 } |
| 1082 |
| 1083 const base::DictionaryValue* GetNetworkConfigForNetworkFromOnc( |
| 1084 const base::ListValue& network_configs, |
| 1085 const NetworkState& network) { |
| 1086 // In all cases except Ethernet, we use the GUID of |network|. |
| 1087 if (!network.Matches(NetworkTypePattern::Ethernet())) |
| 1088 return GetNetworkConfigByGUID(network_configs, network.guid()); |
| 1089 |
| 1090 // Ethernet is always shared and thus cannot store a GUID per user. Thus we |
| 1091 // search for any Ethernet policy intead of a matching GUID. |
| 1092 // EthernetEAP service contains only the EAP parameters and stores the GUID of |
| 1093 // the respective ONC policy. The EthernetEAP service itself is however never |
| 1094 // in state "connected". An EthernetEAP policy must be applied, if an Ethernet |
| 1095 // service is connected using the EAP parameters. |
| 1096 const NetworkState* ethernet_eap = NULL; |
| 1097 if (NetworkHandler::IsInitialized()) { |
| 1098 ethernet_eap = |
| 1099 NetworkHandler::Get()->network_state_handler()->GetEAPForEthernet( |
| 1100 network.path()); |
| 1101 } |
| 1102 |
| 1103 // The GUID associated with the EthernetEAP service refers to the ONC policy |
| 1104 // with "Authentication: 8021X". |
| 1105 if (ethernet_eap) |
| 1106 return GetNetworkConfigByGUID(network_configs, ethernet_eap->guid()); |
| 1107 |
| 1108 // Otherwise, EAP is not used and instead the Ethernet policy with |
| 1109 // "Authentication: None" applies. |
| 1110 return GetNetworkConfigForEthernetWithoutEAP(network_configs); |
| 1111 } |
| 1112 |
| 1113 const base::DictionaryValue* GetPolicyForNetworkFromPref( |
| 1114 const PrefService* pref_service, |
| 1115 const char* pref_name, |
| 1116 const NetworkState& network) { |
| 1117 if (!pref_service) { |
| 1118 VLOG(2) << "No pref service"; |
| 1119 return NULL; |
| 1120 } |
| 1121 |
| 1122 const PrefService::Preference* preference = |
| 1123 pref_service->FindPreference(pref_name); |
| 1124 if (!preference) { |
| 1125 VLOG(2) << "No preference " << pref_name; |
| 1126 // The preference may not exist in tests. |
| 1127 return NULL; |
| 1128 } |
| 1129 |
| 1130 // User prefs are not stored in this Preference yet but only the policy. |
| 1131 // |
| 1132 // The policy server incorrectly configures the OpenNetworkConfiguration user |
| 1133 // policy as Recommended. To work around that, we handle the Recommended and |
| 1134 // the Mandatory value in the same way. |
| 1135 // TODO(pneubeck): Remove this workaround, once the server is fixed. See |
| 1136 // http://crbug.com/280553 . |
| 1137 if (preference->IsDefaultValue()) { |
| 1138 VLOG(2) << "Preference has no recommended or mandatory value."; |
| 1139 // No policy set. |
| 1140 return NULL; |
| 1141 } |
| 1142 VLOG(2) << "Preference with policy found."; |
| 1143 const base::Value* onc_policy_value = preference->GetValue(); |
| 1144 DCHECK(onc_policy_value); |
| 1145 |
| 1146 const base::ListValue* onc_policy = NULL; |
| 1147 onc_policy_value->GetAsList(&onc_policy); |
| 1148 DCHECK(onc_policy); |
| 1149 |
| 1150 return GetNetworkConfigForNetworkFromOnc(*onc_policy, network); |
| 1151 } |
| 1152 |
| 1153 } // namespace |
| 1154 |
| 1155 void ExpandStringPlaceholdersInNetworksForUser( |
| 1156 const user_manager::User* user, |
| 1157 base::ListValue* network_configs) { |
| 1158 if (!user) { |
| 1159 // In tests no user may be logged in. It's not harmful if we just don't |
| 1160 // expand the strings. |
| 1161 return; |
| 1162 } |
| 1163 UserStringSubstitution substitution(user); |
| 1164 chromeos::onc::ExpandStringsInNetworks(substitution, network_configs); |
| 1165 } |
| 1166 |
| 1167 void ImportNetworksForUser(const user_manager::User* user, |
| 1168 const base::ListValue& network_configs, |
| 1169 std::string* error) { |
| 1170 error->clear(); |
| 1171 |
| 1172 std::unique_ptr<base::ListValue> expanded_networks( |
| 1173 network_configs.DeepCopy()); |
| 1174 ExpandStringPlaceholdersInNetworksForUser(user, expanded_networks.get()); |
| 1175 |
| 1176 const NetworkProfile* profile = |
| 1177 NetworkHandler::Get()->network_profile_handler()->GetProfileForUserhash( |
| 1178 user->username_hash()); |
| 1179 if (!profile) { |
| 1180 *error = "User profile doesn't exist."; |
| 1181 return; |
| 1182 } |
| 1183 |
| 1184 bool ethernet_not_found = false; |
| 1185 for (base::ListValue::const_iterator it = expanded_networks->begin(); |
| 1186 it != expanded_networks->end(); ++it) { |
| 1187 const base::DictionaryValue* network = NULL; |
| 1188 (*it)->GetAsDictionary(&network); |
| 1189 DCHECK(network); |
| 1190 |
| 1191 // Remove irrelevant fields. |
| 1192 onc::Normalizer normalizer(true /* remove recommended fields */); |
| 1193 std::unique_ptr<base::DictionaryValue> normalized_network = |
| 1194 normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature, |
| 1195 *network); |
| 1196 |
| 1197 // TODO(pneubeck): Use ONC and ManagedNetworkConfigurationHandler instead. |
| 1198 // crbug.com/457936 |
| 1199 std::unique_ptr<base::DictionaryValue> shill_dict = |
| 1200 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, |
| 1201 *normalized_network); |
| 1202 |
| 1203 std::unique_ptr<NetworkUIData> ui_data( |
| 1204 NetworkUIData::CreateFromONC(::onc::ONC_SOURCE_USER_IMPORT)); |
| 1205 base::DictionaryValue ui_data_dict; |
| 1206 ui_data->FillDictionary(&ui_data_dict); |
| 1207 std::string ui_data_json; |
| 1208 base::JSONWriter::Write(ui_data_dict, &ui_data_json); |
| 1209 shill_dict->SetStringWithoutPathExpansion(shill::kUIDataProperty, |
| 1210 ui_data_json); |
| 1211 |
| 1212 shill_dict->SetStringWithoutPathExpansion(shill::kProfileProperty, |
| 1213 profile->path); |
| 1214 |
| 1215 std::string type; |
| 1216 shill_dict->GetStringWithoutPathExpansion(shill::kTypeProperty, &type); |
| 1217 NetworkConfigurationHandler* config_handler = |
| 1218 NetworkHandler::Get()->network_configuration_handler(); |
| 1219 if (NetworkTypePattern::Ethernet().MatchesType(type)) { |
| 1220 // Ethernet has to be configured using an existing Ethernet service. |
| 1221 const NetworkState* ethernet = |
| 1222 NetworkHandler::Get()->network_state_handler()->FirstNetworkByType( |
| 1223 NetworkTypePattern::Ethernet()); |
| 1224 if (ethernet) { |
| 1225 config_handler->SetShillProperties( |
| 1226 ethernet->path(), *shill_dict, |
| 1227 NetworkConfigurationObserver::SOURCE_USER_ACTION, base::Closure(), |
| 1228 network_handler::ErrorCallback()); |
| 1229 } else { |
| 1230 ethernet_not_found = true; |
| 1231 } |
| 1232 |
| 1233 } else { |
| 1234 config_handler->CreateShillConfiguration( |
| 1235 *shill_dict, NetworkConfigurationObserver::SOURCE_USER_ACTION, |
| 1236 network_handler::ServiceResultCallback(), |
| 1237 network_handler::ErrorCallback()); |
| 1238 } |
| 1239 } |
| 1240 |
| 1241 if (ethernet_not_found) |
| 1242 *error = "No Ethernet available to configure."; |
| 1243 } |
| 1244 |
| 1245 const base::DictionaryValue* FindPolicyForActiveUser( |
| 1246 const std::string& guid, |
| 1247 ::onc::ONCSource* onc_source) { |
| 1248 const user_manager::User* user = |
| 1249 user_manager::UserManager::Get()->GetActiveUser(); |
| 1250 std::string username_hash = user ? user->username_hash() : std::string(); |
| 1251 return NetworkHandler::Get() |
| 1252 ->managed_network_configuration_handler() |
| 1253 ->FindPolicyByGUID(username_hash, guid, onc_source); |
| 1254 } |
| 1255 |
| 1256 namespace { |
| 1257 |
| 1258 const base::DictionaryValue* GetGlobalConfigFromPolicy(bool for_active_user) { |
| 1259 std::string username_hash; |
| 1260 if (for_active_user) { |
| 1261 const user_manager::User* user = |
| 1262 user_manager::UserManager::Get()->GetActiveUser(); |
| 1263 if (!user) { |
| 1264 LOG(ERROR) << "No user logged in yet."; |
| 1265 return NULL; |
| 1266 } |
| 1267 username_hash = user->username_hash(); |
| 1268 } |
| 1269 return NetworkHandler::Get() |
| 1270 ->managed_network_configuration_handler() |
| 1271 ->GetGlobalConfigFromPolicy(username_hash); |
| 1272 } |
| 1273 |
| 1274 } // namespace |
| 1275 |
| 1276 bool PolicyAllowsOnlyPolicyNetworksToAutoconnect(bool for_active_user) { |
| 1277 const base::DictionaryValue* global_config = |
| 1278 GetGlobalConfigFromPolicy(for_active_user); |
| 1279 if (!global_config) |
| 1280 return false; // By default, all networks are allowed to autoconnect. |
| 1281 |
| 1282 bool only_policy_autoconnect = false; |
| 1283 global_config->GetBooleanWithoutPathExpansion( |
| 1284 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, |
| 1285 &only_policy_autoconnect); |
| 1286 return only_policy_autoconnect; |
| 1287 } |
| 1288 |
| 1289 const base::DictionaryValue* GetPolicyForNetwork( |
| 1290 const PrefService* profile_prefs, |
| 1291 const PrefService* local_state_prefs, |
| 1292 const NetworkState& network, |
| 1293 ::onc::ONCSource* onc_source) { |
| 1294 VLOG(2) << "GetPolicyForNetwork: " << network.path(); |
| 1295 *onc_source = ::onc::ONC_SOURCE_NONE; |
| 1296 |
| 1297 const base::DictionaryValue* network_policy = GetPolicyForNetworkFromPref( |
| 1298 profile_prefs, ::onc::prefs::kOpenNetworkConfiguration, network); |
| 1299 if (network_policy) { |
| 1300 VLOG(1) << "Network " << network.path() << " is managed by user policy."; |
| 1301 *onc_source = ::onc::ONC_SOURCE_USER_POLICY; |
| 1302 return network_policy; |
| 1303 } |
| 1304 network_policy = GetPolicyForNetworkFromPref( |
| 1305 local_state_prefs, ::onc::prefs::kDeviceOpenNetworkConfiguration, |
| 1306 network); |
| 1307 if (network_policy) { |
| 1308 VLOG(1) << "Network " << network.path() << " is managed by device policy."; |
| 1309 *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; |
| 1310 return network_policy; |
| 1311 } |
| 1312 VLOG(2) << "Network " << network.path() << " is unmanaged."; |
| 1313 return NULL; |
| 1314 } |
| 1315 |
| 1316 bool HasPolicyForNetwork(const PrefService* profile_prefs, |
| 1317 const PrefService* local_state_prefs, |
| 1318 const NetworkState& network) { |
| 1319 ::onc::ONCSource ignored_onc_source; |
| 1320 const base::DictionaryValue* policy = onc::GetPolicyForNetwork( |
| 1321 profile_prefs, local_state_prefs, network, &ignored_onc_source); |
| 1322 return policy != NULL; |
| 1323 } |
| 1324 |
| 995 } // namespace onc | 1325 } // namespace onc |
| 996 } // namespace chromeos | 1326 } // namespace chromeos |
| OLD | NEW |