Branch data Line data Source code
1 : : /*
2 : : * WPA Supplicant / dbus-based control interface
3 : : * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : : #include <dbus/dbus.h>
11 : :
12 : : #include "common.h"
13 : : #include "eap_peer/eap_methods.h"
14 : : #include "common/ieee802_11_defs.h"
15 : : #include "eapol_supp/eapol_supp_sm.h"
16 : : #include "rsn_supp/wpa.h"
17 : : #include "../config.h"
18 : : #include "../wpa_supplicant_i.h"
19 : : #include "../driver_i.h"
20 : : #include "../notify.h"
21 : : #include "../wpas_glue.h"
22 : : #include "../bss.h"
23 : : #include "../scan.h"
24 : : #include "dbus_old.h"
25 : : #include "dbus_old_handlers.h"
26 : : #include "dbus_dict_helpers.h"
27 : :
28 : : extern int wpa_debug_level;
29 : : extern int wpa_debug_show_keys;
30 : : extern int wpa_debug_timestamp;
31 : :
32 : : /**
33 : : * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
34 : : * @message: Pointer to incoming dbus message this error refers to
35 : : * Returns: a dbus error message
36 : : *
37 : : * Convenience function to create and return an invalid options error
38 : : */
39 : 0 : DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
40 : : const char *arg)
41 : : {
42 : : DBusMessage *reply;
43 : :
44 : 0 : reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
45 : : "Did not receive correct message "
46 : : "arguments.");
47 [ # # ]: 0 : if (arg != NULL)
48 : 0 : dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
49 : : DBUS_TYPE_INVALID);
50 : :
51 : 0 : return reply;
52 : : }
53 : :
54 : :
55 : : /**
56 : : * wpas_dbus_new_success_reply - Return a new success reply message
57 : : * @message: Pointer to incoming dbus message this reply refers to
58 : : * Returns: a dbus message containing a single UINT32 that indicates
59 : : * success (ie, a value of 1)
60 : : *
61 : : * Convenience function to create and return a success reply message
62 : : */
63 : 0 : DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
64 : : {
65 : : DBusMessage *reply;
66 : 0 : unsigned int success = 1;
67 : :
68 : 0 : reply = dbus_message_new_method_return(message);
69 : 0 : dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
70 : : DBUS_TYPE_INVALID);
71 : 0 : return reply;
72 : : }
73 : :
74 : :
75 : : /**
76 : : * wpas_dbus_global_add_interface - Request registration of a network interface
77 : : * @message: Pointer to incoming dbus message
78 : : * @global: %wpa_supplicant global data structure
79 : : * Returns: The object path of the new interface object,
80 : : * or a dbus error message with more information
81 : : *
82 : : * Handler function for "addInterface" method call. Handles requests
83 : : * by dbus clients to register a network interface that wpa_supplicant
84 : : * will manage.
85 : : */
86 : 0 : DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
87 : : struct wpa_global *global)
88 : : {
89 : 0 : char *ifname = NULL;
90 : 0 : char *driver = NULL;
91 : 0 : char *driver_param = NULL;
92 : 0 : char *confname = NULL;
93 : 0 : char *bridge_ifname = NULL;
94 : 0 : DBusMessage *reply = NULL;
95 : : DBusMessageIter iter;
96 : :
97 : 0 : dbus_message_iter_init(message, &iter);
98 : :
99 : : /* First argument: interface name (DBUS_TYPE_STRING)
100 : : * Required; must be non-zero length
101 : : */
102 [ # # ]: 0 : if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
103 : 0 : goto error;
104 : 0 : dbus_message_iter_get_basic(&iter, &ifname);
105 [ # # ]: 0 : if (!os_strlen(ifname))
106 : 0 : goto error;
107 : :
108 : : /* Second argument: dict of options */
109 [ # # ]: 0 : if (dbus_message_iter_next(&iter)) {
110 : : DBusMessageIter iter_dict;
111 : : struct wpa_dbus_dict_entry entry;
112 : :
113 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
114 : 0 : goto error;
115 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
116 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
117 : 0 : goto error;
118 [ # # ][ # # ]: 0 : if (!strcmp(entry.key, "driver") &&
119 : 0 : (entry.type == DBUS_TYPE_STRING)) {
120 : 0 : driver = os_strdup(entry.str_value);
121 : 0 : wpa_dbus_dict_entry_clear(&entry);
122 [ # # ]: 0 : if (driver == NULL)
123 : 0 : goto error;
124 [ # # ][ # # ]: 0 : } else if (!strcmp(entry.key, "driver-params") &&
125 : 0 : (entry.type == DBUS_TYPE_STRING)) {
126 : 0 : driver_param = os_strdup(entry.str_value);
127 : 0 : wpa_dbus_dict_entry_clear(&entry);
128 [ # # ]: 0 : if (driver_param == NULL)
129 : 0 : goto error;
130 [ # # ][ # # ]: 0 : } else if (!strcmp(entry.key, "config-file") &&
131 : 0 : (entry.type == DBUS_TYPE_STRING)) {
132 : 0 : confname = os_strdup(entry.str_value);
133 : 0 : wpa_dbus_dict_entry_clear(&entry);
134 [ # # ]: 0 : if (confname == NULL)
135 : 0 : goto error;
136 [ # # ][ # # ]: 0 : } else if (!strcmp(entry.key, "bridge-ifname") &&
137 : 0 : (entry.type == DBUS_TYPE_STRING)) {
138 : 0 : bridge_ifname = os_strdup(entry.str_value);
139 : 0 : wpa_dbus_dict_entry_clear(&entry);
140 [ # # ]: 0 : if (bridge_ifname == NULL)
141 : 0 : goto error;
142 : : } else {
143 : 0 : wpa_dbus_dict_entry_clear(&entry);
144 : 0 : goto error;
145 : : }
146 : : }
147 : : }
148 : :
149 : : /*
150 : : * Try to get the wpa_supplicant record for this iface, return
151 : : * an error if we already control it.
152 : : */
153 [ # # ]: 0 : if (wpa_supplicant_get_iface(global, ifname) != NULL) {
154 : 0 : reply = dbus_message_new_error(message,
155 : : WPAS_ERROR_EXISTS_ERROR,
156 : : "wpa_supplicant already "
157 : : "controls this interface.");
158 : : } else {
159 : : struct wpa_supplicant *wpa_s;
160 : : struct wpa_interface iface;
161 : 0 : os_memset(&iface, 0, sizeof(iface));
162 : 0 : iface.ifname = ifname;
163 : 0 : iface.driver = driver;
164 : 0 : iface.driver_param = driver_param;
165 : 0 : iface.confname = confname;
166 : 0 : iface.bridge_ifname = bridge_ifname;
167 : : /* Otherwise, have wpa_supplicant attach to it. */
168 [ # # ]: 0 : if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
169 : 0 : const char *path = wpa_s->dbus_path;
170 : 0 : reply = dbus_message_new_method_return(message);
171 : 0 : dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
172 : : &path, DBUS_TYPE_INVALID);
173 : : } else {
174 : 0 : reply = dbus_message_new_error(message,
175 : : WPAS_ERROR_ADD_ERROR,
176 : : "wpa_supplicant "
177 : : "couldn't grab this "
178 : : "interface.");
179 : : }
180 : : }
181 : :
182 : : out:
183 : 0 : os_free(driver);
184 : 0 : os_free(driver_param);
185 : 0 : os_free(confname);
186 : 0 : os_free(bridge_ifname);
187 : 0 : return reply;
188 : :
189 : : error:
190 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
191 : 0 : goto out;
192 : : }
193 : :
194 : :
195 : : /**
196 : : * wpas_dbus_global_remove_interface - Request deregistration of an interface
197 : : * @message: Pointer to incoming dbus message
198 : : * @global: wpa_supplicant global data structure
199 : : * Returns: a dbus message containing a UINT32 indicating success (1) or
200 : : * failure (0), or returns a dbus error message with more information
201 : : *
202 : : * Handler function for "removeInterface" method call. Handles requests
203 : : * by dbus clients to deregister a network interface that wpa_supplicant
204 : : * currently manages.
205 : : */
206 : 0 : DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
207 : : struct wpa_global *global)
208 : : {
209 : : struct wpa_supplicant *wpa_s;
210 : : char *path;
211 : 0 : DBusMessage *reply = NULL;
212 : :
213 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
214 : : DBUS_TYPE_OBJECT_PATH, &path,
215 : : DBUS_TYPE_INVALID)) {
216 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
217 : 0 : goto out;
218 : : }
219 : :
220 : 0 : wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
221 [ # # ]: 0 : if (wpa_s == NULL) {
222 : 0 : reply = wpas_dbus_new_invalid_iface_error(message);
223 : 0 : goto out;
224 : : }
225 : :
226 [ # # ]: 0 : if (!wpa_supplicant_remove_iface(global, wpa_s, 0)) {
227 : 0 : reply = wpas_dbus_new_success_reply(message);
228 : : } else {
229 : 0 : reply = dbus_message_new_error(message,
230 : : WPAS_ERROR_REMOVE_ERROR,
231 : : "wpa_supplicant couldn't "
232 : : "remove this interface.");
233 : : }
234 : :
235 : : out:
236 : 0 : return reply;
237 : : }
238 : :
239 : :
240 : : /**
241 : : * wpas_dbus_global_get_interface - Get the object path for an interface name
242 : : * @message: Pointer to incoming dbus message
243 : : * @global: %wpa_supplicant global data structure
244 : : * Returns: The object path of the interface object,
245 : : * or a dbus error message with more information
246 : : *
247 : : * Handler function for "getInterface" method call. Handles requests
248 : : * by dbus clients for the object path of an specific network interface.
249 : : */
250 : 0 : DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
251 : : struct wpa_global *global)
252 : : {
253 : 0 : DBusMessage *reply = NULL;
254 : : const char *ifname;
255 : : const char *path;
256 : : struct wpa_supplicant *wpa_s;
257 : :
258 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
259 : : DBUS_TYPE_STRING, &ifname,
260 : : DBUS_TYPE_INVALID)) {
261 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
262 : 0 : goto out;
263 : : }
264 : :
265 : 0 : wpa_s = wpa_supplicant_get_iface(global, ifname);
266 [ # # ]: 0 : if (wpa_s == NULL) {
267 : 0 : reply = wpas_dbus_new_invalid_iface_error(message);
268 : 0 : goto out;
269 : : }
270 : :
271 : 0 : path = wpa_s->dbus_path;
272 : 0 : reply = dbus_message_new_method_return(message);
273 : 0 : dbus_message_append_args(reply,
274 : : DBUS_TYPE_OBJECT_PATH, &path,
275 : : DBUS_TYPE_INVALID);
276 : :
277 : : out:
278 : 0 : return reply;
279 : : }
280 : :
281 : :
282 : : /**
283 : : * wpas_dbus_global_set_debugparams- Set the debug params
284 : : * @message: Pointer to incoming dbus message
285 : : * @global: %wpa_supplicant global data structure
286 : : * Returns: a dbus message containing a UINT32 indicating success (1) or
287 : : * failure (0), or returns a dbus error message with more information
288 : : *
289 : : * Handler function for "setDebugParams" method call. Handles requests
290 : : * by dbus clients for the object path of an specific network interface.
291 : : */
292 : 0 : DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
293 : : struct wpa_global *global)
294 : : {
295 : 0 : DBusMessage *reply = NULL;
296 : : int debug_level;
297 : : dbus_bool_t debug_timestamp;
298 : : dbus_bool_t debug_show_keys;
299 : :
300 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
301 : : DBUS_TYPE_INT32, &debug_level,
302 : : DBUS_TYPE_BOOLEAN, &debug_timestamp,
303 : : DBUS_TYPE_BOOLEAN, &debug_show_keys,
304 : : DBUS_TYPE_INVALID)) {
305 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
306 : : }
307 : :
308 [ # # ]: 0 : if (wpa_supplicant_set_debug_params(global, debug_level,
309 : : debug_timestamp ? 1 : 0,
310 : : debug_show_keys ? 1 : 0)) {
311 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
312 : : }
313 : :
314 : 0 : reply = wpas_dbus_new_success_reply(message);
315 : :
316 : 0 : return reply;
317 : : }
318 : :
319 : :
320 : : /**
321 : : * wpas_dbus_iface_scan - Request a wireless scan on an interface
322 : : * @message: Pointer to incoming dbus message
323 : : * @wpa_s: wpa_supplicant structure for a network interface
324 : : * Returns: a dbus message containing a UINT32 indicating success (1) or
325 : : * failure (0)
326 : : *
327 : : * Handler function for "scan" method call of a network device. Requests
328 : : * that wpa_supplicant perform a wireless scan as soon as possible
329 : : * on a particular wireless interface.
330 : : */
331 : 0 : DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
332 : : struct wpa_supplicant *wpa_s)
333 : : {
334 : 0 : wpa_s->scan_req = MANUAL_SCAN_REQ;
335 : 0 : wpa_supplicant_req_scan(wpa_s, 0, 0);
336 : 0 : return wpas_dbus_new_success_reply(message);
337 : : }
338 : :
339 : :
340 : : /**
341 : : * wpas_dbus_iface_scan_results - Get the results of a recent scan request
342 : : * @message: Pointer to incoming dbus message
343 : : * @wpa_s: wpa_supplicant structure for a network interface
344 : : * Returns: a dbus message containing a dbus array of objects paths, or returns
345 : : * a dbus error message if not scan results could be found
346 : : *
347 : : * Handler function for "scanResults" method call of a network device. Returns
348 : : * a dbus message containing the object paths of wireless networks found.
349 : : */
350 : 0 : DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
351 : : struct wpa_supplicant *wpa_s)
352 : : {
353 : 0 : DBusMessage *reply = NULL;
354 : : DBusMessageIter iter;
355 : : DBusMessageIter sub_iter;
356 : : struct wpa_bss *bss;
357 : :
358 : : /* Create and initialize the return message */
359 : 0 : reply = dbus_message_new_method_return(message);
360 : 0 : dbus_message_iter_init_append(reply, &iter);
361 : 0 : dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
362 : : DBUS_TYPE_OBJECT_PATH_AS_STRING,
363 : : &sub_iter);
364 : :
365 : : /* Loop through scan results and append each result's object path */
366 [ # # ]: 0 : dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
367 : : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
368 : 0 : char *path = path_buf;
369 : :
370 : : /* Construct the object path for this network. Note that ':'
371 : : * is not a valid character in dbus object paths.
372 : : */
373 : 0 : os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
374 : : "%s/" WPAS_DBUS_BSSIDS_PART "/"
375 : : WPAS_DBUS_BSSID_FORMAT,
376 : 0 : wpa_s->dbus_path, MAC2STR(bss->bssid));
377 : 0 : dbus_message_iter_append_basic(&sub_iter,
378 : : DBUS_TYPE_OBJECT_PATH, &path);
379 : : }
380 : :
381 : 0 : dbus_message_iter_close_container(&iter, &sub_iter);
382 : :
383 : 0 : return reply;
384 : : }
385 : :
386 : :
387 : : /**
388 : : * wpas_dbus_bssid_properties - Return the properties of a scanned network
389 : : * @message: Pointer to incoming dbus message
390 : : * @wpa_s: wpa_supplicant structure for a network interface
391 : : * @res: wpa_supplicant scan result for which to get properties
392 : : * Returns: a dbus message containing the properties for the requested network
393 : : *
394 : : * Handler function for "properties" method call of a scanned network.
395 : : * Returns a dbus message containing the the properties.
396 : : */
397 : 0 : DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
398 : : struct wpa_supplicant *wpa_s,
399 : : struct wpa_bss *bss)
400 : : {
401 : : DBusMessage *reply;
402 : : DBusMessageIter iter, iter_dict;
403 : : const u8 *ie;
404 : :
405 : : /* Dump the properties into a dbus message */
406 : 0 : reply = dbus_message_new_method_return(message);
407 : :
408 : 0 : dbus_message_iter_init_append(reply, &iter);
409 [ # # ]: 0 : if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
410 : 0 : goto error;
411 : :
412 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
413 : 0 : (const char *) bss->bssid,
414 : : ETH_ALEN))
415 : 0 : goto error;
416 : :
417 : 0 : ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
418 [ # # ]: 0 : if (ie) {
419 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
420 : : (const char *) (ie + 2),
421 : 0 : ie[1]))
422 : 0 : goto error;
423 : : }
424 : :
425 : 0 : ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
426 [ # # ]: 0 : if (ie) {
427 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
428 : : (const char *) ie,
429 : 0 : ie[1] + 2))
430 : 0 : goto error;
431 : : }
432 : :
433 : 0 : ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
434 [ # # ]: 0 : if (ie) {
435 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
436 : : (const char *) ie,
437 : 0 : ie[1] + 2))
438 : 0 : goto error;
439 : : }
440 : :
441 : 0 : ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
442 [ # # ]: 0 : if (ie) {
443 [ # # ]: 0 : if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
444 : : (const char *) ie,
445 : 0 : ie[1] + 2))
446 : 0 : goto error;
447 : : }
448 : :
449 [ # # ]: 0 : if (bss->freq) {
450 [ # # ]: 0 : if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
451 : : bss->freq))
452 : 0 : goto error;
453 : : }
454 [ # # ]: 0 : if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
455 : 0 : bss->caps))
456 : 0 : goto error;
457 [ # # # # ]: 0 : if (!(bss->flags & WPA_BSS_QUAL_INVALID) &&
458 : 0 : !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual))
459 : 0 : goto error;
460 [ # # # # ]: 0 : if (!(bss->flags & WPA_BSS_NOISE_INVALID) &&
461 : 0 : !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise))
462 : 0 : goto error;
463 [ # # # # ]: 0 : if (!(bss->flags & WPA_BSS_LEVEL_INVALID) &&
464 : 0 : !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level))
465 : 0 : goto error;
466 [ # # ]: 0 : if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
467 : 0 : wpa_bss_get_max_rate(bss) * 500000))
468 : 0 : goto error;
469 : :
470 [ # # ]: 0 : if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
471 : 0 : goto error;
472 : :
473 : 0 : return reply;
474 : :
475 : : error:
476 [ # # ]: 0 : if (reply)
477 : 0 : dbus_message_unref(reply);
478 : 0 : return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
479 : : "an internal error occurred returning "
480 : : "BSSID properties.");
481 : : }
482 : :
483 : :
484 : : /**
485 : : * wpas_dbus_iface_capabilities - Return interface capabilities
486 : : * @message: Pointer to incoming dbus message
487 : : * @wpa_s: wpa_supplicant structure for a network interface
488 : : * Returns: A dbus message containing a dict of strings
489 : : *
490 : : * Handler function for "capabilities" method call of an interface.
491 : : */
492 : 0 : DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
493 : : struct wpa_supplicant *wpa_s)
494 : : {
495 : 0 : DBusMessage *reply = NULL;
496 : : struct wpa_driver_capa capa;
497 : : int res;
498 : : DBusMessageIter iter, iter_dict;
499 : : char **eap_methods;
500 : : size_t num_items;
501 : 0 : dbus_bool_t strict = FALSE;
502 : : DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
503 : :
504 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
505 : : DBUS_TYPE_BOOLEAN, &strict,
506 : : DBUS_TYPE_INVALID))
507 : 0 : strict = FALSE;
508 : :
509 : 0 : reply = dbus_message_new_method_return(message);
510 : :
511 : 0 : dbus_message_iter_init_append(reply, &iter);
512 [ # # ]: 0 : if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
513 : 0 : goto error;
514 : :
515 : : /* EAP methods */
516 : 0 : eap_methods = eap_get_names_as_string_array(&num_items);
517 [ # # ]: 0 : if (eap_methods) {
518 : 0 : dbus_bool_t success = FALSE;
519 : 0 : size_t i = 0;
520 : :
521 : 0 : success = wpa_dbus_dict_append_string_array(
522 : : &iter_dict, "eap", (const char **) eap_methods,
523 : : num_items);
524 : :
525 : : /* free returned method array */
526 [ # # ]: 0 : while (eap_methods[i])
527 : 0 : os_free(eap_methods[i++]);
528 : 0 : os_free(eap_methods);
529 : :
530 [ # # ]: 0 : if (!success)
531 : 0 : goto error;
532 : : }
533 : :
534 : 0 : res = wpa_drv_get_capa(wpa_s, &capa);
535 : :
536 : : /***** pairwise cipher */
537 [ # # ]: 0 : if (res < 0) {
538 [ # # ]: 0 : if (!strict) {
539 : 0 : const char *args[] = {"CCMP", "TKIP", "NONE"};
540 [ # # ]: 0 : if (!wpa_dbus_dict_append_string_array(
541 : : &iter_dict, "pairwise", args,
542 : : ARRAY_SIZE(args)))
543 : 0 : goto error;
544 : : }
545 : : } else {
546 [ # # ]: 0 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
547 : : &iter_dict_entry,
548 : : &iter_dict_val,
549 : : &iter_array))
550 : 0 : goto error;
551 : :
552 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
553 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
554 : : &iter_array, "CCMP"))
555 : 0 : goto error;
556 : : }
557 : :
558 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
559 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
560 : : &iter_array, "TKIP"))
561 : 0 : goto error;
562 : : }
563 : :
564 [ # # ]: 0 : if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
565 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
566 : : &iter_array, "NONE"))
567 : 0 : goto error;
568 : : }
569 : :
570 [ # # ]: 0 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
571 : : &iter_dict_entry,
572 : : &iter_dict_val,
573 : : &iter_array))
574 : 0 : goto error;
575 : : }
576 : :
577 : : /***** group cipher */
578 [ # # ]: 0 : if (res < 0) {
579 [ # # ]: 0 : if (!strict) {
580 : 0 : const char *args[] = {
581 : : "CCMP", "TKIP", "WEP104", "WEP40"
582 : : };
583 [ # # ]: 0 : if (!wpa_dbus_dict_append_string_array(
584 : : &iter_dict, "group", args,
585 : : ARRAY_SIZE(args)))
586 : 0 : goto error;
587 : : }
588 : : } else {
589 [ # # ]: 0 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
590 : : &iter_dict_entry,
591 : : &iter_dict_val,
592 : : &iter_array))
593 : 0 : goto error;
594 : :
595 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
596 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
597 : : &iter_array, "CCMP"))
598 : 0 : goto error;
599 : : }
600 : :
601 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
602 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
603 : : &iter_array, "TKIP"))
604 : 0 : goto error;
605 : : }
606 : :
607 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
608 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
609 : : &iter_array, "WEP104"))
610 : 0 : goto error;
611 : : }
612 : :
613 [ # # ]: 0 : if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
614 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
615 : : &iter_array, "WEP40"))
616 : 0 : goto error;
617 : : }
618 : :
619 [ # # ]: 0 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
620 : : &iter_dict_entry,
621 : : &iter_dict_val,
622 : : &iter_array))
623 : 0 : goto error;
624 : : }
625 : :
626 : : /***** key management */
627 [ # # ]: 0 : if (res < 0) {
628 [ # # ]: 0 : if (!strict) {
629 : 0 : const char *args[] = {
630 : : "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
631 : : "NONE"
632 : : };
633 [ # # ]: 0 : if (!wpa_dbus_dict_append_string_array(
634 : : &iter_dict, "key_mgmt", args,
635 : : ARRAY_SIZE(args)))
636 : 0 : goto error;
637 : : }
638 : : } else {
639 [ # # ]: 0 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
640 : : &iter_dict_entry,
641 : : &iter_dict_val,
642 : : &iter_array))
643 : 0 : goto error;
644 : :
645 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(&iter_array,
646 : : "NONE"))
647 : 0 : goto error;
648 : :
649 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(&iter_array,
650 : : "IEEE8021X"))
651 : 0 : goto error;
652 : :
653 [ # # ]: 0 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
654 : : WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
655 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
656 : : &iter_array, "WPA-EAP"))
657 : 0 : goto error;
658 : : }
659 : :
660 [ # # ]: 0 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
661 : : WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
662 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
663 : : &iter_array, "WPA-PSK"))
664 : 0 : goto error;
665 : : }
666 : :
667 [ # # ]: 0 : if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
668 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
669 : : &iter_array, "WPA-NONE"))
670 : 0 : goto error;
671 : : }
672 : :
673 [ # # ]: 0 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
674 : : &iter_dict_entry,
675 : : &iter_dict_val,
676 : : &iter_array))
677 : 0 : goto error;
678 : : }
679 : :
680 : : /***** WPA protocol */
681 [ # # ]: 0 : if (res < 0) {
682 [ # # ]: 0 : if (!strict) {
683 : 0 : const char *args[] = { "RSN", "WPA" };
684 [ # # ]: 0 : if (!wpa_dbus_dict_append_string_array(
685 : : &iter_dict, "proto", args,
686 : : ARRAY_SIZE(args)))
687 : 0 : goto error;
688 : : }
689 : : } else {
690 [ # # ]: 0 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
691 : : &iter_dict_entry,
692 : : &iter_dict_val,
693 : : &iter_array))
694 : 0 : goto error;
695 : :
696 [ # # ]: 0 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
697 : : WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
698 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
699 : : &iter_array, "RSN"))
700 : 0 : goto error;
701 : : }
702 : :
703 [ # # ]: 0 : if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
704 : : WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
705 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
706 : : &iter_array, "WPA"))
707 : 0 : goto error;
708 : : }
709 : :
710 [ # # ]: 0 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
711 : : &iter_dict_entry,
712 : : &iter_dict_val,
713 : : &iter_array))
714 : 0 : goto error;
715 : : }
716 : :
717 : : /***** auth alg */
718 [ # # ]: 0 : if (res < 0) {
719 [ # # ]: 0 : if (!strict) {
720 : 0 : const char *args[] = { "OPEN", "SHARED", "LEAP" };
721 [ # # ]: 0 : if (!wpa_dbus_dict_append_string_array(
722 : : &iter_dict, "auth_alg", args,
723 : : ARRAY_SIZE(args)))
724 : 0 : goto error;
725 : : }
726 : : } else {
727 [ # # ]: 0 : if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
728 : : &iter_dict_entry,
729 : : &iter_dict_val,
730 : : &iter_array))
731 : 0 : goto error;
732 : :
733 [ # # ]: 0 : if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
734 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
735 : : &iter_array, "OPEN"))
736 : 0 : goto error;
737 : : }
738 : :
739 [ # # ]: 0 : if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
740 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
741 : : &iter_array, "SHARED"))
742 : 0 : goto error;
743 : : }
744 : :
745 [ # # ]: 0 : if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
746 [ # # ]: 0 : if (!wpa_dbus_dict_string_array_add_element(
747 : : &iter_array, "LEAP"))
748 : 0 : goto error;
749 : : }
750 : :
751 [ # # ]: 0 : if (!wpa_dbus_dict_end_string_array(&iter_dict,
752 : : &iter_dict_entry,
753 : : &iter_dict_val,
754 : : &iter_array))
755 : 0 : goto error;
756 : : }
757 : :
758 [ # # ]: 0 : if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
759 : 0 : goto error;
760 : :
761 : 0 : return reply;
762 : :
763 : : error:
764 [ # # ]: 0 : if (reply)
765 : 0 : dbus_message_unref(reply);
766 : 0 : return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
767 : : "an internal error occurred returning "
768 : : "interface capabilities.");
769 : : }
770 : :
771 : :
772 : : /**
773 : : * wpas_dbus_iface_add_network - Add a new configured network
774 : : * @message: Pointer to incoming dbus message
775 : : * @wpa_s: wpa_supplicant structure for a network interface
776 : : * Returns: A dbus message containing the object path of the new network
777 : : *
778 : : * Handler function for "addNetwork" method call of a network interface.
779 : : */
780 : 0 : DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
781 : : struct wpa_supplicant *wpa_s)
782 : : {
783 : 0 : DBusMessage *reply = NULL;
784 : : struct wpa_ssid *ssid;
785 : 0 : char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
786 : :
787 : 0 : ssid = wpa_config_add_network(wpa_s->conf);
788 [ # # ]: 0 : if (ssid == NULL) {
789 : 0 : reply = dbus_message_new_error(message,
790 : : WPAS_ERROR_ADD_NETWORK_ERROR,
791 : : "wpa_supplicant could not add "
792 : : "a network on this interface.");
793 : 0 : goto out;
794 : : }
795 : 0 : wpas_notify_network_added(wpa_s, ssid);
796 : 0 : ssid->disabled = 1;
797 : 0 : wpa_config_set_network_defaults(ssid);
798 : :
799 : : /* Construct the object path for this network. */
800 : 0 : os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
801 : : "%s/" WPAS_DBUS_NETWORKS_PART "/%d",
802 : : wpa_s->dbus_path, ssid->id);
803 : :
804 : 0 : reply = dbus_message_new_method_return(message);
805 : 0 : dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
806 : : &path, DBUS_TYPE_INVALID);
807 : :
808 : : out:
809 : 0 : return reply;
810 : : }
811 : :
812 : :
813 : : /**
814 : : * wpas_dbus_iface_remove_network - Remove a configured network
815 : : * @message: Pointer to incoming dbus message
816 : : * @wpa_s: wpa_supplicant structure for a network interface
817 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
818 : : * failure (0)
819 : : *
820 : : * Handler function for "removeNetwork" method call of a network interface.
821 : : */
822 : 0 : DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
823 : : struct wpa_supplicant *wpa_s)
824 : : {
825 : 0 : DBusMessage *reply = NULL;
826 : : const char *op;
827 : 0 : char *iface = NULL, *net_id = NULL;
828 : : int id;
829 : : struct wpa_ssid *ssid;
830 : :
831 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
832 : : DBUS_TYPE_OBJECT_PATH, &op,
833 : : DBUS_TYPE_INVALID)) {
834 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
835 : 0 : goto out;
836 : : }
837 : :
838 : : /* Extract the network ID */
839 : 0 : iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
840 [ # # ]: 0 : if (iface == NULL) {
841 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
842 : 0 : goto out;
843 : : }
844 : :
845 : : /* Ensure the network is actually a child of this interface */
846 [ # # ]: 0 : if (os_strcmp(iface, wpa_s->dbus_path) != 0) {
847 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
848 : 0 : goto out;
849 : : }
850 : :
851 : 0 : id = strtoul(net_id, NULL, 10);
852 : 0 : ssid = wpa_config_get_network(wpa_s->conf, id);
853 [ # # ]: 0 : if (ssid == NULL) {
854 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
855 : 0 : goto out;
856 : : }
857 : :
858 : 0 : wpas_notify_network_removed(wpa_s, ssid);
859 : :
860 [ # # ]: 0 : if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
861 : 0 : reply = dbus_message_new_error(message,
862 : : WPAS_ERROR_REMOVE_NETWORK_ERROR,
863 : : "error removing the specified "
864 : : "on this interface.");
865 : 0 : goto out;
866 : : }
867 : :
868 [ # # ]: 0 : if (ssid == wpa_s->current_ssid)
869 : 0 : wpa_supplicant_deauthenticate(wpa_s,
870 : : WLAN_REASON_DEAUTH_LEAVING);
871 : 0 : reply = wpas_dbus_new_success_reply(message);
872 : :
873 : : out:
874 : 0 : os_free(iface);
875 : 0 : os_free(net_id);
876 : 0 : return reply;
877 : : }
878 : :
879 : :
880 : : static const char *dont_quote[] = {
881 : : "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
882 : : "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
883 : : "bssid", NULL
884 : : };
885 : :
886 : :
887 : 0 : static dbus_bool_t should_quote_opt(const char *key)
888 : : {
889 : 0 : int i = 0;
890 [ # # ]: 0 : while (dont_quote[i] != NULL) {
891 [ # # ]: 0 : if (strcmp(key, dont_quote[i]) == 0)
892 : 0 : return FALSE;
893 : 0 : i++;
894 : : }
895 : 0 : return TRUE;
896 : : }
897 : :
898 : :
899 : : /**
900 : : * wpas_dbus_iface_set_network - Set options for a configured network
901 : : * @message: Pointer to incoming dbus message
902 : : * @wpa_s: wpa_supplicant structure for a network interface
903 : : * @ssid: wpa_ssid structure for a configured network
904 : : * Returns: a dbus message containing a UINT32 indicating success (1) or
905 : : * failure (0)
906 : : *
907 : : * Handler function for "set" method call of a configured network.
908 : : */
909 : 0 : DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
910 : : struct wpa_supplicant *wpa_s,
911 : : struct wpa_ssid *ssid)
912 : : {
913 : 0 : DBusMessage *reply = NULL;
914 : 0 : struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
915 : : DBusMessageIter iter, iter_dict;
916 : :
917 : 0 : dbus_message_iter_init(message, &iter);
918 : :
919 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) {
920 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
921 : 0 : goto out;
922 : : }
923 : :
924 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
925 : 0 : char *value = NULL;
926 : 0 : size_t size = 50;
927 : : int ret;
928 : :
929 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
930 : 0 : reply = wpas_dbus_new_invalid_opts_error(message,
931 : : NULL);
932 : 0 : goto out;
933 : : }
934 : :
935 : : /* Type conversions, since wpa_supplicant wants strings */
936 [ # # ][ # # ]: 0 : if (entry.type == DBUS_TYPE_ARRAY &&
937 : 0 : entry.array_type == DBUS_TYPE_BYTE) {
938 [ # # ]: 0 : if (entry.array_len <= 0)
939 : 0 : goto error;
940 : :
941 : 0 : size = entry.array_len * 2 + 1;
942 : 0 : value = os_zalloc(size);
943 [ # # ]: 0 : if (value == NULL)
944 : 0 : goto error;
945 : 0 : ret = wpa_snprintf_hex(value, size,
946 : 0 : (u8 *) entry.bytearray_value,
947 : 0 : entry.array_len);
948 [ # # ]: 0 : if (ret <= 0)
949 : 0 : goto error;
950 [ # # ]: 0 : } else if (entry.type == DBUS_TYPE_STRING) {
951 [ # # ]: 0 : if (should_quote_opt(entry.key)) {
952 : 0 : size = os_strlen(entry.str_value);
953 : : /* Zero-length option check */
954 [ # # ]: 0 : if (size <= 0)
955 : 0 : goto error;
956 : 0 : size += 3; /* For quotes and terminator */
957 : 0 : value = os_zalloc(size);
958 [ # # ]: 0 : if (value == NULL)
959 : 0 : goto error;
960 : 0 : ret = os_snprintf(value, size, "\"%s\"",
961 : : entry.str_value);
962 [ # # ][ # # ]: 0 : if (ret < 0 || (size_t) ret != (size - 1))
963 : : goto error;
964 : : } else {
965 : 0 : value = os_strdup(entry.str_value);
966 [ # # ]: 0 : if (value == NULL)
967 : 0 : goto error;
968 : : }
969 [ # # ]: 0 : } else if (entry.type == DBUS_TYPE_UINT32) {
970 : 0 : value = os_zalloc(size);
971 [ # # ]: 0 : if (value == NULL)
972 : 0 : goto error;
973 : 0 : ret = os_snprintf(value, size, "%u",
974 : : entry.uint32_value);
975 [ # # ]: 0 : if (ret <= 0)
976 : 0 : goto error;
977 [ # # ]: 0 : } else if (entry.type == DBUS_TYPE_INT32) {
978 : 0 : value = os_zalloc(size);
979 [ # # ]: 0 : if (value == NULL)
980 : 0 : goto error;
981 : 0 : ret = os_snprintf(value, size, "%d",
982 : : entry.int32_value);
983 [ # # ]: 0 : if (ret <= 0)
984 : 0 : goto error;
985 : : } else
986 : 0 : goto error;
987 : :
988 [ # # ]: 0 : if (wpa_config_set(ssid, entry.key, value, 0) < 0)
989 : 0 : goto error;
990 : :
991 [ # # ][ # # ]: 0 : if ((os_strcmp(entry.key, "psk") == 0 &&
992 [ # # ][ # # ]: 0 : value[0] == '"' && ssid->ssid_len) ||
993 [ # # ]: 0 : (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
994 : 0 : wpa_config_update_psk(ssid);
995 [ # # ]: 0 : else if (os_strcmp(entry.key, "priority") == 0)
996 : 0 : wpa_config_update_prio_list(wpa_s->conf);
997 : :
998 : 0 : os_free(value);
999 : 0 : wpa_dbus_dict_entry_clear(&entry);
1000 : 0 : continue;
1001 : :
1002 : : error:
1003 : 0 : os_free(value);
1004 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
1005 : 0 : wpa_dbus_dict_entry_clear(&entry);
1006 : 0 : break;
1007 : : }
1008 : :
1009 [ # # ]: 0 : if (!reply)
1010 : 0 : reply = wpas_dbus_new_success_reply(message);
1011 : :
1012 : : out:
1013 : 0 : return reply;
1014 : : }
1015 : :
1016 : :
1017 : : /**
1018 : : * wpas_dbus_iface_enable_network - Mark a configured network as enabled
1019 : : * @message: Pointer to incoming dbus message
1020 : : * @wpa_s: wpa_supplicant structure for a network interface
1021 : : * @ssid: wpa_ssid structure for a configured network
1022 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1023 : : * failure (0)
1024 : : *
1025 : : * Handler function for "enable" method call of a configured network.
1026 : : */
1027 : 0 : DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
1028 : : struct wpa_supplicant *wpa_s,
1029 : : struct wpa_ssid *ssid)
1030 : : {
1031 : 0 : wpa_supplicant_enable_network(wpa_s, ssid);
1032 : 0 : return wpas_dbus_new_success_reply(message);
1033 : : }
1034 : :
1035 : :
1036 : : /**
1037 : : * wpas_dbus_iface_disable_network - Mark a configured network as disabled
1038 : : * @message: Pointer to incoming dbus message
1039 : : * @wpa_s: wpa_supplicant structure for a network interface
1040 : : * @ssid: wpa_ssid structure for a configured network
1041 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1042 : : * failure (0)
1043 : : *
1044 : : * Handler function for "disable" method call of a configured network.
1045 : : */
1046 : 0 : DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
1047 : : struct wpa_supplicant *wpa_s,
1048 : : struct wpa_ssid *ssid)
1049 : : {
1050 : 0 : wpa_supplicant_disable_network(wpa_s, ssid);
1051 : 0 : return wpas_dbus_new_success_reply(message);
1052 : : }
1053 : :
1054 : :
1055 : : /**
1056 : : * wpas_dbus_iface_select_network - Attempt association with a configured network
1057 : : * @message: Pointer to incoming dbus message
1058 : : * @wpa_s: wpa_supplicant structure for a network interface
1059 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1060 : : * failure (0)
1061 : : *
1062 : : * Handler function for "selectNetwork" method call of network interface.
1063 : : */
1064 : 0 : DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
1065 : : struct wpa_supplicant *wpa_s)
1066 : : {
1067 : 0 : DBusMessage *reply = NULL;
1068 : : const char *op;
1069 : : struct wpa_ssid *ssid;
1070 : 0 : char *iface_obj_path = NULL;
1071 : 0 : char *network = NULL;
1072 : :
1073 [ # # ]: 0 : if (os_strlen(dbus_message_get_signature(message)) == 0) {
1074 : : /* Any network */
1075 : 0 : ssid = NULL;
1076 : : } else {
1077 : : int nid;
1078 : :
1079 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL,
1080 : : DBUS_TYPE_OBJECT_PATH, &op,
1081 : : DBUS_TYPE_INVALID)) {
1082 : 0 : reply = wpas_dbus_new_invalid_opts_error(message,
1083 : : NULL);
1084 : 0 : goto out;
1085 : : }
1086 : :
1087 : : /* Extract the network number */
1088 : 0 : iface_obj_path = wpas_dbus_decompose_object_path(op,
1089 : : &network,
1090 : : NULL);
1091 [ # # ]: 0 : if (iface_obj_path == NULL) {
1092 : 0 : reply = wpas_dbus_new_invalid_iface_error(message);
1093 : 0 : goto out;
1094 : : }
1095 : : /* Ensure the object path really points to this interface */
1096 [ # # ]: 0 : if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) {
1097 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
1098 : 0 : goto out;
1099 : : }
1100 : :
1101 : 0 : nid = strtoul(network, NULL, 10);
1102 [ # # ]: 0 : if (errno == EINVAL) {
1103 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
1104 : 0 : goto out;
1105 : : }
1106 : :
1107 : 0 : ssid = wpa_config_get_network(wpa_s->conf, nid);
1108 [ # # ]: 0 : if (ssid == NULL) {
1109 : 0 : reply = wpas_dbus_new_invalid_network_error(message);
1110 : 0 : goto out;
1111 : : }
1112 : : }
1113 : :
1114 : : /* Finally, associate with the network */
1115 : 0 : wpa_supplicant_select_network(wpa_s, ssid);
1116 : :
1117 : 0 : reply = wpas_dbus_new_success_reply(message);
1118 : :
1119 : : out:
1120 : 0 : os_free(iface_obj_path);
1121 : 0 : os_free(network);
1122 : 0 : return reply;
1123 : : }
1124 : :
1125 : :
1126 : : /**
1127 : : * wpas_dbus_iface_disconnect - Terminate the current connection
1128 : : * @message: Pointer to incoming dbus message
1129 : : * @wpa_s: wpa_supplicant structure for a network interface
1130 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1131 : : * failure (0)
1132 : : *
1133 : : * Handler function for "disconnect" method call of network interface.
1134 : : */
1135 : 0 : DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
1136 : : struct wpa_supplicant *wpa_s)
1137 : : {
1138 : 0 : wpa_s->disconnected = 1;
1139 : 0 : wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1140 : :
1141 : 0 : return wpas_dbus_new_success_reply(message);
1142 : : }
1143 : :
1144 : :
1145 : : /**
1146 : : * wpas_dbus_iface_set_ap_scan - Control roaming mode
1147 : : * @message: Pointer to incoming dbus message
1148 : : * @wpa_s: wpa_supplicant structure for a network interface
1149 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1150 : : * failure (0)
1151 : : *
1152 : : * Handler function for "setAPScan" method call.
1153 : : */
1154 : 0 : DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
1155 : : struct wpa_supplicant *wpa_s)
1156 : : {
1157 : 0 : DBusMessage *reply = NULL;
1158 : 0 : dbus_uint32_t ap_scan = 1;
1159 : :
1160 [ # # ]: 0 : if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
1161 : : DBUS_TYPE_INVALID)) {
1162 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1163 : 0 : goto out;
1164 : : }
1165 : :
1166 [ # # ]: 0 : if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
1167 : 0 : reply = wpas_dbus_new_invalid_opts_error(message, NULL);
1168 : 0 : goto out;
1169 : : }
1170 : :
1171 : 0 : reply = wpas_dbus_new_success_reply(message);
1172 : :
1173 : : out:
1174 : 0 : return reply;
1175 : : }
1176 : :
1177 : :
1178 : : /**
1179 : : * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
1180 : : * @message: Pointer to incoming dbus message
1181 : : * @wpa_s: wpa_supplicant structure for a network interface
1182 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1183 : : * failure (0)
1184 : : *
1185 : : * Handler function for "setSmartcardModules" method call.
1186 : : */
1187 : 0 : DBusMessage * wpas_dbus_iface_set_smartcard_modules(
1188 : : DBusMessage *message, struct wpa_supplicant *wpa_s)
1189 : : {
1190 : : DBusMessageIter iter, iter_dict;
1191 : 0 : char *opensc_engine_path = NULL;
1192 : 0 : char *pkcs11_engine_path = NULL;
1193 : 0 : char *pkcs11_module_path = NULL;
1194 : : struct wpa_dbus_dict_entry entry;
1195 : :
1196 [ # # ]: 0 : if (!dbus_message_iter_init(message, &iter))
1197 : 0 : goto error;
1198 : :
1199 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
1200 : 0 : goto error;
1201 : :
1202 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1203 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
1204 : 0 : goto error;
1205 [ # # ][ # # ]: 0 : if (!strcmp(entry.key, "opensc_engine_path") &&
1206 : 0 : (entry.type == DBUS_TYPE_STRING)) {
1207 : 0 : opensc_engine_path = os_strdup(entry.str_value);
1208 [ # # ]: 0 : if (opensc_engine_path == NULL)
1209 : 0 : goto error;
1210 [ # # ][ # # ]: 0 : } else if (!strcmp(entry.key, "pkcs11_engine_path") &&
1211 : 0 : (entry.type == DBUS_TYPE_STRING)) {
1212 : 0 : pkcs11_engine_path = os_strdup(entry.str_value);
1213 [ # # ]: 0 : if (pkcs11_engine_path == NULL)
1214 : 0 : goto error;
1215 [ # # ][ # # ]: 0 : } else if (!strcmp(entry.key, "pkcs11_module_path") &&
1216 : 0 : (entry.type == DBUS_TYPE_STRING)) {
1217 : 0 : pkcs11_module_path = os_strdup(entry.str_value);
1218 [ # # ]: 0 : if (pkcs11_module_path == NULL)
1219 : 0 : goto error;
1220 : : } else {
1221 : 0 : wpa_dbus_dict_entry_clear(&entry);
1222 : 0 : goto error;
1223 : : }
1224 : 0 : wpa_dbus_dict_entry_clear(&entry);
1225 : : }
1226 : :
1227 : 0 : os_free(wpa_s->conf->opensc_engine_path);
1228 : 0 : wpa_s->conf->opensc_engine_path = opensc_engine_path;
1229 : 0 : os_free(wpa_s->conf->pkcs11_engine_path);
1230 : 0 : wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
1231 : 0 : os_free(wpa_s->conf->pkcs11_module_path);
1232 : 0 : wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
1233 : :
1234 : 0 : wpa_sm_set_eapol(wpa_s->wpa, NULL);
1235 : 0 : eapol_sm_deinit(wpa_s->eapol);
1236 : 0 : wpa_s->eapol = NULL;
1237 : 0 : wpa_supplicant_init_eapol(wpa_s);
1238 : 0 : wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
1239 : :
1240 : 0 : return wpas_dbus_new_success_reply(message);
1241 : :
1242 : : error:
1243 : 0 : os_free(opensc_engine_path);
1244 : 0 : os_free(pkcs11_engine_path);
1245 : 0 : os_free(pkcs11_module_path);
1246 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
1247 : : }
1248 : :
1249 : :
1250 : : /**
1251 : : * wpas_dbus_iface_get_state - Get interface state
1252 : : * @message: Pointer to incoming dbus message
1253 : : * @wpa_s: wpa_supplicant structure for a network interface
1254 : : * Returns: A dbus message containing a STRING representing the current
1255 : : * interface state
1256 : : *
1257 : : * Handler function for "state" method call.
1258 : : */
1259 : 0 : DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
1260 : : struct wpa_supplicant *wpa_s)
1261 : : {
1262 : 0 : DBusMessage *reply = NULL;
1263 : : const char *str_state;
1264 : :
1265 : 0 : reply = dbus_message_new_method_return(message);
1266 [ # # ]: 0 : if (reply != NULL) {
1267 : 0 : str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1268 : 0 : dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
1269 : : DBUS_TYPE_INVALID);
1270 : : }
1271 : :
1272 : 0 : return reply;
1273 : : }
1274 : :
1275 : :
1276 : : /**
1277 : : * wpas_dbus_iface_get_scanning - Get interface scanning state
1278 : : * @message: Pointer to incoming dbus message
1279 : : * @wpa_s: wpa_supplicant structure for a network interface
1280 : : * Returns: A dbus message containing whether the interface is scanning
1281 : : *
1282 : : * Handler function for "scanning" method call.
1283 : : */
1284 : 0 : DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
1285 : : struct wpa_supplicant *wpa_s)
1286 : : {
1287 : 0 : DBusMessage *reply = NULL;
1288 : 0 : dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
1289 : :
1290 : 0 : reply = dbus_message_new_method_return(message);
1291 [ # # ]: 0 : if (reply != NULL) {
1292 : 0 : dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
1293 : : DBUS_TYPE_INVALID);
1294 : : } else {
1295 : 0 : wpa_printf(MSG_ERROR, "dbus: Not enough memory to return "
1296 : : "scanning state");
1297 : : }
1298 : :
1299 : 0 : return reply;
1300 : : }
1301 : :
1302 : :
1303 : : #ifndef CONFIG_NO_CONFIG_BLOBS
1304 : :
1305 : : /**
1306 : : * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
1307 : : * @message: Pointer to incoming dbus message
1308 : : * @wpa_s: %wpa_supplicant data structure
1309 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1310 : : * failure (0)
1311 : : *
1312 : : * Asks wpa_supplicant to internally store a one or more binary blobs.
1313 : : */
1314 : 0 : DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
1315 : : struct wpa_supplicant *wpa_s)
1316 : : {
1317 : 0 : DBusMessage *reply = NULL;
1318 : 0 : struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
1319 : : DBusMessageIter iter, iter_dict;
1320 : :
1321 : 0 : dbus_message_iter_init(message, &iter);
1322 : :
1323 [ # # ]: 0 : if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
1324 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
1325 : :
1326 [ # # ]: 0 : while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1327 : : struct wpa_config_blob *blob;
1328 : :
1329 [ # # ]: 0 : if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1330 : 0 : reply = wpas_dbus_new_invalid_opts_error(message,
1331 : : NULL);
1332 : 0 : break;
1333 : : }
1334 : :
1335 [ # # ][ # # ]: 0 : if (entry.type != DBUS_TYPE_ARRAY ||
1336 : 0 : entry.array_type != DBUS_TYPE_BYTE) {
1337 : 0 : reply = wpas_dbus_new_invalid_opts_error(
1338 : : message, "Byte array expected.");
1339 : 0 : break;
1340 : : }
1341 : :
1342 [ # # ][ # # ]: 0 : if ((entry.array_len <= 0) || (entry.array_len > 65536) ||
[ # # ]
1343 : 0 : !strlen(entry.key)) {
1344 : 0 : reply = wpas_dbus_new_invalid_opts_error(
1345 : : message, "Invalid array size.");
1346 : 0 : break;
1347 : : }
1348 : :
1349 : 0 : blob = os_zalloc(sizeof(*blob));
1350 [ # # ]: 0 : if (blob == NULL) {
1351 : 0 : reply = dbus_message_new_error(
1352 : : message, WPAS_ERROR_ADD_ERROR,
1353 : : "Not enough memory to add blob.");
1354 : 0 : break;
1355 : : }
1356 : 0 : blob->data = os_zalloc(entry.array_len);
1357 [ # # ]: 0 : if (blob->data == NULL) {
1358 : 0 : reply = dbus_message_new_error(
1359 : : message, WPAS_ERROR_ADD_ERROR,
1360 : : "Not enough memory to add blob data.");
1361 : 0 : os_free(blob);
1362 : 0 : break;
1363 : : }
1364 : :
1365 : 0 : blob->name = os_strdup(entry.key);
1366 : 0 : blob->len = entry.array_len;
1367 : 0 : os_memcpy(blob->data, (u8 *) entry.bytearray_value,
1368 : : entry.array_len);
1369 [ # # ][ # # ]: 0 : if (blob->name == NULL || blob->data == NULL) {
1370 : 0 : wpa_config_free_blob(blob);
1371 : 0 : reply = dbus_message_new_error(
1372 : : message, WPAS_ERROR_ADD_ERROR,
1373 : : "Error adding blob.");
1374 : 0 : break;
1375 : : }
1376 : :
1377 : : /* Success */
1378 [ # # ]: 0 : if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
1379 : 0 : wpas_notify_blob_removed(wpa_s, blob->name);
1380 : 0 : wpa_config_set_blob(wpa_s->conf, blob);
1381 : 0 : wpas_notify_blob_added(wpa_s, blob->name);
1382 : :
1383 : 0 : wpa_dbus_dict_entry_clear(&entry);
1384 : : }
1385 : 0 : wpa_dbus_dict_entry_clear(&entry);
1386 : :
1387 [ # # ]: 0 : return reply ? reply : wpas_dbus_new_success_reply(message);
1388 : : }
1389 : :
1390 : :
1391 : : /**
1392 : : * wpas_dbus_iface_remove_blob - Remove named binary blobs
1393 : : * @message: Pointer to incoming dbus message
1394 : : * @wpa_s: %wpa_supplicant data structure
1395 : : * Returns: A dbus message containing a UINT32 indicating success (1) or
1396 : : * failure (0)
1397 : : *
1398 : : * Asks wpa_supplicant to remove one or more previously stored binary blobs.
1399 : : */
1400 : 0 : DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
1401 : : struct wpa_supplicant *wpa_s)
1402 : : {
1403 : : DBusMessageIter iter, array;
1404 : 0 : char *err_msg = NULL;
1405 : :
1406 : 0 : dbus_message_iter_init(message, &iter);
1407 : :
1408 [ # # # # ]: 0 : if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
1409 : 0 : (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
1410 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
1411 : :
1412 : 0 : dbus_message_iter_recurse(&iter, &array);
1413 [ # # ]: 0 : while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
1414 : : const char *name;
1415 : :
1416 : 0 : dbus_message_iter_get_basic(&array, &name);
1417 [ # # ]: 0 : if (!os_strlen(name))
1418 : 0 : err_msg = "Invalid blob name.";
1419 : :
1420 [ # # ]: 0 : if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
1421 : 0 : err_msg = "Error removing blob.";
1422 : : else
1423 : 0 : wpas_notify_blob_removed(wpa_s, name);
1424 : 0 : dbus_message_iter_next(&array);
1425 : : }
1426 : :
1427 [ # # ]: 0 : if (err_msg)
1428 : 0 : return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR,
1429 : : err_msg);
1430 : :
1431 : 0 : return wpas_dbus_new_success_reply(message);
1432 : : }
1433 : :
1434 : : #endif /* CONFIG_NO_CONFIG_BLOBS */
1435 : :
1436 : :
1437 : : /**
1438 : : * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries
1439 : : * @message: Pointer to incoming dbus message
1440 : : * @wpa_s: %wpa_supplicant data structure
1441 : : * Returns: a dbus message containing a UINT32 indicating success (1) or
1442 : : * failure (0), or returns a dbus error message with more information
1443 : : *
1444 : : * Handler function for "flush" method call. Handles requests for an
1445 : : * interface with an optional "age" parameter that specifies the minimum
1446 : : * age of a BSS to be flushed.
1447 : : */
1448 : 0 : DBusMessage * wpas_dbus_iface_flush(DBusMessage *message,
1449 : : struct wpa_supplicant *wpa_s)
1450 : : {
1451 : 0 : int flush_age = 0;
1452 : :
1453 [ # # # # ]: 0 : if (os_strlen(dbus_message_get_signature(message)) != 0 &&
1454 : 0 : !dbus_message_get_args(message, NULL,
1455 : : DBUS_TYPE_INT32, &flush_age,
1456 : : DBUS_TYPE_INVALID)) {
1457 : 0 : return wpas_dbus_new_invalid_opts_error(message, NULL);
1458 : : }
1459 : :
1460 [ # # ]: 0 : if (flush_age == 0)
1461 : 0 : wpa_bss_flush(wpa_s);
1462 : : else
1463 : 0 : wpa_bss_flush_by_age(wpa_s, flush_age);
1464 : :
1465 : 0 : return wpas_dbus_new_success_reply(message);
1466 : : }
|