1 /*
2 * hidl interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004-2016, Roshan Pius <rpius@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
copyFile(const std::string & src_file_path,const std::string & dest_file_path)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 */
copyFileIfItExists(const std::string & src_file_path,const std::string & dest_file_path)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 */
ensureConfigFileExists(const std::string & config_file_path,const std::string & old_config_file_path)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
Supplicant(struct wpa_global * global)164 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
isValid()165 bool Supplicant::isValid()
166 {
167 // This top level object cannot be invalidated.
168 return true;
169 }
170
addInterface(const IfaceInfo & iface_info,addInterface_cb _hidl_cb)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
removeInterface(const IfaceInfo & iface_info,removeInterface_cb _hidl_cb)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
getInterface(const IfaceInfo & iface_info,getInterface_cb _hidl_cb)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
listInterfaces(listInterfaces_cb _hidl_cb)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
registerCallback(const sp<ISupplicantCallback> & callback,registerCallback_cb _hidl_cb)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
setDebugParams(ISupplicant::DebugLevel level,bool show_timestamp,bool show_keys,setDebugParams_cb _hidl_cb)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
setConcurrencyPriority(IfaceType type,setConcurrencyPriority_cb _hidl_cb)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
getDebugLevel()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
isDebugShowTimestampEnabled()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
isDebugShowKeysEnabled()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
terminate()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>>
addInterfaceInternal(const IfaceInfo & iface_info)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
removeInterfaceInternal(const IfaceInfo & iface_info)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>>
getInterfaceInternal(const IfaceInfo & iface_info)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>>
listInterfacesInternal()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
registerCallbackInternal(const sp<ISupplicantCallback> & callback)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
setDebugParamsInternal(ISupplicant::DebugLevel level,bool show_timestamp,bool show_keys)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
setConcurrencyPriorityInternal(IfaceType type)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