1 /* 2 * hidl interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2016, Jouni Malinen <j (at) w1.fi> 4 * Copyright (c) 2004-2016, Roshan Pius <rpius (at) google.com> 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10 #include "hidl_manager.h" 11 #include "hidl_return_util.h" 12 #include "supplicant.h" 13 14 #include <android-base/file.h> 15 #include <fcntl.h> 16 #include <sys/stat.h> 17 18 namespace { 19 using namespace android::hardware::wifi::supplicant::V1_2; 20 21 // Pre-populated interface params for interfaces controlled by wpa_supplicant. 22 // Note: This may differ for other OEM's. So, modify this accordingly. 23 constexpr char kIfaceDriverName[] = "nl80211"; 24 constexpr char kStaIfaceConfPath[] = 25 "/data/vendor/wifi/wpa/wpa_supplicant.conf"; 26 constexpr char kStaIfaceConfOverlayPath[] = 27 "/vendor/etc/wifi/wpa_supplicant_overlay.conf"; 28 constexpr char kP2pIfaceConfPath[] = 29 "/data/vendor/wifi/wpa/p2p_supplicant.conf"; 30 constexpr char kP2pIfaceConfOverlayPath[] = 31 "/vendor/etc/wifi/p2p_supplicant_overlay.conf"; 32 // Migrate conf files for existing devices. 33 constexpr char kSystemTemplateConfPath[] = 34 "/system/etc/wifi/wpa_supplicant.conf"; 35 constexpr char kVendorTemplateConfPath[] = 36 "/vendor/etc/wifi/wpa_supplicant.conf"; 37 constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf"; 38 constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf"; 39 constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 40 41 int copyFile( 42 const std::string& src_file_path, const std::string& dest_file_path) 43 { 44 std::string file_contents; 45 if (!android::base::ReadFileToString(src_file_path, &file_contents)) { 46 wpa_printf( 47 MSG_ERROR, "Failed to read from %s. Errno: %s", 48 src_file_path.c_str(), strerror(errno)); 49 return -1; 50 } 51 if (!android::base::WriteStringToFile( 52 file_contents, dest_file_path, kConfigFileMode, getuid(), 53 getgid())) { 54 wpa_printf( 55 MSG_ERROR, "Failed to write to %s. Errno: %s", 56 dest_file_path.c_str(), strerror(errno)); 57 return -1; 58 } 59 return 0; 60 } 61 62 /** 63 * Copy |src_file_path| to |dest_file_path| if it exists. 64 * 65 * Returns 1 if |src_file_path| does not exist or not accessible, 66 * Returns -1 if the copy fails. 67 * Returns 0 if the copy succeeds. 68 */ 69 int copyFileIfItExists( 70 const std::string& src_file_path, const std::string& dest_file_path) 71 { 72 int ret = access(src_file_path.c_str(), R_OK); 73 // Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT. 74 if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) { 75 return 1; 76 } 77 ret = copyFile(src_file_path, dest_file_path); 78 if (ret != 0) { 79 wpa_printf( 80 MSG_ERROR, "Failed copying %s to %s.", 81 src_file_path.c_str(), dest_file_path.c_str()); 82 return -1; 83 } 84 return 0; 85 } 86 87 /** 88 * Ensure that the specified config file pointed by |config_file_path| exists. 89 * a) If the |config_file_path| exists with the correct permissions, return. 90 * b) If the |config_file_path| does not exist, but |old_config_file_path| 91 * exists, copy over the contents of the |old_config_file_path| to 92 * |config_file_path|. 93 * c) If the |config_file_path| & |old_config_file_path| 94 * does not exists, copy over the contents of |template_config_file_path|. 95 */ 96 int ensureConfigFileExists( 97 const std::string& config_file_path, 98 const std::string& old_config_file_path) 99 { 100 int ret = access(config_file_path.c_str(), R_OK | W_OK); 101 if (ret == 0) { 102 return 0; 103 } 104 if (errno == EACCES) { 105 ret = chmod(config_file_path.c_str(), kConfigFileMode); 106 if (ret == 0) { 107 return 0; 108 } else { 109 wpa_printf( 110 MSG_ERROR, "Cannot set RW to %s. Errno: %s", 111 config_file_path.c_str(), strerror(errno)); 112 return -1; 113 } 114 } else if (errno != ENOENT) { 115 wpa_printf( 116 MSG_ERROR, "Cannot acces %s. Errno: %s", 117 config_file_path.c_str(), strerror(errno)); 118 return -1; 119 } 120 ret = copyFileIfItExists(old_config_file_path, config_file_path); 121 if (ret == 0) { 122 wpa_printf( 123 MSG_INFO, "Migrated conf file from %s to %s", 124 old_config_file_path.c_str(), config_file_path.c_str()); 125 unlink(old_config_file_path.c_str()); 126 return 0; 127 } else if (ret == -1) { 128 unlink(config_file_path.c_str()); 129 return -1; 130 } 131 ret = copyFileIfItExists(kVendorTemplateConfPath, config_file_path); 132 if (ret == 0) { 133 wpa_printf( 134 MSG_INFO, "Copied template conf file from %s to %s", 135 kVendorTemplateConfPath, config_file_path.c_str()); 136 return 0; 137 } else if (ret == -1) { 138 unlink(config_file_path.c_str()); 139 return -1; 140 } 141 ret = copyFileIfItExists(kSystemTemplateConfPath, config_file_path); 142 if (ret == 0) { 143 wpa_printf( 144 MSG_INFO, "Copied template conf file from %s to %s", 145 kSystemTemplateConfPath, config_file_path.c_str()); 146 return 0; 147 } else if (ret == -1) { 148 unlink(config_file_path.c_str()); 149 return -1; 150 } 151 // Did not create the conf file. 152 return -1; 153 } 154 } // namespace 155 156 namespace android { 157 namespace hardware { 158 namespace wifi { 159 namespace supplicant { 160 namespace V1_2 { 161 namespace implementation { 162 using hidl_return_util::validateAndCall; 163 164 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {} 165 bool Supplicant::isValid() 166 { 167 // This top level object cannot be invalidated. 168 return true; 169 } 170 171 Return<void> Supplicant::addInterface( 172 const IfaceInfo& iface_info, addInterface_cb _hidl_cb) 173 { 174 return validateAndCall( 175 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 176 &Supplicant::addInterfaceInternal, _hidl_cb, iface_info); 177 } 178 179 Return<void> Supplicant::removeInterface( 180 const IfaceInfo& iface_info, removeInterface_cb _hidl_cb) 181 { 182 return validateAndCall( 183 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 184 &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info); 185 } 186 187 Return<void> Supplicant::getInterface( 188 const IfaceInfo& iface_info, getInterface_cb _hidl_cb) 189 { 190 return validateAndCall( 191 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 192 &Supplicant::getInterfaceInternal, _hidl_cb, iface_info); 193 } 194 195 Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb) 196 { 197 return validateAndCall( 198 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 199 &Supplicant::listInterfacesInternal, _hidl_cb); 200 } 201 202 Return<void> Supplicant::registerCallback( 203 const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb) 204 { 205 return validateAndCall( 206 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 207 &Supplicant::registerCallbackInternal, _hidl_cb, callback); 208 } 209 210 Return<void> Supplicant::setDebugParams( 211 ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys, 212 setDebugParams_cb _hidl_cb) 213 { 214 return validateAndCall( 215 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 216 &Supplicant::setDebugParamsInternal, _hidl_cb, level, 217 show_timestamp, show_keys); 218 } 219 220 Return<void> Supplicant::setConcurrencyPriority( 221 IfaceType type, setConcurrencyPriority_cb _hidl_cb) 222 { 223 return validateAndCall( 224 this, SupplicantStatusCode::FAILURE_IFACE_INVALID, 225 &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type); 226 } 227 228 Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel() 229 { 230 // TODO: Add SupplicantStatus in this method return for uniformity with 231 // the other methods in supplicant HIDL interface. 232 return (ISupplicant::DebugLevel)wpa_debug_level; 233 } 234 235 Return<bool> Supplicant::isDebugShowTimestampEnabled() 236 { 237 // TODO: Add SupplicantStatus in this method return for uniformity with 238 // the other methods in supplicant HIDL interface. 239 return ((wpa_debug_timestamp != 0) ? true : false); 240 } 241 242 Return<bool> Supplicant::isDebugShowKeysEnabled() 243 { 244 // TODO: Add SupplicantStatus in this method return for uniformity with 245 // the other methods in supplicant HIDL interface. 246 return ((wpa_debug_show_keys != 0) ? true : false); 247 } 248 249 Return<void> Supplicant::terminate() 250 { 251 wpa_printf(MSG_INFO, "Terminating..."); 252 wpa_supplicant_terminate_proc(wpa_global_); 253 return Void(); 254 } 255 256 std::pair<SupplicantStatus, sp<ISupplicantIface>> 257 Supplicant::addInterfaceInternal(const IfaceInfo& iface_info) 258 { 259 android::sp<ISupplicantIface> iface; 260 261 // Check if required |ifname| argument is empty. 262 if (iface_info.name.empty()) { 263 return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}}; 264 } 265 // Try to get the wpa_supplicant record for this iface, return 266 // the iface object with the appropriate status code if it exists. 267 SupplicantStatus status; 268 std::tie(status, iface) = getInterfaceInternal(iface_info); 269 if (status.code == SupplicantStatusCode::SUCCESS) { 270 return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""}, 271 iface}; 272 } 273 274 struct wpa_interface iface_params = {}; 275 iface_params.driver = kIfaceDriverName; 276 if (iface_info.type == IfaceType::P2P) { 277 if (ensureConfigFileExists( 278 kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) { 279 wpa_printf( 280 MSG_ERROR, "Conf file does not exists: %s", 281 kP2pIfaceConfPath); 282 return {{SupplicantStatusCode::FAILURE_UNKNOWN, 283 "Conf file does not exist"}, 284 {}}; 285 } 286 iface_params.confname = kP2pIfaceConfPath; 287 int ret = access(kP2pIfaceConfOverlayPath, R_OK); 288 if (ret == 0) { 289 iface_params.confanother = kP2pIfaceConfOverlayPath; 290 } 291 } else { 292 if (ensureConfigFileExists( 293 kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) { 294 wpa_printf( 295 MSG_ERROR, "Conf file does not exists: %s", 296 kStaIfaceConfPath); 297 return {{SupplicantStatusCode::FAILURE_UNKNOWN, 298 "Conf file does not exist"}, 299 {}}; 300 } 301 iface_params.confname = kStaIfaceConfPath; 302 int ret = access(kStaIfaceConfOverlayPath, R_OK); 303 if (ret == 0) { 304 iface_params.confanother = kStaIfaceConfOverlayPath; 305 } 306 } 307 iface_params.ifname = iface_info.name.c_str(); 308 struct wpa_supplicant* wpa_s = 309 wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL); 310 if (!wpa_s) { 311 return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}}; 312 } 313 // The supplicant core creates a corresponding hidl object via 314 // HidlManager when |wpa_supplicant_add_iface| is called. 315 return getInterfaceInternal(iface_info); 316 } 317 318 SupplicantStatus Supplicant::removeInterfaceInternal( 319 const IfaceInfo& iface_info) 320 { 321 struct wpa_supplicant* wpa_s = 322 wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str()); 323 if (!wpa_s) { 324 return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}; 325 } 326 if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) { 327 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 328 } 329 return {SupplicantStatusCode::SUCCESS, ""}; 330 } 331 332 std::pair<SupplicantStatus, sp<ISupplicantIface>> 333 Supplicant::getInterfaceInternal(const IfaceInfo& iface_info) 334 { 335 struct wpa_supplicant* wpa_s = 336 wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str()); 337 if (!wpa_s) { 338 return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}, 339 nullptr}; 340 } 341 HidlManager* hidl_manager = HidlManager::getInstance(); 342 if (iface_info.type == IfaceType::P2P) { 343 android::sp<ISupplicantP2pIface> iface; 344 if (!hidl_manager || 345 hidl_manager->getP2pIfaceHidlObjectByIfname( 346 wpa_s->ifname, &iface)) { 347 return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, 348 iface}; 349 } 350 // Set this flag true here, since there is no HIDL initialize 351 // method for the p2p config, and the supplicant interface is 352 // not ready when the p2p iface is created. 353 wpa_s->conf->persistent_reconnect = true; 354 return {{SupplicantStatusCode::SUCCESS, ""}, iface}; 355 } else { 356 android::sp<ISupplicantStaIface> iface; 357 if (!hidl_manager || 358 hidl_manager->getStaIfaceHidlObjectByIfname( 359 wpa_s->ifname, &iface)) { 360 return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, 361 iface}; 362 } 363 return {{SupplicantStatusCode::SUCCESS, ""}, iface}; 364 } 365 } 366 367 std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>> 368 Supplicant::listInterfacesInternal() 369 { 370 std::vector<ISupplicant::IfaceInfo> ifaces; 371 for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s; 372 wpa_s = wpa_s->next) { 373 if (wpa_s->global->p2p_init_wpa_s == wpa_s) { 374 ifaces.emplace_back(ISupplicant::IfaceInfo{ 375 IfaceType::P2P, wpa_s->ifname}); 376 } else { 377 ifaces.emplace_back(ISupplicant::IfaceInfo{ 378 IfaceType::STA, wpa_s->ifname}); 379 } 380 } 381 return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)}; 382 } 383 384 SupplicantStatus Supplicant::registerCallbackInternal( 385 const sp<ISupplicantCallback>& callback) 386 { 387 HidlManager* hidl_manager = HidlManager::getInstance(); 388 if (!hidl_manager || 389 hidl_manager->addSupplicantCallbackHidlObject(callback)) { 390 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 391 } 392 return {SupplicantStatusCode::SUCCESS, ""}; 393 } 394 395 SupplicantStatus Supplicant::setDebugParamsInternal( 396 ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys) 397 { 398 if (wpa_supplicant_set_debug_params( 399 wpa_global_, static_cast<uint32_t>(level), show_timestamp, 400 show_keys)) { 401 return {SupplicantStatusCode::FAILURE_UNKNOWN, ""}; 402 } 403 return {SupplicantStatusCode::SUCCESS, ""}; 404 } 405 406 SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type) 407 { 408 if (type == IfaceType::STA) { 409 wpa_global_->conc_pref = 410 wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA; 411 } else if (type == IfaceType::P2P) { 412 wpa_global_->conc_pref = 413 wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P; 414 } else { 415 return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}; 416 } 417 return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}; 418 } 419 } // namespace implementation 420 } // namespace V1_2 421 } // namespace supplicant 422 } // namespace wifi 423 } // namespace hardware 424 } // namespace android 425