1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
22 #include "../bss.h"
23 #include "../scan.h"
24 #include "../autoscan.h"
25 #include "dbus_new_helpers.h"
26 #include "dbus_new.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_dict_helpers.h"
29 #include "dbus_common_i.h"
30
31 static const char *debug_strings[] = {
32 "excessive", "msgdump", "debug", "info", "warning", "error", NULL
33 };
34
35
36 /**
37 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
38 * @message: Pointer to incoming dbus message this error refers to
39 * @arg: Optional string appended to error message
40 * Returns: a dbus error message
41 *
42 * Convenience function to create and return an UnknownError
43 */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)44 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
45 const char *arg)
46 {
47 /*
48 * This function can be called as a result of a failure
49 * within internal getter calls, which will call this function
50 * with a NULL message parameter. However, dbus_message_new_error
51 * looks very unkindly (i.e, abort()) on a NULL message, so
52 * in this case, we should not call it.
53 */
54 if (message == NULL) {
55 wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
56 "called with NULL message (arg=%s)",
57 arg ? arg : "N/A");
58 return NULL;
59 }
60
61 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
62 arg);
63 }
64
65
66 /**
67 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
68 * @message: Pointer to incoming dbus message this error refers to
69 * Returns: A dbus error message
70 *
71 * Convenience function to create and return an invalid interface error
72 */
wpas_dbus_error_iface_unknown(DBusMessage * message)73 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
74 {
75 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
76 "wpa_supplicant knows nothing about "
77 "this interface.");
78 }
79
80
81 /**
82 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
83 * @message: Pointer to incoming dbus message this error refers to
84 * Returns: a dbus error message
85 *
86 * Convenience function to create and return an invalid network error
87 */
wpas_dbus_error_network_unknown(DBusMessage * message)88 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
89 {
90 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
91 "There is no such a network in this "
92 "interface.");
93 }
94
95
96 /**
97 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
98 * @message: Pointer to incoming dbus message this error refers to
99 * Returns: a dbus error message
100 *
101 * Convenience function to create and return an invalid options error
102 */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)103 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
104 const char *arg)
105 {
106 DBusMessage *reply;
107
108 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
109 "Did not receive correct message "
110 "arguments.");
111 if (arg != NULL)
112 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
113 DBUS_TYPE_INVALID);
114
115 return reply;
116 }
117
118
119 /**
120 * wpas_dbus_error_scan_error - Return a new ScanError error message
121 * @message: Pointer to incoming dbus message this error refers to
122 * @error: Optional string to be used as the error message
123 * Returns: a dbus error message
124 *
125 * Convenience function to create and return a scan error
126 */
wpas_dbus_error_scan_error(DBusMessage * message,const char * error)127 DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
128 const char *error)
129 {
130 DBusMessage *reply;
131
132 reply = dbus_message_new_error(message,
133 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
134 error);
135
136 return reply;
137 }
138
139
140 static const char *dont_quote[] = {
141 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
142 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
143 "bssid", "scan_freq", "freq_list", NULL
144 };
145
should_quote_opt(const char * key)146 static dbus_bool_t should_quote_opt(const char *key)
147 {
148 int i = 0;
149 while (dont_quote[i] != NULL) {
150 if (os_strcmp(key, dont_quote[i]) == 0)
151 return FALSE;
152 i++;
153 }
154 return TRUE;
155 }
156
157 /**
158 * get_iface_by_dbus_path - Get a new network interface
159 * @global: Pointer to global data from wpa_supplicant_init()
160 * @path: Pointer to a dbus object path representing an interface
161 * Returns: Pointer to the interface or %NULL if not found
162 */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)163 static struct wpa_supplicant * get_iface_by_dbus_path(
164 struct wpa_global *global, const char *path)
165 {
166 struct wpa_supplicant *wpa_s;
167
168 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
169 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
170 return wpa_s;
171 }
172 return NULL;
173 }
174
175
176 /**
177 * set_network_properties - Set properties of a configured network
178 * @wpa_s: wpa_supplicant structure for a network interface
179 * @ssid: wpa_ssid structure for a configured network
180 * @iter: DBus message iterator containing dictionary of network
181 * properties to set.
182 * @error: On failure, an error describing the failure
183 * Returns: TRUE if the request succeeds, FALSE if it failed
184 *
185 * Sets network configuration with parameters given id DBus dictionary
186 */
set_network_properties(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter,DBusError * error)187 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
188 struct wpa_ssid *ssid,
189 DBusMessageIter *iter,
190 DBusError *error)
191 {
192 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
193 DBusMessageIter iter_dict;
194 char *value = NULL;
195
196 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
197 return FALSE;
198
199 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
200 size_t size = 50;
201 int ret;
202
203 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
204 goto error;
205
206 value = NULL;
207 if (entry.type == DBUS_TYPE_ARRAY &&
208 entry.array_type == DBUS_TYPE_BYTE) {
209 if (entry.array_len <= 0)
210 goto error;
211
212 size = entry.array_len * 2 + 1;
213 value = os_zalloc(size);
214 if (value == NULL)
215 goto error;
216
217 ret = wpa_snprintf_hex(value, size,
218 (u8 *) entry.bytearray_value,
219 entry.array_len);
220 if (ret <= 0)
221 goto error;
222 } else if (entry.type == DBUS_TYPE_STRING) {
223 if (should_quote_opt(entry.key)) {
224 size = os_strlen(entry.str_value);
225 if (size <= 0)
226 goto error;
227
228 size += 3;
229 value = os_zalloc(size);
230 if (value == NULL)
231 goto error;
232
233 ret = os_snprintf(value, size, "\"%s\"",
234 entry.str_value);
235 if (ret < 0 || (size_t) ret != (size - 1))
236 goto error;
237 } else {
238 value = os_strdup(entry.str_value);
239 if (value == NULL)
240 goto error;
241 }
242 } else if (entry.type == DBUS_TYPE_UINT32) {
243 value = os_zalloc(size);
244 if (value == NULL)
245 goto error;
246
247 ret = os_snprintf(value, size, "%u",
248 entry.uint32_value);
249 if (ret <= 0)
250 goto error;
251 } else if (entry.type == DBUS_TYPE_INT32) {
252 value = os_zalloc(size);
253 if (value == NULL)
254 goto error;
255
256 ret = os_snprintf(value, size, "%d",
257 entry.int32_value);
258 if (ret <= 0)
259 goto error;
260 } else
261 goto error;
262
263 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
264 goto error;
265
266 if ((os_strcmp(entry.key, "psk") == 0 &&
267 value[0] == '"' && ssid->ssid_len) ||
268 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
269 wpa_config_update_psk(ssid);
270 else if (os_strcmp(entry.key, "priority") == 0)
271 wpa_config_update_prio_list(wpa_s->conf);
272
273 os_free(value);
274 value = NULL;
275 wpa_dbus_dict_entry_clear(&entry);
276 }
277
278 return TRUE;
279
280 error:
281 os_free(value);
282 wpa_dbus_dict_entry_clear(&entry);
283 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
284 "invalid message format");
285 return FALSE;
286 }
287
288
289 /**
290 * wpas_dbus_simple_property_getter - Get basic type property
291 * @iter: Message iter to use when appending arguments
292 * @type: DBus type of property (must be basic type)
293 * @val: pointer to place holding property value
294 * @error: On failure an error describing the failure
295 * Returns: TRUE if the request was successful, FALSE if it failed
296 *
297 * Generic getter for basic type properties. Type is required to be basic.
298 */
wpas_dbus_simple_property_getter(DBusMessageIter * iter,const int type,const void * val,DBusError * error)299 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
300 const int type,
301 const void *val,
302 DBusError *error)
303 {
304 DBusMessageIter variant_iter;
305
306 if (!dbus_type_is_basic(type)) {
307 dbus_set_error(error, DBUS_ERROR_FAILED,
308 "%s: given type is not basic", __func__);
309 return FALSE;
310 }
311
312 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
313 wpa_dbus_type_as_string(type),
314 &variant_iter))
315 goto error;
316
317 if (!dbus_message_iter_append_basic(&variant_iter, type, val))
318 goto error;
319
320 if (!dbus_message_iter_close_container(iter, &variant_iter))
321 goto error;
322
323 return TRUE;
324
325 error:
326 dbus_set_error(error, DBUS_ERROR_FAILED,
327 "%s: error constructing reply", __func__);
328 return FALSE;
329 }
330
331
332 /**
333 * wpas_dbus_simple_property_setter - Set basic type property
334 * @message: Pointer to incoming dbus message
335 * @type: DBus type of property (must be basic type)
336 * @val: pointer to place where value being set will be stored
337 * Returns: TRUE if the request was successful, FALSE if it failed
338 *
339 * Generic setter for basic type properties. Type is required to be basic.
340 */
wpas_dbus_simple_property_setter(DBusMessageIter * iter,DBusError * error,const int type,void * val)341 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
342 DBusError *error,
343 const int type, void *val)
344 {
345 DBusMessageIter variant_iter;
346
347 if (!dbus_type_is_basic(type)) {
348 dbus_set_error(error, DBUS_ERROR_FAILED,
349 "%s: given type is not basic", __func__);
350 return FALSE;
351 }
352
353 /* Look at the new value */
354 dbus_message_iter_recurse(iter, &variant_iter);
355 if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
356 dbus_set_error_const(error, DBUS_ERROR_FAILED,
357 "wrong property type");
358 return FALSE;
359 }
360 dbus_message_iter_get_basic(&variant_iter, val);
361
362 return TRUE;
363 }
364
365
366 /**
367 * wpas_dbus_simple_array_property_getter - Get array type property
368 * @iter: Pointer to incoming dbus message iterator
369 * @type: DBus type of property array elements (must be basic type)
370 * @array: pointer to array of elements to put into response message
371 * @array_len: length of above array
372 * @error: a pointer to an error to fill on failure
373 * Returns: TRUE if the request succeeded, FALSE if it failed
374 *
375 * Generic getter for array type properties. Array elements type is
376 * required to be basic.
377 */
wpas_dbus_simple_array_property_getter(DBusMessageIter * iter,const int type,const void * array,size_t array_len,DBusError * error)378 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
379 const int type,
380 const void *array,
381 size_t array_len,
382 DBusError *error)
383 {
384 DBusMessageIter variant_iter, array_iter;
385 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
386 const char *sub_type_str;
387 size_t element_size, i;
388
389 if (!dbus_type_is_basic(type)) {
390 dbus_set_error(error, DBUS_ERROR_FAILED,
391 "%s: given type is not basic", __func__);
392 return FALSE;
393 }
394
395 sub_type_str = wpa_dbus_type_as_string(type);
396 type_str[1] = sub_type_str[0];
397
398 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
399 type_str, &variant_iter)) {
400 dbus_set_error(error, DBUS_ERROR_FAILED,
401 "%s: failed to construct message 1", __func__);
402 return FALSE;
403 }
404
405 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
406 sub_type_str, &array_iter)) {
407 dbus_set_error(error, DBUS_ERROR_FAILED,
408 "%s: failed to construct message 2", __func__);
409 return FALSE;
410 }
411
412 switch(type) {
413 case DBUS_TYPE_BYTE:
414 case DBUS_TYPE_BOOLEAN:
415 element_size = 1;
416 break;
417 case DBUS_TYPE_INT16:
418 case DBUS_TYPE_UINT16:
419 element_size = sizeof(uint16_t);
420 break;
421 case DBUS_TYPE_INT32:
422 case DBUS_TYPE_UINT32:
423 element_size = sizeof(uint32_t);
424 break;
425 case DBUS_TYPE_INT64:
426 case DBUS_TYPE_UINT64:
427 element_size = sizeof(uint64_t);
428 break;
429 case DBUS_TYPE_DOUBLE:
430 element_size = sizeof(double);
431 break;
432 case DBUS_TYPE_STRING:
433 case DBUS_TYPE_OBJECT_PATH:
434 element_size = sizeof(char *);
435 break;
436 default:
437 dbus_set_error(error, DBUS_ERROR_FAILED,
438 "%s: unknown element type %d", __func__, type);
439 return FALSE;
440 }
441
442 for (i = 0; i < array_len; i++) {
443 if (!dbus_message_iter_append_basic(&array_iter, type,
444 array + i * element_size)) {
445 dbus_set_error(error, DBUS_ERROR_FAILED,
446 "%s: failed to construct message 2.5",
447 __func__);
448 return FALSE;
449 }
450 }
451
452 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
453 dbus_set_error(error, DBUS_ERROR_FAILED,
454 "%s: failed to construct message 3", __func__);
455 return FALSE;
456 }
457
458 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
459 dbus_set_error(error, DBUS_ERROR_FAILED,
460 "%s: failed to construct message 4", __func__);
461 return FALSE;
462 }
463
464 return TRUE;
465 }
466
467
468 /**
469 * wpas_dbus_simple_array_array_property_getter - Get array array type property
470 * @iter: Pointer to incoming dbus message iterator
471 * @type: DBus type of property array elements (must be basic type)
472 * @array: pointer to array of elements to put into response message
473 * @array_len: length of above array
474 * @error: a pointer to an error to fill on failure
475 * Returns: TRUE if the request succeeded, FALSE if it failed
476 *
477 * Generic getter for array type properties. Array elements type is
478 * required to be basic.
479 */
wpas_dbus_simple_array_array_property_getter(DBusMessageIter * iter,const int type,struct wpabuf ** array,size_t array_len,DBusError * error)480 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
481 const int type,
482 struct wpabuf **array,
483 size_t array_len,
484 DBusError *error)
485 {
486 DBusMessageIter variant_iter, array_iter;
487 char type_str[] = "aa?";
488 char inner_type_str[] = "a?";
489 const char *sub_type_str;
490 size_t i;
491
492 if (!dbus_type_is_basic(type)) {
493 dbus_set_error(error, DBUS_ERROR_FAILED,
494 "%s: given type is not basic", __func__);
495 return FALSE;
496 }
497
498 sub_type_str = wpa_dbus_type_as_string(type);
499 type_str[2] = sub_type_str[0];
500 inner_type_str[1] = sub_type_str[0];
501
502 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
503 type_str, &variant_iter)) {
504 dbus_set_error(error, DBUS_ERROR_FAILED,
505 "%s: failed to construct message 1", __func__);
506 return FALSE;
507 }
508 if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
509 inner_type_str, &array_iter)) {
510 dbus_set_error(error, DBUS_ERROR_FAILED,
511 "%s: failed to construct message 2", __func__);
512 return FALSE;
513 }
514
515 for (i = 0; i < array_len && array[i]; i++) {
516 wpa_dbus_dict_bin_array_add_element(&array_iter,
517 wpabuf_head(array[i]),
518 wpabuf_len(array[i]));
519
520 }
521
522 if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
523 dbus_set_error(error, DBUS_ERROR_FAILED,
524 "%s: failed to close message 2", __func__);
525 return FALSE;
526 }
527
528 if (!dbus_message_iter_close_container(iter, &variant_iter)) {
529 dbus_set_error(error, DBUS_ERROR_FAILED,
530 "%s: failed to close message 1", __func__);
531 return FALSE;
532 }
533
534 return TRUE;
535 }
536
537
538 /**
539 * wpas_dbus_handler_create_interface - Request registration of a network iface
540 * @message: Pointer to incoming dbus message
541 * @global: %wpa_supplicant global data structure
542 * Returns: The object path of the new interface object,
543 * or a dbus error message with more information
544 *
545 * Handler function for "CreateInterface" method call. Handles requests
546 * by dbus clients to register a network interface that wpa_supplicant
547 * will manage.
548 */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)549 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
550 struct wpa_global *global)
551 {
552 DBusMessageIter iter_dict;
553 DBusMessage *reply = NULL;
554 DBusMessageIter iter;
555 struct wpa_dbus_dict_entry entry;
556 char *driver = NULL;
557 char *ifname = NULL;
558 char *confname = NULL;
559 char *bridge_ifname = NULL;
560
561 dbus_message_iter_init(message, &iter);
562
563 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
564 goto error;
565 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
566 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
567 goto error;
568 if (!os_strcmp(entry.key, "Driver") &&
569 (entry.type == DBUS_TYPE_STRING)) {
570 os_free(driver);
571 driver = os_strdup(entry.str_value);
572 wpa_dbus_dict_entry_clear(&entry);
573 if (driver == NULL)
574 goto error;
575 } else if (!os_strcmp(entry.key, "Ifname") &&
576 (entry.type == DBUS_TYPE_STRING)) {
577 os_free(ifname);
578 ifname = os_strdup(entry.str_value);
579 wpa_dbus_dict_entry_clear(&entry);
580 if (ifname == NULL)
581 goto error;
582 } else if (!os_strcmp(entry.key, "ConfigFile") &&
583 (entry.type == DBUS_TYPE_STRING)) {
584 os_free(confname);
585 confname = os_strdup(entry.str_value);
586 wpa_dbus_dict_entry_clear(&entry);
587 if (confname == NULL)
588 goto error;
589 } else if (!os_strcmp(entry.key, "BridgeIfname") &&
590 (entry.type == DBUS_TYPE_STRING)) {
591 os_free(bridge_ifname);
592 bridge_ifname = os_strdup(entry.str_value);
593 wpa_dbus_dict_entry_clear(&entry);
594 if (bridge_ifname == NULL)
595 goto error;
596 } else {
597 wpa_dbus_dict_entry_clear(&entry);
598 goto error;
599 }
600 }
601
602 if (ifname == NULL)
603 goto error; /* Required Ifname argument missing */
604
605 /*
606 * Try to get the wpa_supplicant record for this iface, return
607 * an error if we already control it.
608 */
609 if (wpa_supplicant_get_iface(global, ifname) != NULL) {
610 reply = dbus_message_new_error(message,
611 WPAS_DBUS_ERROR_IFACE_EXISTS,
612 "wpa_supplicant already "
613 "controls this interface.");
614 } else {
615 struct wpa_supplicant *wpa_s;
616 struct wpa_interface iface;
617 os_memset(&iface, 0, sizeof(iface));
618 iface.driver = driver;
619 iface.ifname = ifname;
620 iface.confname = confname;
621 iface.bridge_ifname = bridge_ifname;
622 /* Otherwise, have wpa_supplicant attach to it. */
623 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
624 const char *path = wpa_s->dbus_new_path;
625 reply = dbus_message_new_method_return(message);
626 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
627 &path, DBUS_TYPE_INVALID);
628 } else {
629 reply = wpas_dbus_error_unknown_error(
630 message, "wpa_supplicant couldn't grab this "
631 "interface.");
632 }
633 }
634
635 out:
636 os_free(driver);
637 os_free(ifname);
638 os_free(confname);
639 os_free(bridge_ifname);
640 return reply;
641
642 error:
643 reply = wpas_dbus_error_invalid_args(message, NULL);
644 goto out;
645 }
646
647
648 /**
649 * wpas_dbus_handler_remove_interface - Request deregistration of an interface
650 * @message: Pointer to incoming dbus message
651 * @global: wpa_supplicant global data structure
652 * Returns: a dbus message containing a UINT32 indicating success (1) or
653 * failure (0), or returns a dbus error message with more information
654 *
655 * Handler function for "removeInterface" method call. Handles requests
656 * by dbus clients to deregister a network interface that wpa_supplicant
657 * currently manages.
658 */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)659 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
660 struct wpa_global *global)
661 {
662 struct wpa_supplicant *wpa_s;
663 char *path;
664 DBusMessage *reply = NULL;
665
666 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
667 DBUS_TYPE_INVALID);
668
669 wpa_s = get_iface_by_dbus_path(global, path);
670 if (wpa_s == NULL)
671 reply = wpas_dbus_error_iface_unknown(message);
672 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
673 reply = wpas_dbus_error_unknown_error(
674 message, "wpa_supplicant couldn't remove this "
675 "interface.");
676 }
677
678 return reply;
679 }
680
681
682 /**
683 * wpas_dbus_handler_get_interface - Get the object path for an interface name
684 * @message: Pointer to incoming dbus message
685 * @global: %wpa_supplicant global data structure
686 * Returns: The object path of the interface object,
687 * or a dbus error message with more information
688 *
689 * Handler function for "getInterface" method call.
690 */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)691 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
692 struct wpa_global *global)
693 {
694 DBusMessage *reply = NULL;
695 const char *ifname;
696 const char *path;
697 struct wpa_supplicant *wpa_s;
698
699 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
700 DBUS_TYPE_INVALID);
701
702 wpa_s = wpa_supplicant_get_iface(global, ifname);
703 if (wpa_s == NULL)
704 return wpas_dbus_error_iface_unknown(message);
705
706 path = wpa_s->dbus_new_path;
707 reply = dbus_message_new_method_return(message);
708 if (reply == NULL)
709 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
710 NULL);
711 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
712 DBUS_TYPE_INVALID)) {
713 dbus_message_unref(reply);
714 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
715 NULL);
716 }
717
718 return reply;
719 }
720
721
722 /**
723 * wpas_dbus_getter_debug_level - Get debug level
724 * @iter: Pointer to incoming dbus message iter
725 * @error: Location to store error on failure
726 * @user_data: Function specific data
727 * Returns: TRUE on success, FALSE on failure
728 *
729 * Getter for "DebugLevel" property.
730 */
wpas_dbus_getter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)731 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
732 DBusError *error,
733 void *user_data)
734 {
735 const char *str;
736 int idx = wpa_debug_level;
737
738 if (idx < 0)
739 idx = 0;
740 if (idx > 5)
741 idx = 5;
742 str = debug_strings[idx];
743 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
744 &str, error);
745 }
746
747
748 /**
749 * wpas_dbus_getter_debug_timestamp - Get debug timestamp
750 * @iter: Pointer to incoming dbus message iter
751 * @error: Location to store error on failure
752 * @user_data: Function specific data
753 * Returns: TRUE on success, FALSE on failure
754 *
755 * Getter for "DebugTimestamp" property.
756 */
wpas_dbus_getter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)757 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
758 DBusError *error,
759 void *user_data)
760 {
761 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
762 &wpa_debug_timestamp, error);
763
764 }
765
766
767 /**
768 * wpas_dbus_getter_debug_show_keys - Get debug show keys
769 * @iter: Pointer to incoming dbus message iter
770 * @error: Location to store error on failure
771 * @user_data: Function specific data
772 * Returns: TRUE on success, FALSE on failure
773 *
774 * Getter for "DebugShowKeys" property.
775 */
wpas_dbus_getter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)776 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
777 DBusError *error,
778 void *user_data)
779 {
780 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
781 &wpa_debug_show_keys, error);
782
783 }
784
785 /**
786 * wpas_dbus_setter_debug_level - Set debug level
787 * @iter: Pointer to incoming dbus message iter
788 * @error: Location to store error on failure
789 * @user_data: Function specific data
790 * Returns: TRUE on success, FALSE on failure
791 *
792 * Setter for "DebugLevel" property.
793 */
wpas_dbus_setter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)794 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
795 DBusError *error, void *user_data)
796 {
797 struct wpa_global *global = user_data;
798 const char *str = NULL;
799 int i, val = -1;
800
801 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
802 &str))
803 return FALSE;
804
805 for (i = 0; debug_strings[i]; i++)
806 if (os_strcmp(debug_strings[i], str) == 0) {
807 val = i;
808 break;
809 }
810
811 if (val < 0 ||
812 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
813 wpa_debug_show_keys)) {
814 dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug "
815 "level value");
816 return FALSE;
817 }
818
819 return TRUE;
820 }
821
822
823 /**
824 * wpas_dbus_setter_debug_timestamp - Set debug timestamp
825 * @iter: Pointer to incoming dbus message iter
826 * @error: Location to store error on failure
827 * @user_data: Function specific data
828 * Returns: TRUE on success, FALSE on failure
829 *
830 * Setter for "DebugTimestamp" property.
831 */
wpas_dbus_setter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)832 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
833 DBusError *error,
834 void *user_data)
835 {
836 struct wpa_global *global = user_data;
837 dbus_bool_t val;
838
839 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
840 &val))
841 return FALSE;
842
843 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
844 wpa_debug_show_keys);
845 return TRUE;
846 }
847
848
849 /**
850 * wpas_dbus_setter_debug_show_keys - Set debug show keys
851 * @iter: Pointer to incoming dbus message iter
852 * @error: Location to store error on failure
853 * @user_data: Function specific data
854 * Returns: TRUE on success, FALSE on failure
855 *
856 * Setter for "DebugShowKeys" property.
857 */
wpas_dbus_setter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)858 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
859 DBusError *error,
860 void *user_data)
861 {
862 struct wpa_global *global = user_data;
863 dbus_bool_t val;
864
865 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
866 &val))
867 return FALSE;
868
869 wpa_supplicant_set_debug_params(global, wpa_debug_level,
870 wpa_debug_timestamp,
871 val ? 1 : 0);
872 return TRUE;
873 }
874
875
876 /**
877 * wpas_dbus_getter_interfaces - Request registered interfaces list
878 * @iter: Pointer to incoming dbus message iter
879 * @error: Location to store error on failure
880 * @user_data: Function specific data
881 * Returns: TRUE on success, FALSE on failure
882 *
883 * Getter for "Interfaces" property. Handles requests
884 * by dbus clients to return list of registered interfaces objects
885 * paths
886 */
wpas_dbus_getter_interfaces(DBusMessageIter * iter,DBusError * error,void * user_data)887 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
888 DBusError *error,
889 void *user_data)
890 {
891 struct wpa_global *global = user_data;
892 struct wpa_supplicant *wpa_s;
893 const char **paths;
894 unsigned int i = 0, num = 0;
895 dbus_bool_t success;
896
897 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
898 num++;
899
900 paths = os_calloc(num, sizeof(char *));
901 if (!paths) {
902 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
903 return FALSE;
904 }
905
906 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
907 paths[i++] = wpa_s->dbus_new_path;
908
909 success = wpas_dbus_simple_array_property_getter(iter,
910 DBUS_TYPE_OBJECT_PATH,
911 paths, num, error);
912
913 os_free(paths);
914 return success;
915 }
916
917
918 /**
919 * wpas_dbus_getter_eap_methods - Request supported EAP methods list
920 * @iter: Pointer to incoming dbus message iter
921 * @error: Location to store error on failure
922 * @user_data: Function specific data
923 * Returns: TRUE on success, FALSE on failure
924 *
925 * Getter for "EapMethods" property. Handles requests
926 * by dbus clients to return list of strings with supported EAP methods
927 */
wpas_dbus_getter_eap_methods(DBusMessageIter * iter,DBusError * error,void * user_data)928 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
929 DBusError *error, void *user_data)
930 {
931 char **eap_methods;
932 size_t num_items = 0;
933 dbus_bool_t success;
934
935 eap_methods = eap_get_names_as_string_array(&num_items);
936 if (!eap_methods) {
937 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
938 return FALSE;
939 }
940
941 success = wpas_dbus_simple_array_property_getter(iter,
942 DBUS_TYPE_STRING,
943 eap_methods,
944 num_items, error);
945
946 while (num_items)
947 os_free(eap_methods[--num_items]);
948 os_free(eap_methods);
949 return success;
950 }
951
952
953 /**
954 * wpas_dbus_getter_global_capabilities - Request supported global capabilities
955 * @iter: Pointer to incoming dbus message iter
956 * @error: Location to store error on failure
957 * @user_data: Function specific data
958 * Returns: TRUE on success, FALSE on failure
959 *
960 * Getter for "Capabilities" property. Handles requests by dbus clients to
961 * return a list of strings with supported capabilities like AP, RSN IBSS,
962 * and P2P that are determined at compile time.
963 */
wpas_dbus_getter_global_capabilities(DBusMessageIter * iter,DBusError * error,void * user_data)964 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
965 DBusError *error,
966 void *user_data)
967 {
968 const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
969 size_t num_items = 0;
970
971 #ifdef CONFIG_AP
972 capabilities[num_items++] = "ap";
973 #endif /* CONFIG_AP */
974 #ifdef CONFIG_IBSS_RSN
975 capabilities[num_items++] = "ibss-rsn";
976 #endif /* CONFIG_IBSS_RSN */
977 #ifdef CONFIG_P2P
978 capabilities[num_items++] = "p2p";
979 #endif /* CONFIG_P2P */
980 #ifdef CONFIG_INTERWORKING
981 capabilities[num_items++] = "interworking";
982 #endif /* CONFIG_INTERWORKING */
983
984 return wpas_dbus_simple_array_property_getter(iter,
985 DBUS_TYPE_STRING,
986 capabilities,
987 num_items, error);
988 }
989
990
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)991 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
992 char **type, DBusMessage **reply)
993 {
994 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
995 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
996 "Type must be a string");
997 *reply = wpas_dbus_error_invalid_args(
998 message, "Wrong Type value type. String required");
999 return -1;
1000 }
1001 dbus_message_iter_get_basic(var, type);
1002 return 0;
1003 }
1004
1005
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1006 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
1007 struct wpa_driver_scan_params *params,
1008 DBusMessage **reply)
1009 {
1010 struct wpa_driver_scan_ssid *ssids = params->ssids;
1011 size_t ssids_num = 0;
1012 u8 *ssid;
1013 DBusMessageIter array_iter, sub_array_iter;
1014 char *val;
1015 int len;
1016
1017 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1018 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
1019 "must be an array of arrays of bytes");
1020 *reply = wpas_dbus_error_invalid_args(
1021 message, "Wrong SSIDs value type. Array of arrays of "
1022 "bytes required");
1023 return -1;
1024 }
1025
1026 dbus_message_iter_recurse(var, &array_iter);
1027
1028 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1029 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1030 {
1031 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
1032 "must be an array of arrays of bytes");
1033 *reply = wpas_dbus_error_invalid_args(
1034 message, "Wrong SSIDs value type. Array of arrays of "
1035 "bytes required");
1036 return -1;
1037 }
1038
1039 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1040 {
1041 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1042 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1043 "Too many ssids specified on scan dbus "
1044 "call");
1045 *reply = wpas_dbus_error_invalid_args(
1046 message, "Too many ssids specified. Specify "
1047 "at most four");
1048 return -1;
1049 }
1050
1051 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1052
1053 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1054
1055 if (len > MAX_SSID_LEN) {
1056 wpa_printf(MSG_DEBUG,
1057 "wpas_dbus_handler_scan[dbus]: "
1058 "SSID too long (len=%d max_len=%d)",
1059 len, MAX_SSID_LEN);
1060 *reply = wpas_dbus_error_invalid_args(
1061 message, "Invalid SSID: too long");
1062 return -1;
1063 }
1064
1065 if (len != 0) {
1066 ssid = os_malloc(len);
1067 if (ssid == NULL) {
1068 wpa_printf(MSG_DEBUG,
1069 "wpas_dbus_handler_scan[dbus]: "
1070 "out of memory. Cannot allocate "
1071 "memory for SSID");
1072 *reply = dbus_message_new_error(
1073 message, DBUS_ERROR_NO_MEMORY, NULL);
1074 return -1;
1075 }
1076 os_memcpy(ssid, val, len);
1077 } else {
1078 /* Allow zero-length SSIDs */
1079 ssid = NULL;
1080 }
1081
1082 ssids[ssids_num].ssid = ssid;
1083 ssids[ssids_num].ssid_len = len;
1084
1085 dbus_message_iter_next(&array_iter);
1086 ssids_num++;
1087 }
1088
1089 params->num_ssids = ssids_num;
1090 return 0;
1091 }
1092
1093
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1094 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1095 struct wpa_driver_scan_params *params,
1096 DBusMessage **reply)
1097 {
1098 u8 *ies = NULL, *nies;
1099 int ies_len = 0;
1100 DBusMessageIter array_iter, sub_array_iter;
1101 char *val;
1102 int len;
1103
1104 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1105 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1106 "be an array of arrays of bytes");
1107 *reply = wpas_dbus_error_invalid_args(
1108 message, "Wrong IEs value type. Array of arrays of "
1109 "bytes required");
1110 return -1;
1111 }
1112
1113 dbus_message_iter_recurse(var, &array_iter);
1114
1115 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1116 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1117 {
1118 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1119 "be an array of arrays of bytes");
1120 *reply = wpas_dbus_error_invalid_args(
1121 message, "Wrong IEs value type. Array required");
1122 return -1;
1123 }
1124
1125 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1126 {
1127 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1128
1129 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1130 if (len == 0) {
1131 dbus_message_iter_next(&array_iter);
1132 continue;
1133 }
1134
1135 nies = os_realloc(ies, ies_len + len);
1136 if (nies == NULL) {
1137 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1138 "out of memory. Cannot allocate memory for "
1139 "IE");
1140 os_free(ies);
1141 *reply = dbus_message_new_error(
1142 message, DBUS_ERROR_NO_MEMORY, NULL);
1143 return -1;
1144 }
1145 ies = nies;
1146 os_memcpy(ies + ies_len, val, len);
1147 ies_len += len;
1148
1149 dbus_message_iter_next(&array_iter);
1150 }
1151
1152 params->extra_ies = ies;
1153 params->extra_ies_len = ies_len;
1154 return 0;
1155 }
1156
1157
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1158 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1159 DBusMessageIter *var,
1160 struct wpa_driver_scan_params *params,
1161 DBusMessage **reply)
1162 {
1163 DBusMessageIter array_iter, sub_array_iter;
1164 int *freqs = NULL, *nfreqs;
1165 int freqs_num = 0;
1166
1167 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1168 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1169 "Channels must be an array of structs");
1170 *reply = wpas_dbus_error_invalid_args(
1171 message, "Wrong Channels value type. Array of structs "
1172 "required");
1173 return -1;
1174 }
1175
1176 dbus_message_iter_recurse(var, &array_iter);
1177
1178 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1179 wpa_printf(MSG_DEBUG,
1180 "wpas_dbus_handler_scan[dbus]: Channels must be an "
1181 "array of structs");
1182 *reply = wpas_dbus_error_invalid_args(
1183 message, "Wrong Channels value type. Array of structs "
1184 "required");
1185 return -1;
1186 }
1187
1188 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1189 {
1190 int freq, width;
1191
1192 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1193
1194 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1195 DBUS_TYPE_UINT32) {
1196 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1197 "Channel must by specified by struct of "
1198 "two UINT32s %c",
1199 dbus_message_iter_get_arg_type(
1200 &sub_array_iter));
1201 *reply = wpas_dbus_error_invalid_args(
1202 message, "Wrong Channel struct. Two UINT32s "
1203 "required");
1204 os_free(freqs);
1205 return -1;
1206 }
1207 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1208
1209 if (!dbus_message_iter_next(&sub_array_iter) ||
1210 dbus_message_iter_get_arg_type(&sub_array_iter) !=
1211 DBUS_TYPE_UINT32) {
1212 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1213 "Channel must by specified by struct of "
1214 "two UINT32s");
1215 *reply = wpas_dbus_error_invalid_args(
1216 message,
1217 "Wrong Channel struct. Two UINT32s required");
1218 os_free(freqs);
1219 return -1;
1220 }
1221
1222 dbus_message_iter_get_basic(&sub_array_iter, &width);
1223
1224 #define FREQS_ALLOC_CHUNK 32
1225 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1226 nfreqs = os_realloc_array(
1227 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1228 sizeof(int));
1229 if (nfreqs == NULL)
1230 os_free(freqs);
1231 freqs = nfreqs;
1232 }
1233 if (freqs == NULL) {
1234 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1235 "out of memory. can't allocate memory for "
1236 "freqs");
1237 *reply = dbus_message_new_error(
1238 message, DBUS_ERROR_NO_MEMORY, NULL);
1239 return -1;
1240 }
1241
1242 freqs[freqs_num] = freq;
1243
1244 freqs_num++;
1245 dbus_message_iter_next(&array_iter);
1246 }
1247
1248 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1249 if (nfreqs == NULL)
1250 os_free(freqs);
1251 freqs = nfreqs;
1252 if (freqs == NULL) {
1253 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1254 "out of memory. Can't allocate memory for freqs");
1255 *reply = dbus_message_new_error(
1256 message, DBUS_ERROR_NO_MEMORY, NULL);
1257 return -1;
1258 }
1259 freqs[freqs_num] = 0;
1260
1261 params->freqs = freqs;
1262 return 0;
1263 }
1264
1265
wpas_dbus_get_scan_allow_roam(DBusMessage * message,DBusMessageIter * var,dbus_bool_t * allow,DBusMessage ** reply)1266 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1267 DBusMessageIter *var,
1268 dbus_bool_t *allow,
1269 DBusMessage **reply)
1270 {
1271 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1272 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1273 "Type must be a boolean");
1274 *reply = wpas_dbus_error_invalid_args(
1275 message, "Wrong Type value type. Boolean required");
1276 return -1;
1277 }
1278 dbus_message_iter_get_basic(var, allow);
1279 return 0;
1280 }
1281
1282
1283 /**
1284 * wpas_dbus_handler_scan - Request a wireless scan on an interface
1285 * @message: Pointer to incoming dbus message
1286 * @wpa_s: wpa_supplicant structure for a network interface
1287 * Returns: NULL indicating success or DBus error message on failure
1288 *
1289 * Handler function for "Scan" method call of a network device. Requests
1290 * that wpa_supplicant perform a wireless scan as soon as possible
1291 * on a particular wireless interface.
1292 */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1293 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1294 struct wpa_supplicant *wpa_s)
1295 {
1296 DBusMessage *reply = NULL;
1297 DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1298 char *key = NULL, *type = NULL;
1299 struct wpa_driver_scan_params params;
1300 size_t i;
1301 dbus_bool_t allow_roam = 1;
1302
1303 os_memset(¶ms, 0, sizeof(params));
1304
1305 dbus_message_iter_init(message, &iter);
1306
1307 dbus_message_iter_recurse(&iter, &dict_iter);
1308
1309 while (dbus_message_iter_get_arg_type(&dict_iter) ==
1310 DBUS_TYPE_DICT_ENTRY) {
1311 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1312 dbus_message_iter_get_basic(&entry_iter, &key);
1313 dbus_message_iter_next(&entry_iter);
1314 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1315
1316 if (os_strcmp(key, "Type") == 0) {
1317 if (wpas_dbus_get_scan_type(message, &variant_iter,
1318 &type, &reply) < 0)
1319 goto out;
1320 } else if (os_strcmp(key, "SSIDs") == 0) {
1321 if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1322 ¶ms, &reply) < 0)
1323 goto out;
1324 } else if (os_strcmp(key, "IEs") == 0) {
1325 if (wpas_dbus_get_scan_ies(message, &variant_iter,
1326 ¶ms, &reply) < 0)
1327 goto out;
1328 } else if (os_strcmp(key, "Channels") == 0) {
1329 if (wpas_dbus_get_scan_channels(message, &variant_iter,
1330 ¶ms, &reply) < 0)
1331 goto out;
1332 } else if (os_strcmp(key, "AllowRoam") == 0) {
1333 if (wpas_dbus_get_scan_allow_roam(message,
1334 &variant_iter,
1335 &allow_roam,
1336 &reply) < 0)
1337 goto out;
1338 } else {
1339 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1340 "Unknown argument %s", key);
1341 reply = wpas_dbus_error_invalid_args(message, key);
1342 goto out;
1343 }
1344
1345 dbus_message_iter_next(&dict_iter);
1346 }
1347
1348 if (!type) {
1349 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1350 "Scan type not specified");
1351 reply = wpas_dbus_error_invalid_args(message, key);
1352 goto out;
1353 }
1354
1355 if (!os_strcmp(type, "passive")) {
1356 if (params.num_ssids || params.extra_ies_len) {
1357 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1358 "SSIDs or IEs specified for passive scan.");
1359 reply = wpas_dbus_error_invalid_args(
1360 message, "You can specify only Channels in "
1361 "passive scan");
1362 goto out;
1363 } else if (params.freqs && params.freqs[0]) {
1364 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1365 reply = wpas_dbus_error_scan_error(
1366 message, "Scan request rejected");
1367 }
1368 } else {
1369 wpa_s->scan_req = MANUAL_SCAN_REQ;
1370 wpa_supplicant_req_scan(wpa_s, 0, 0);
1371 }
1372 } else if (!os_strcmp(type, "active")) {
1373 if (!params.num_ssids) {
1374 /* Add wildcard ssid */
1375 params.num_ssids++;
1376 }
1377 #ifdef CONFIG_AUTOSCAN
1378 autoscan_deinit(wpa_s);
1379 #endif /* CONFIG_AUTOSCAN */
1380 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) {
1381 reply = wpas_dbus_error_scan_error(
1382 message, "Scan request rejected");
1383 }
1384 } else {
1385 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1386 "Unknown scan type: %s", type);
1387 reply = wpas_dbus_error_invalid_args(message,
1388 "Wrong scan type");
1389 goto out;
1390 }
1391
1392 if (!allow_roam)
1393 wpa_s->scan_res_handler = scan_only_handler;
1394
1395 out:
1396 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1397 os_free((u8 *) params.ssids[i].ssid);
1398 os_free((u8 *) params.extra_ies);
1399 os_free(params.freqs);
1400 return reply;
1401 }
1402
1403
1404 /*
1405 * wpas_dbus_handler_disconnect - Terminate the current connection
1406 * @message: Pointer to incoming dbus message
1407 * @wpa_s: wpa_supplicant structure for a network interface
1408 * Returns: NotConnected DBus error message if already not connected
1409 * or NULL otherwise.
1410 *
1411 * Handler function for "Disconnect" method call of network interface.
1412 */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1413 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1414 struct wpa_supplicant *wpa_s)
1415 {
1416 if (wpa_s->current_ssid != NULL) {
1417 wpa_s->disconnected = 1;
1418 wpa_supplicant_deauthenticate(wpa_s,
1419 WLAN_REASON_DEAUTH_LEAVING);
1420
1421 return NULL;
1422 }
1423
1424 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1425 "This interface is not connected");
1426 }
1427
1428
1429 /**
1430 * wpas_dbus_new_iface_add_network - Add a new configured network
1431 * @message: Pointer to incoming dbus message
1432 * @wpa_s: wpa_supplicant structure for a network interface
1433 * Returns: A dbus message containing the object path of the new network
1434 *
1435 * Handler function for "AddNetwork" method call of a network interface.
1436 */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1437 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1438 struct wpa_supplicant *wpa_s)
1439 {
1440 DBusMessage *reply = NULL;
1441 DBusMessageIter iter;
1442 struct wpa_ssid *ssid = NULL;
1443 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1444 DBusError error;
1445
1446 dbus_message_iter_init(message, &iter);
1447
1448 ssid = wpa_config_add_network(wpa_s->conf);
1449 if (ssid == NULL) {
1450 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1451 "can't add new interface.");
1452 reply = wpas_dbus_error_unknown_error(
1453 message,
1454 "wpa_supplicant could not add "
1455 "a network on this interface.");
1456 goto err;
1457 }
1458 wpas_notify_network_added(wpa_s, ssid);
1459 ssid->disabled = 1;
1460 wpa_config_set_network_defaults(ssid);
1461
1462 dbus_error_init(&error);
1463 if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1464 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1465 "control interface couldn't set network "
1466 "properties");
1467 reply = wpas_dbus_reply_new_from_error(message, &error,
1468 DBUS_ERROR_INVALID_ARGS,
1469 "Failed to add network");
1470 dbus_error_free(&error);
1471 goto err;
1472 }
1473
1474 /* Construct the object path for this network. */
1475 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1476 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1477 wpa_s->dbus_new_path, ssid->id);
1478
1479 reply = dbus_message_new_method_return(message);
1480 if (reply == NULL) {
1481 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1482 NULL);
1483 goto err;
1484 }
1485 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1486 DBUS_TYPE_INVALID)) {
1487 dbus_message_unref(reply);
1488 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1489 NULL);
1490 goto err;
1491 }
1492
1493 return reply;
1494
1495 err:
1496 if (ssid) {
1497 wpas_notify_network_removed(wpa_s, ssid);
1498 wpa_config_remove_network(wpa_s->conf, ssid->id);
1499 }
1500 return reply;
1501 }
1502
1503
1504 /**
1505 * wpas_dbus_handler_reassociate - Reassociate
1506 * @message: Pointer to incoming dbus message
1507 * @wpa_s: wpa_supplicant structure for a network interface
1508 * Returns: InterfaceDisabled DBus error message if disabled
1509 * or NULL otherwise.
1510 *
1511 * Handler function for "Reassociate" method call of network interface.
1512 */
wpas_dbus_handler_reassociate(DBusMessage * message,struct wpa_supplicant * wpa_s)1513 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1514 struct wpa_supplicant *wpa_s)
1515 {
1516 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1517 wpas_request_connection(wpa_s);
1518 return NULL;
1519 }
1520
1521 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1522 "This interface is disabled");
1523 }
1524
1525
1526 /**
1527 * wpas_dbus_handler_reattach - Reattach to current AP
1528 * @message: Pointer to incoming dbus message
1529 * @wpa_s: wpa_supplicant structure for a network interface
1530 * Returns: NotConnected DBus error message if not connected
1531 * or NULL otherwise.
1532 *
1533 * Handler function for "Reattach" method call of network interface.
1534 */
wpas_dbus_handler_reattach(DBusMessage * message,struct wpa_supplicant * wpa_s)1535 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1536 struct wpa_supplicant *wpa_s)
1537 {
1538 if (wpa_s->current_ssid != NULL) {
1539 wpa_s->reattach = 1;
1540 wpas_request_connection(wpa_s);
1541 return NULL;
1542 }
1543
1544 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1545 "This interface is not connected");
1546 }
1547
1548
1549 /**
1550 * wpas_dbus_handler_remove_network - Remove a configured network
1551 * @message: Pointer to incoming dbus message
1552 * @wpa_s: wpa_supplicant structure for a network interface
1553 * Returns: NULL on success or dbus error on failure
1554 *
1555 * Handler function for "RemoveNetwork" method call of a network interface.
1556 */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1557 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1558 struct wpa_supplicant *wpa_s)
1559 {
1560 DBusMessage *reply = NULL;
1561 const char *op;
1562 char *iface = NULL, *net_id = NULL;
1563 int id;
1564 struct wpa_ssid *ssid;
1565 int was_disabled;
1566
1567 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1568 DBUS_TYPE_INVALID);
1569
1570 /* Extract the network ID and ensure the network */
1571 /* is actually a child of this interface */
1572 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1573 if (iface == NULL || net_id == NULL ||
1574 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1575 reply = wpas_dbus_error_invalid_args(message, op);
1576 goto out;
1577 }
1578
1579 errno = 0;
1580 id = strtoul(net_id, NULL, 10);
1581 if (errno != 0) {
1582 reply = wpas_dbus_error_invalid_args(message, op);
1583 goto out;
1584 }
1585
1586 ssid = wpa_config_get_network(wpa_s->conf, id);
1587 if (ssid == NULL) {
1588 reply = wpas_dbus_error_network_unknown(message);
1589 goto out;
1590 }
1591
1592 was_disabled = ssid->disabled;
1593
1594 wpas_notify_network_removed(wpa_s, ssid);
1595
1596 if (ssid == wpa_s->current_ssid)
1597 wpa_supplicant_deauthenticate(wpa_s,
1598 WLAN_REASON_DEAUTH_LEAVING);
1599 else if (!was_disabled && wpa_s->sched_scanning) {
1600 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
1601 "network from filters");
1602 wpa_supplicant_cancel_sched_scan(wpa_s);
1603 wpa_supplicant_req_scan(wpa_s, 0, 0);
1604 }
1605
1606 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1607 wpa_printf(MSG_ERROR,
1608 "wpas_dbus_handler_remove_network[dbus]: "
1609 "error occurred when removing network %d", id);
1610 reply = wpas_dbus_error_unknown_error(
1611 message, "error removing the specified network on "
1612 "this interface.");
1613 goto out;
1614 }
1615
1616 out:
1617 os_free(iface);
1618 os_free(net_id);
1619 return reply;
1620 }
1621
1622
remove_network(void * arg,struct wpa_ssid * ssid)1623 static void remove_network(void *arg, struct wpa_ssid *ssid)
1624 {
1625 struct wpa_supplicant *wpa_s = arg;
1626
1627 wpas_notify_network_removed(wpa_s, ssid);
1628
1629 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1630 wpa_printf(MSG_ERROR,
1631 "wpas_dbus_handler_remove_all_networks[dbus]: "
1632 "error occurred when removing network %d",
1633 ssid->id);
1634 return;
1635 }
1636
1637 if (ssid == wpa_s->current_ssid)
1638 wpa_supplicant_deauthenticate(wpa_s,
1639 WLAN_REASON_DEAUTH_LEAVING);
1640 }
1641
1642
1643 /**
1644 * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1645 * @message: Pointer to incoming dbus message
1646 * @wpa_s: wpa_supplicant structure for a network interface
1647 * Returns: NULL on success or dbus error on failure
1648 *
1649 * Handler function for "RemoveAllNetworks" method call of a network interface.
1650 */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)1651 DBusMessage * wpas_dbus_handler_remove_all_networks(
1652 DBusMessage *message, struct wpa_supplicant *wpa_s)
1653 {
1654 if (wpa_s->sched_scanning)
1655 wpa_supplicant_cancel_sched_scan(wpa_s);
1656
1657 /* NB: could check for failure and return an error */
1658 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1659 return NULL;
1660 }
1661
1662
1663 /**
1664 * wpas_dbus_handler_select_network - Attempt association with a network
1665 * @message: Pointer to incoming dbus message
1666 * @wpa_s: wpa_supplicant structure for a network interface
1667 * Returns: NULL on success or dbus error on failure
1668 *
1669 * Handler function for "SelectNetwork" method call of network interface.
1670 */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1671 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1672 struct wpa_supplicant *wpa_s)
1673 {
1674 DBusMessage *reply = NULL;
1675 const char *op;
1676 char *iface = NULL, *net_id = NULL;
1677 int id;
1678 struct wpa_ssid *ssid;
1679
1680 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1681 DBUS_TYPE_INVALID);
1682
1683 /* Extract the network ID and ensure the network */
1684 /* is actually a child of this interface */
1685 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1686 if (iface == NULL || net_id == NULL ||
1687 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1688 reply = wpas_dbus_error_invalid_args(message, op);
1689 goto out;
1690 }
1691
1692 errno = 0;
1693 id = strtoul(net_id, NULL, 10);
1694 if (errno != 0) {
1695 reply = wpas_dbus_error_invalid_args(message, op);
1696 goto out;
1697 }
1698
1699 ssid = wpa_config_get_network(wpa_s->conf, id);
1700 if (ssid == NULL) {
1701 reply = wpas_dbus_error_network_unknown(message);
1702 goto out;
1703 }
1704
1705 /* Finally, associate with the network */
1706 wpa_supplicant_select_network(wpa_s, ssid);
1707
1708 out:
1709 os_free(iface);
1710 os_free(net_id);
1711 return reply;
1712 }
1713
1714
1715 /**
1716 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1717 * @message: Pointer to incoming dbus message
1718 * @wpa_s: wpa_supplicant structure for a network interface
1719 * Returns: NULL on success or dbus error on failure
1720 *
1721 * Handler function for "NetworkReply" method call of network interface.
1722 */
wpas_dbus_handler_network_reply(DBusMessage * message,struct wpa_supplicant * wpa_s)1723 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1724 struct wpa_supplicant *wpa_s)
1725 {
1726 #ifdef IEEE8021X_EAPOL
1727 DBusMessage *reply = NULL;
1728 const char *op, *field, *value;
1729 char *iface = NULL, *net_id = NULL;
1730 int id;
1731 struct wpa_ssid *ssid;
1732
1733 if (!dbus_message_get_args(message, NULL,
1734 DBUS_TYPE_OBJECT_PATH, &op,
1735 DBUS_TYPE_STRING, &field,
1736 DBUS_TYPE_STRING, &value,
1737 DBUS_TYPE_INVALID))
1738 return wpas_dbus_error_invalid_args(message, NULL);
1739
1740 /* Extract the network ID and ensure the network */
1741 /* is actually a child of this interface */
1742 iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1743 if (iface == NULL || net_id == NULL ||
1744 os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1745 reply = wpas_dbus_error_invalid_args(message, op);
1746 goto out;
1747 }
1748
1749 errno = 0;
1750 id = strtoul(net_id, NULL, 10);
1751 if (errno != 0) {
1752 reply = wpas_dbus_error_invalid_args(message, net_id);
1753 goto out;
1754 }
1755
1756 ssid = wpa_config_get_network(wpa_s->conf, id);
1757 if (ssid == NULL) {
1758 reply = wpas_dbus_error_network_unknown(message);
1759 goto out;
1760 }
1761
1762 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1763 field, value) < 0)
1764 reply = wpas_dbus_error_invalid_args(message, field);
1765 else {
1766 /* Tell EAP to retry immediately */
1767 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1768 }
1769
1770 out:
1771 os_free(iface);
1772 os_free(net_id);
1773 return reply;
1774 #else /* IEEE8021X_EAPOL */
1775 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1776 return wpas_dbus_error_unknown_error(message, "802.1X not included");
1777 #endif /* IEEE8021X_EAPOL */
1778 }
1779
1780
1781 #ifndef CONFIG_NO_CONFIG_BLOBS
1782
1783 /**
1784 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1785 * @message: Pointer to incoming dbus message
1786 * @wpa_s: %wpa_supplicant data structure
1787 * Returns: A dbus message containing an error on failure or NULL on success
1788 *
1789 * Asks wpa_supplicant to internally store a binary blobs.
1790 */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1791 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1792 struct wpa_supplicant *wpa_s)
1793 {
1794 DBusMessage *reply = NULL;
1795 DBusMessageIter iter, array_iter;
1796
1797 char *blob_name;
1798 u8 *blob_data;
1799 int blob_len;
1800 struct wpa_config_blob *blob = NULL;
1801
1802 dbus_message_iter_init(message, &iter);
1803 dbus_message_iter_get_basic(&iter, &blob_name);
1804
1805 if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1806 return dbus_message_new_error(message,
1807 WPAS_DBUS_ERROR_BLOB_EXISTS,
1808 NULL);
1809 }
1810
1811 dbus_message_iter_next(&iter);
1812 dbus_message_iter_recurse(&iter, &array_iter);
1813
1814 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1815
1816 blob = os_zalloc(sizeof(*blob));
1817 if (!blob) {
1818 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1819 NULL);
1820 goto err;
1821 }
1822
1823 blob->data = os_malloc(blob_len);
1824 if (!blob->data) {
1825 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1826 NULL);
1827 goto err;
1828 }
1829 os_memcpy(blob->data, blob_data, blob_len);
1830
1831 blob->len = blob_len;
1832 blob->name = os_strdup(blob_name);
1833 if (!blob->name) {
1834 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1835 NULL);
1836 goto err;
1837 }
1838
1839 wpa_config_set_blob(wpa_s->conf, blob);
1840 wpas_notify_blob_added(wpa_s, blob->name);
1841
1842 return reply;
1843
1844 err:
1845 if (blob) {
1846 os_free(blob->name);
1847 os_free(blob->data);
1848 os_free(blob);
1849 }
1850 return reply;
1851 }
1852
1853
1854 /**
1855 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1856 * @message: Pointer to incoming dbus message
1857 * @wpa_s: %wpa_supplicant data structure
1858 * Returns: A dbus message containing array of bytes (blob)
1859 *
1860 * Gets one wpa_supplicant's binary blobs.
1861 */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1862 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1863 struct wpa_supplicant *wpa_s)
1864 {
1865 DBusMessage *reply = NULL;
1866 DBusMessageIter iter, array_iter;
1867
1868 char *blob_name;
1869 const struct wpa_config_blob *blob;
1870
1871 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1872 DBUS_TYPE_INVALID);
1873
1874 blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1875 if (!blob) {
1876 return dbus_message_new_error(message,
1877 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1878 "Blob id not set");
1879 }
1880
1881 reply = dbus_message_new_method_return(message);
1882 if (!reply) {
1883 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1884 NULL);
1885 goto out;
1886 }
1887
1888 dbus_message_iter_init_append(reply, &iter);
1889
1890 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1891 DBUS_TYPE_BYTE_AS_STRING,
1892 &array_iter)) {
1893 dbus_message_unref(reply);
1894 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1895 NULL);
1896 goto out;
1897 }
1898
1899 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1900 &(blob->data), blob->len)) {
1901 dbus_message_unref(reply);
1902 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1903 NULL);
1904 goto out;
1905 }
1906
1907 if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1908 dbus_message_unref(reply);
1909 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1910 NULL);
1911 goto out;
1912 }
1913
1914 out:
1915 return reply;
1916 }
1917
1918
1919 /**
1920 * wpas_remove_handler_remove_blob - Remove named binary blob
1921 * @message: Pointer to incoming dbus message
1922 * @wpa_s: %wpa_supplicant data structure
1923 * Returns: NULL on success or dbus error
1924 *
1925 * Asks wpa_supplicant to internally remove a binary blobs.
1926 */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1927 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1928 struct wpa_supplicant *wpa_s)
1929 {
1930 DBusMessage *reply = NULL;
1931 char *blob_name;
1932
1933 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1934 DBUS_TYPE_INVALID);
1935
1936 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1937 return dbus_message_new_error(message,
1938 WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1939 "Blob id not set");
1940 }
1941 wpas_notify_blob_removed(wpa_s, blob_name);
1942
1943 return reply;
1944
1945 }
1946
1947 #endif /* CONFIG_NO_CONFIG_BLOBS */
1948
1949
1950 /*
1951 * wpas_dbus_handler_flush_bss - Flush the BSS cache
1952 * @message: Pointer to incoming dbus message
1953 * @wpa_s: wpa_supplicant structure for a network interface
1954 * Returns: NULL
1955 *
1956 * Handler function for "FlushBSS" method call of network interface.
1957 */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)1958 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1959 struct wpa_supplicant *wpa_s)
1960 {
1961 dbus_uint32_t age;
1962
1963 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1964 DBUS_TYPE_INVALID);
1965
1966 if (age == 0)
1967 wpa_bss_flush(wpa_s);
1968 else
1969 wpa_bss_flush_by_age(wpa_s, age);
1970
1971 return NULL;
1972 }
1973
1974
1975 #ifdef CONFIG_AUTOSCAN
1976 /**
1977 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1978 * @message: Pointer to incoming dbus message
1979 * @wpa_s: wpa_supplicant structure for a network interface
1980 * Returns: NULL
1981 *
1982 * Handler function for "AutoScan" method call of network interface.
1983 */
wpas_dbus_handler_autoscan(DBusMessage * message,struct wpa_supplicant * wpa_s)1984 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1985 struct wpa_supplicant *wpa_s)
1986 {
1987 DBusMessage *reply = NULL;
1988 enum wpa_states state = wpa_s->wpa_state;
1989 char *arg;
1990
1991 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
1992 DBUS_TYPE_INVALID);
1993
1994 if (arg != NULL && os_strlen(arg) > 0) {
1995 char *tmp;
1996 tmp = os_strdup(arg);
1997 if (tmp == NULL) {
1998 reply = dbus_message_new_error(message,
1999 DBUS_ERROR_NO_MEMORY,
2000 NULL);
2001 } else {
2002 os_free(wpa_s->conf->autoscan);
2003 wpa_s->conf->autoscan = tmp;
2004 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
2005 autoscan_init(wpa_s, 1);
2006 else if (state == WPA_SCANNING)
2007 wpa_supplicant_reinit_autoscan(wpa_s);
2008 }
2009 } else if (arg != NULL && os_strlen(arg) == 0) {
2010 os_free(wpa_s->conf->autoscan);
2011 wpa_s->conf->autoscan = NULL;
2012 autoscan_deinit(wpa_s);
2013 } else
2014 reply = dbus_message_new_error(message,
2015 DBUS_ERROR_INVALID_ARGS,
2016 NULL);
2017
2018 return reply;
2019 }
2020 #endif /* CONFIG_AUTOSCAN */
2021
2022
2023 /*
2024 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2025 * @message: Pointer to incoming dbus message
2026 * @wpa_s: wpa_supplicant structure for a network interface
2027 * Returns: NULL
2028 *
2029 * Handler function for "EAPLogoff" method call of network interface.
2030 */
wpas_dbus_handler_eap_logoff(DBusMessage * message,struct wpa_supplicant * wpa_s)2031 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2032 struct wpa_supplicant *wpa_s)
2033 {
2034 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2035 return NULL;
2036 }
2037
2038
2039 /*
2040 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2041 * @message: Pointer to incoming dbus message
2042 * @wpa_s: wpa_supplicant structure for a network interface
2043 * Returns: NULL
2044 *
2045 * Handler function for "EAPLogin" method call of network interface.
2046 */
wpas_dbus_handler_eap_logon(DBusMessage * message,struct wpa_supplicant * wpa_s)2047 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2048 struct wpa_supplicant *wpa_s)
2049 {
2050 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2051 return NULL;
2052 }
2053
2054
2055 #ifdef CONFIG_TDLS
2056
get_peer_hwaddr_helper(DBusMessage * message,const char * func_name,u8 * peer_address,DBusMessage ** error)2057 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2058 u8 *peer_address, DBusMessage **error)
2059 {
2060 const char *peer_string;
2061
2062 *error = NULL;
2063
2064 if (!dbus_message_get_args(message, NULL,
2065 DBUS_TYPE_STRING, &peer_string,
2066 DBUS_TYPE_INVALID)) {
2067 *error = wpas_dbus_error_invalid_args(message, NULL);
2068 return -1;
2069 }
2070
2071 if (hwaddr_aton(peer_string, peer_address)) {
2072 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2073 func_name, peer_string);
2074 *error = wpas_dbus_error_invalid_args(
2075 message, "Invalid hardware address format");
2076 return -1;
2077 }
2078
2079 return 0;
2080 }
2081
2082
2083 /*
2084 * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2085 * @message: Pointer to incoming dbus message
2086 * @wpa_s: wpa_supplicant structure for a network interface
2087 * Returns: NULL indicating success or DBus error message on failure
2088 *
2089 * Handler function for "TDLSDiscover" method call of network interface.
2090 */
wpas_dbus_handler_tdls_discover(DBusMessage * message,struct wpa_supplicant * wpa_s)2091 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2092 struct wpa_supplicant *wpa_s)
2093 {
2094 u8 peer[ETH_ALEN];
2095 DBusMessage *error_reply;
2096 int ret;
2097
2098 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2099 return error_reply;
2100
2101 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2102
2103 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2104 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2105 else
2106 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2107
2108 if (ret) {
2109 return wpas_dbus_error_unknown_error(
2110 message, "error performing TDLS discovery");
2111 }
2112
2113 return NULL;
2114 }
2115
2116
2117 /*
2118 * wpas_dbus_handler_tdls_setup - Setup TDLS session
2119 * @message: Pointer to incoming dbus message
2120 * @wpa_s: wpa_supplicant structure for a network interface
2121 * Returns: NULL indicating success or DBus error message on failure
2122 *
2123 * Handler function for "TDLSSetup" method call of network interface.
2124 */
wpas_dbus_handler_tdls_setup(DBusMessage * message,struct wpa_supplicant * wpa_s)2125 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2126 struct wpa_supplicant *wpa_s)
2127 {
2128 u8 peer[ETH_ALEN];
2129 DBusMessage *error_reply;
2130 int ret;
2131
2132 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2133 return error_reply;
2134
2135 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2136
2137 wpa_tdls_remove(wpa_s->wpa, peer);
2138 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2139 ret = wpa_tdls_start(wpa_s->wpa, peer);
2140 else
2141 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2142
2143 if (ret) {
2144 return wpas_dbus_error_unknown_error(
2145 message, "error performing TDLS setup");
2146 }
2147
2148 return NULL;
2149 }
2150
2151
2152 /*
2153 * wpas_dbus_handler_tdls_status - Return TDLS session status
2154 * @message: Pointer to incoming dbus message
2155 * @wpa_s: wpa_supplicant structure for a network interface
2156 * Returns: A string representing the state of the link to this TDLS peer
2157 *
2158 * Handler function for "TDLSStatus" method call of network interface.
2159 */
wpas_dbus_handler_tdls_status(DBusMessage * message,struct wpa_supplicant * wpa_s)2160 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2161 struct wpa_supplicant *wpa_s)
2162 {
2163 u8 peer[ETH_ALEN];
2164 DBusMessage *reply;
2165 const char *tdls_status;
2166
2167 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2168 return reply;
2169
2170 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2171
2172 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2173
2174 reply = dbus_message_new_method_return(message);
2175 dbus_message_append_args(reply, DBUS_TYPE_STRING,
2176 &tdls_status, DBUS_TYPE_INVALID);
2177 return reply;
2178 }
2179
2180
2181 /*
2182 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2183 * @message: Pointer to incoming dbus message
2184 * @wpa_s: wpa_supplicant structure for a network interface
2185 * Returns: NULL indicating success or DBus error message on failure
2186 *
2187 * Handler function for "TDLSTeardown" method call of network interface.
2188 */
wpas_dbus_handler_tdls_teardown(DBusMessage * message,struct wpa_supplicant * wpa_s)2189 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2190 struct wpa_supplicant *wpa_s)
2191 {
2192 u8 peer[ETH_ALEN];
2193 DBusMessage *error_reply;
2194 int ret;
2195
2196 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2197 return error_reply;
2198
2199 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2200
2201 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2202 ret = wpa_tdls_teardown_link(
2203 wpa_s->wpa, peer,
2204 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2205 else
2206 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2207
2208 if (ret) {
2209 return wpas_dbus_error_unknown_error(
2210 message, "error performing TDLS teardown");
2211 }
2212
2213 return NULL;
2214 }
2215
2216 #endif /* CONFIG_TDLS */
2217
2218
2219 /**
2220 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2221 * @message: Pointer to incoming dbus message
2222 * @wpa_s: %wpa_supplicant data structure
2223 * Returns: A dbus message containing an error on failure or NULL on success
2224 *
2225 * Sets the PKCS #11 engine and module path.
2226 */
wpas_dbus_handler_set_pkcs11_engine_and_module_path(DBusMessage * message,struct wpa_supplicant * wpa_s)2227 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2228 DBusMessage *message, struct wpa_supplicant *wpa_s)
2229 {
2230 DBusMessageIter iter;
2231 char *value = NULL;
2232 char *pkcs11_engine_path = NULL;
2233 char *pkcs11_module_path = NULL;
2234
2235 dbus_message_iter_init(message, &iter);
2236 dbus_message_iter_get_basic(&iter, &value);
2237 if (value == NULL) {
2238 return dbus_message_new_error(
2239 message, DBUS_ERROR_INVALID_ARGS,
2240 "Invalid pkcs11_engine_path argument");
2241 }
2242 /* Empty path defaults to NULL */
2243 if (os_strlen(value))
2244 pkcs11_engine_path = value;
2245
2246 dbus_message_iter_next(&iter);
2247 dbus_message_iter_get_basic(&iter, &value);
2248 if (value == NULL) {
2249 os_free(pkcs11_engine_path);
2250 return dbus_message_new_error(
2251 message, DBUS_ERROR_INVALID_ARGS,
2252 "Invalid pkcs11_module_path argument");
2253 }
2254 /* Empty path defaults to NULL */
2255 if (os_strlen(value))
2256 pkcs11_module_path = value;
2257
2258 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2259 pkcs11_module_path))
2260 return dbus_message_new_error(
2261 message, DBUS_ERROR_FAILED,
2262 "Reinit of the EAPOL state machine with the new PKCS "
2263 "#11 engine and module path failed.");
2264
2265 wpa_dbus_mark_property_changed(
2266 wpa_s->global->dbus, wpa_s->dbus_new_path,
2267 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2268 wpa_dbus_mark_property_changed(
2269 wpa_s->global->dbus, wpa_s->dbus_new_path,
2270 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2271
2272 return NULL;
2273 }
2274
2275
2276 /**
2277 * wpas_dbus_getter_capabilities - Return interface capabilities
2278 * @iter: Pointer to incoming dbus message iter
2279 * @error: Location to store error on failure
2280 * @user_data: Function specific data
2281 * Returns: TRUE on success, FALSE on failure
2282 *
2283 * Getter for "Capabilities" property of an interface.
2284 */
wpas_dbus_getter_capabilities(DBusMessageIter * iter,DBusError * error,void * user_data)2285 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2286 DBusError *error, void *user_data)
2287 {
2288 struct wpa_supplicant *wpa_s = user_data;
2289 struct wpa_driver_capa capa;
2290 int res;
2291 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2292 variant_iter;
2293 const char *scans[] = { "active", "passive", "ssid" };
2294
2295 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2296 "a{sv}", &variant_iter))
2297 goto nomem;
2298
2299 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2300 goto nomem;
2301
2302 res = wpa_drv_get_capa(wpa_s, &capa);
2303
2304 /***** pairwise cipher */
2305 if (res < 0) {
2306 const char *args[] = {"ccmp", "tkip", "none"};
2307 if (!wpa_dbus_dict_append_string_array(
2308 &iter_dict, "Pairwise", args,
2309 ARRAY_SIZE(args)))
2310 goto nomem;
2311 } else {
2312 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2313 &iter_dict_entry,
2314 &iter_dict_val,
2315 &iter_array))
2316 goto nomem;
2317
2318 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
2319 if (!wpa_dbus_dict_string_array_add_element(
2320 &iter_array, "ccmp-256"))
2321 goto nomem;
2322 }
2323
2324 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
2325 if (!wpa_dbus_dict_string_array_add_element(
2326 &iter_array, "gcmp-256"))
2327 goto nomem;
2328 }
2329
2330 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2331 if (!wpa_dbus_dict_string_array_add_element(
2332 &iter_array, "ccmp"))
2333 goto nomem;
2334 }
2335
2336 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2337 if (!wpa_dbus_dict_string_array_add_element(
2338 &iter_array, "gcmp"))
2339 goto nomem;
2340 }
2341
2342 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2343 if (!wpa_dbus_dict_string_array_add_element(
2344 &iter_array, "tkip"))
2345 goto nomem;
2346 }
2347
2348 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2349 if (!wpa_dbus_dict_string_array_add_element(
2350 &iter_array, "none"))
2351 goto nomem;
2352 }
2353
2354 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2355 &iter_dict_entry,
2356 &iter_dict_val,
2357 &iter_array))
2358 goto nomem;
2359 }
2360
2361 /***** group cipher */
2362 if (res < 0) {
2363 const char *args[] = {
2364 "ccmp", "tkip", "wep104", "wep40"
2365 };
2366 if (!wpa_dbus_dict_append_string_array(
2367 &iter_dict, "Group", args,
2368 ARRAY_SIZE(args)))
2369 goto nomem;
2370 } else {
2371 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2372 &iter_dict_entry,
2373 &iter_dict_val,
2374 &iter_array))
2375 goto nomem;
2376
2377 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
2378 if (!wpa_dbus_dict_string_array_add_element(
2379 &iter_array, "ccmp-256"))
2380 goto nomem;
2381 }
2382
2383 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
2384 if (!wpa_dbus_dict_string_array_add_element(
2385 &iter_array, "gcmp-256"))
2386 goto nomem;
2387 }
2388
2389 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
2390 if (!wpa_dbus_dict_string_array_add_element(
2391 &iter_array, "ccmp"))
2392 goto nomem;
2393 }
2394
2395 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) {
2396 if (!wpa_dbus_dict_string_array_add_element(
2397 &iter_array, "gcmp"))
2398 goto nomem;
2399 }
2400
2401 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
2402 if (!wpa_dbus_dict_string_array_add_element(
2403 &iter_array, "tkip"))
2404 goto nomem;
2405 }
2406
2407 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
2408 if (!wpa_dbus_dict_string_array_add_element(
2409 &iter_array, "wep104"))
2410 goto nomem;
2411 }
2412
2413 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
2414 if (!wpa_dbus_dict_string_array_add_element(
2415 &iter_array, "wep40"))
2416 goto nomem;
2417 }
2418
2419 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2420 &iter_dict_entry,
2421 &iter_dict_val,
2422 &iter_array))
2423 goto nomem;
2424 }
2425
2426 /***** key management */
2427 if (res < 0) {
2428 const char *args[] = {
2429 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2430 #ifdef CONFIG_WPS
2431 "wps",
2432 #endif /* CONFIG_WPS */
2433 "none"
2434 };
2435 if (!wpa_dbus_dict_append_string_array(
2436 &iter_dict, "KeyMgmt", args,
2437 ARRAY_SIZE(args)))
2438 goto nomem;
2439 } else {
2440 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2441 &iter_dict_entry,
2442 &iter_dict_val,
2443 &iter_array))
2444 goto nomem;
2445
2446 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2447 "none"))
2448 goto nomem;
2449
2450 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2451 "ieee8021x"))
2452 goto nomem;
2453
2454 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2455 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2456 if (!wpa_dbus_dict_string_array_add_element(
2457 &iter_array, "wpa-eap"))
2458 goto nomem;
2459
2460 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
2461 if (!wpa_dbus_dict_string_array_add_element(
2462 &iter_array, "wpa-ft-eap"))
2463 goto nomem;
2464
2465 /* TODO: Ensure that driver actually supports sha256 encryption. */
2466 #ifdef CONFIG_IEEE80211W
2467 if (!wpa_dbus_dict_string_array_add_element(
2468 &iter_array, "wpa-eap-sha256"))
2469 goto nomem;
2470 #endif /* CONFIG_IEEE80211W */
2471 }
2472
2473 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2474 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2475 if (!wpa_dbus_dict_string_array_add_element(
2476 &iter_array, "wpa-psk"))
2477 goto nomem;
2478
2479 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
2480 if (!wpa_dbus_dict_string_array_add_element(
2481 &iter_array, "wpa-ft-psk"))
2482 goto nomem;
2483
2484 /* TODO: Ensure that driver actually supports sha256 encryption. */
2485 #ifdef CONFIG_IEEE80211W
2486 if (!wpa_dbus_dict_string_array_add_element(
2487 &iter_array, "wpa-psk-sha256"))
2488 goto nomem;
2489 #endif /* CONFIG_IEEE80211W */
2490 }
2491
2492 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
2493 if (!wpa_dbus_dict_string_array_add_element(
2494 &iter_array, "wpa-none"))
2495 goto nomem;
2496 }
2497
2498
2499 #ifdef CONFIG_WPS
2500 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2501 "wps"))
2502 goto nomem;
2503 #endif /* CONFIG_WPS */
2504
2505 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2506 &iter_dict_entry,
2507 &iter_dict_val,
2508 &iter_array))
2509 goto nomem;
2510 }
2511
2512 /***** WPA protocol */
2513 if (res < 0) {
2514 const char *args[] = { "rsn", "wpa" };
2515 if (!wpa_dbus_dict_append_string_array(
2516 &iter_dict, "Protocol", args,
2517 ARRAY_SIZE(args)))
2518 goto nomem;
2519 } else {
2520 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2521 &iter_dict_entry,
2522 &iter_dict_val,
2523 &iter_array))
2524 goto nomem;
2525
2526 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2527 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2528 if (!wpa_dbus_dict_string_array_add_element(
2529 &iter_array, "rsn"))
2530 goto nomem;
2531 }
2532
2533 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2534 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
2535 if (!wpa_dbus_dict_string_array_add_element(
2536 &iter_array, "wpa"))
2537 goto nomem;
2538 }
2539
2540 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2541 &iter_dict_entry,
2542 &iter_dict_val,
2543 &iter_array))
2544 goto nomem;
2545 }
2546
2547 /***** auth alg */
2548 if (res < 0) {
2549 const char *args[] = { "open", "shared", "leap" };
2550 if (!wpa_dbus_dict_append_string_array(
2551 &iter_dict, "AuthAlg", args,
2552 ARRAY_SIZE(args)))
2553 goto nomem;
2554 } else {
2555 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2556 &iter_dict_entry,
2557 &iter_dict_val,
2558 &iter_array))
2559 goto nomem;
2560
2561 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
2562 if (!wpa_dbus_dict_string_array_add_element(
2563 &iter_array, "open"))
2564 goto nomem;
2565 }
2566
2567 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
2568 if (!wpa_dbus_dict_string_array_add_element(
2569 &iter_array, "shared"))
2570 goto nomem;
2571 }
2572
2573 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2574 if (!wpa_dbus_dict_string_array_add_element(
2575 &iter_array, "leap"))
2576 goto nomem;
2577 }
2578
2579 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2580 &iter_dict_entry,
2581 &iter_dict_val,
2582 &iter_array))
2583 goto nomem;
2584 }
2585
2586 /***** Scan */
2587 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2588 ARRAY_SIZE(scans)))
2589 goto nomem;
2590
2591 /***** Modes */
2592 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2593 &iter_dict_entry,
2594 &iter_dict_val,
2595 &iter_array))
2596 goto nomem;
2597
2598 if (!wpa_dbus_dict_string_array_add_element(
2599 &iter_array, "infrastructure"))
2600 goto nomem;
2601
2602 if (!wpa_dbus_dict_string_array_add_element(
2603 &iter_array, "ad-hoc"))
2604 goto nomem;
2605
2606 if (res >= 0) {
2607 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2608 if (!wpa_dbus_dict_string_array_add_element(
2609 &iter_array, "ap"))
2610 goto nomem;
2611 }
2612
2613 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2614 if (!wpa_dbus_dict_string_array_add_element(
2615 &iter_array, "p2p"))
2616 goto nomem;
2617 }
2618 }
2619
2620 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2621 &iter_dict_entry,
2622 &iter_dict_val,
2623 &iter_array))
2624 goto nomem;
2625 /***** Modes end */
2626
2627 if (res >= 0) {
2628 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2629
2630 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2631 max_scan_ssid))
2632 goto nomem;
2633 }
2634
2635 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2636 goto nomem;
2637 if (!dbus_message_iter_close_container(iter, &variant_iter))
2638 goto nomem;
2639
2640 return TRUE;
2641
2642 nomem:
2643 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2644 return FALSE;
2645 }
2646
2647
2648 /**
2649 * wpas_dbus_getter_state - Get interface state
2650 * @iter: Pointer to incoming dbus message iter
2651 * @error: Location to store error on failure
2652 * @user_data: Function specific data
2653 * Returns: TRUE on success, FALSE on failure
2654 *
2655 * Getter for "State" property.
2656 */
wpas_dbus_getter_state(DBusMessageIter * iter,DBusError * error,void * user_data)2657 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2658 void *user_data)
2659 {
2660 struct wpa_supplicant *wpa_s = user_data;
2661 const char *str_state;
2662 char *state_ls, *tmp;
2663 dbus_bool_t success = FALSE;
2664
2665 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2666
2667 /* make state string lowercase to fit new DBus API convention
2668 */
2669 state_ls = tmp = os_strdup(str_state);
2670 if (!tmp) {
2671 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2672 return FALSE;
2673 }
2674 while (*tmp) {
2675 *tmp = tolower(*tmp);
2676 tmp++;
2677 }
2678
2679 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2680 &state_ls, error);
2681
2682 os_free(state_ls);
2683
2684 return success;
2685 }
2686
2687
2688 /**
2689 * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2690 * @iter: Pointer to incoming dbus message iter
2691 * @error: Location to store error on failure
2692 * @user_data: Function specific data
2693 * Returns: TRUE on success, FALSE on failure
2694 *
2695 * Getter for "scanning" property.
2696 */
wpas_dbus_getter_scanning(DBusMessageIter * iter,DBusError * error,void * user_data)2697 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2698 void *user_data)
2699 {
2700 struct wpa_supplicant *wpa_s = user_data;
2701 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2702
2703 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2704 &scanning, error);
2705 }
2706
2707
2708 /**
2709 * wpas_dbus_getter_ap_scan - Control roaming mode
2710 * @iter: Pointer to incoming dbus message iter
2711 * @error: Location to store error on failure
2712 * @user_data: Function specific data
2713 * Returns: TRUE on success, FALSE on failure
2714 *
2715 * Getter function for "ApScan" property.
2716 */
wpas_dbus_getter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2717 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2718 void *user_data)
2719 {
2720 struct wpa_supplicant *wpa_s = user_data;
2721 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2722
2723 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2724 &ap_scan, error);
2725 }
2726
2727
2728 /**
2729 * wpas_dbus_setter_ap_scan - Control roaming mode
2730 * @iter: Pointer to incoming dbus message iter
2731 * @error: Location to store error on failure
2732 * @user_data: Function specific data
2733 * Returns: TRUE on success, FALSE on failure
2734 *
2735 * Setter function for "ApScan" property.
2736 */
wpas_dbus_setter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2737 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2738 void *user_data)
2739 {
2740 struct wpa_supplicant *wpa_s = user_data;
2741 dbus_uint32_t ap_scan;
2742
2743 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2744 &ap_scan))
2745 return FALSE;
2746
2747 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2748 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2749 "ap_scan must be 0, 1, or 2");
2750 return FALSE;
2751 }
2752 return TRUE;
2753 }
2754
2755
2756 /**
2757 * wpas_dbus_getter_fast_reauth - Control fast
2758 * reauthentication (TLS session resumption)
2759 * @iter: Pointer to incoming dbus message iter
2760 * @error: Location to store error on failure
2761 * @user_data: Function specific data
2762 * Returns: TRUE on success, FALSE on failure
2763 *
2764 * Getter function for "FastReauth" property.
2765 */
wpas_dbus_getter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2766 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2767 DBusError *error,
2768 void *user_data)
2769 {
2770 struct wpa_supplicant *wpa_s = user_data;
2771 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2772
2773 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2774 &fast_reauth, error);
2775 }
2776
2777
2778 /**
2779 * wpas_dbus_setter_fast_reauth - Control fast
2780 * reauthentication (TLS session resumption)
2781 * @iter: Pointer to incoming dbus message iter
2782 * @error: Location to store error on failure
2783 * @user_data: Function specific data
2784 * Returns: TRUE on success, FALSE on failure
2785 *
2786 * Setter function for "FastReauth" property.
2787 */
wpas_dbus_setter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2788 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2789 DBusError *error,
2790 void *user_data)
2791 {
2792 struct wpa_supplicant *wpa_s = user_data;
2793 dbus_bool_t fast_reauth;
2794
2795 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2796 &fast_reauth))
2797 return FALSE;
2798
2799 wpa_s->conf->fast_reauth = fast_reauth;
2800 return TRUE;
2801 }
2802
2803
2804 /**
2805 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2806 * @iter: Pointer to incoming dbus message iter
2807 * @error: Location to store error on failure
2808 * @user_data: Function specific data
2809 * Returns: TRUE on success, FALSE on failure
2810 *
2811 * Getter for "DisconnectReason" property. The reason is negative if it is
2812 * locally generated.
2813 */
wpas_dbus_getter_disconnect_reason(DBusMessageIter * iter,DBusError * error,void * user_data)2814 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2815 DBusError *error,
2816 void *user_data)
2817 {
2818 struct wpa_supplicant *wpa_s = user_data;
2819 dbus_int32_t reason = wpa_s->disconnect_reason;
2820 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2821 &reason, error);
2822 }
2823
2824
2825 /**
2826 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2827 * @iter: Pointer to incoming dbus message iter
2828 * @error: Location to store error on failure
2829 * @user_data: Function specific data
2830 * Returns: TRUE on success, FALSE on failure
2831 *
2832 * Getter function for "BSSExpireAge" property.
2833 */
wpas_dbus_getter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2834 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2835 DBusError *error,
2836 void *user_data)
2837 {
2838 struct wpa_supplicant *wpa_s = user_data;
2839 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2840
2841 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2842 &expire_age, error);
2843 }
2844
2845
2846 /**
2847 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2848 * @iter: Pointer to incoming dbus message iter
2849 * @error: Location to store error on failure
2850 * @user_data: Function specific data
2851 * Returns: TRUE on success, FALSE on failure
2852 *
2853 * Setter function for "BSSExpireAge" property.
2854 */
wpas_dbus_setter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2855 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2856 DBusError *error,
2857 void *user_data)
2858 {
2859 struct wpa_supplicant *wpa_s = user_data;
2860 dbus_uint32_t expire_age;
2861
2862 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2863 &expire_age))
2864 return FALSE;
2865
2866 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2867 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2868 "BSSExpireAge must be >= 10");
2869 return FALSE;
2870 }
2871 return TRUE;
2872 }
2873
2874
2875 /**
2876 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2877 * @iter: Pointer to incoming dbus message iter
2878 * @error: Location to store error on failure
2879 * @user_data: Function specific data
2880 * Returns: TRUE on success, FALSE on failure
2881 *
2882 * Getter function for "BSSExpireCount" property.
2883 */
wpas_dbus_getter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2884 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2885 DBusError *error,
2886 void *user_data)
2887 {
2888 struct wpa_supplicant *wpa_s = user_data;
2889 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2890
2891 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2892 &expire_count, error);
2893 }
2894
2895
2896 /**
2897 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2898 * @iter: Pointer to incoming dbus message iter
2899 * @error: Location to store error on failure
2900 * @user_data: Function specific data
2901 * Returns: TRUE on success, FALSE on failure
2902 *
2903 * Setter function for "BSSExpireCount" property.
2904 */
wpas_dbus_setter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2905 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2906 DBusError *error,
2907 void *user_data)
2908 {
2909 struct wpa_supplicant *wpa_s = user_data;
2910 dbus_uint32_t expire_count;
2911
2912 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2913 &expire_count))
2914 return FALSE;
2915
2916 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2917 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2918 "BSSExpireCount must be > 0");
2919 return FALSE;
2920 }
2921 return TRUE;
2922 }
2923
2924
2925 /**
2926 * wpas_dbus_getter_country - Control country code
2927 * @iter: Pointer to incoming dbus message iter
2928 * @error: Location to store error on failure
2929 * @user_data: Function specific data
2930 * Returns: TRUE on success, FALSE on failure
2931 *
2932 * Getter function for "Country" property.
2933 */
wpas_dbus_getter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2934 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2935 void *user_data)
2936 {
2937 struct wpa_supplicant *wpa_s = user_data;
2938 char country[3];
2939 char *str = country;
2940
2941 country[0] = wpa_s->conf->country[0];
2942 country[1] = wpa_s->conf->country[1];
2943 country[2] = '\0';
2944
2945 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2946 &str, error);
2947 }
2948
2949
2950 /**
2951 * wpas_dbus_setter_country - Control country code
2952 * @iter: Pointer to incoming dbus message iter
2953 * @error: Location to store error on failure
2954 * @user_data: Function specific data
2955 * Returns: TRUE on success, FALSE on failure
2956 *
2957 * Setter function for "Country" property.
2958 */
wpas_dbus_setter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2959 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2960 void *user_data)
2961 {
2962 struct wpa_supplicant *wpa_s = user_data;
2963 const char *country;
2964
2965 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2966 &country))
2967 return FALSE;
2968
2969 if (!country[0] || !country[1]) {
2970 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2971 "invalid country code");
2972 return FALSE;
2973 }
2974
2975 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2976 wpa_printf(MSG_DEBUG, "Failed to set country");
2977 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2978 "failed to set country code");
2979 return FALSE;
2980 }
2981
2982 wpa_s->conf->country[0] = country[0];
2983 wpa_s->conf->country[1] = country[1];
2984 return TRUE;
2985 }
2986
2987
2988 /**
2989 * wpas_dbus_getter_scan_interval - Get scan interval
2990 * @iter: Pointer to incoming dbus message iter
2991 * @error: Location to store error on failure
2992 * @user_data: Function specific data
2993 * Returns: TRUE on success, FALSE on failure
2994 *
2995 * Getter function for "ScanInterval" property.
2996 */
wpas_dbus_getter_scan_interval(DBusMessageIter * iter,DBusError * error,void * user_data)2997 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2998 DBusError *error,
2999 void *user_data)
3000 {
3001 struct wpa_supplicant *wpa_s = user_data;
3002 dbus_int32_t scan_interval = wpa_s->scan_interval;
3003
3004 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
3005 &scan_interval, error);
3006 }
3007
3008
3009 /**
3010 * wpas_dbus_setter_scan_interval - Control scan interval
3011 * @iter: Pointer to incoming dbus message iter
3012 * @error: Location to store error on failure
3013 * @user_data: Function specific data
3014 * Returns: TRUE on success, FALSE on failure
3015 *
3016 * Setter function for "ScanInterval" property.
3017 */
wpas_dbus_setter_scan_interval(DBusMessageIter * iter,DBusError * error,void * user_data)3018 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
3019 DBusError *error,
3020 void *user_data)
3021 {
3022 struct wpa_supplicant *wpa_s = user_data;
3023 dbus_int32_t scan_interval;
3024
3025 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
3026 &scan_interval))
3027 return FALSE;
3028
3029 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
3030 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3031 "scan_interval must be >= 0");
3032 return FALSE;
3033 }
3034 return TRUE;
3035 }
3036
3037
3038 /**
3039 * wpas_dbus_getter_ifname - Get interface name
3040 * @iter: Pointer to incoming dbus message iter
3041 * @error: Location to store error on failure
3042 * @user_data: Function specific data
3043 * Returns: TRUE on success, FALSE on failure
3044 *
3045 * Getter for "Ifname" property.
3046 */
wpas_dbus_getter_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)3047 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
3048 void *user_data)
3049 {
3050 struct wpa_supplicant *wpa_s = user_data;
3051 const char *ifname = wpa_s->ifname;
3052
3053 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3054 &ifname, error);
3055 }
3056
3057
3058 /**
3059 * wpas_dbus_getter_driver - Get interface name
3060 * @iter: Pointer to incoming dbus message iter
3061 * @error: Location to store error on failure
3062 * @user_data: Function specific data
3063 * Returns: TRUE on success, FALSE on failure
3064 *
3065 * Getter for "Driver" property.
3066 */
wpas_dbus_getter_driver(DBusMessageIter * iter,DBusError * error,void * user_data)3067 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
3068 void *user_data)
3069 {
3070 struct wpa_supplicant *wpa_s = user_data;
3071 const char *driver;
3072
3073 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
3074 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
3075 "wpa_s has no driver set");
3076 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
3077 __func__);
3078 return FALSE;
3079 }
3080
3081 driver = wpa_s->driver->name;
3082 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3083 &driver, error);
3084 }
3085
3086
3087 /**
3088 * wpas_dbus_getter_current_bss - Get current bss object path
3089 * @iter: Pointer to incoming dbus message iter
3090 * @error: Location to store error on failure
3091 * @user_data: Function specific data
3092 * Returns: TRUE on success, FALSE on failure
3093 *
3094 * Getter for "CurrentBSS" property.
3095 */
wpas_dbus_getter_current_bss(DBusMessageIter * iter,DBusError * error,void * user_data)3096 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3097 DBusError *error,
3098 void *user_data)
3099 {
3100 struct wpa_supplicant *wpa_s = user_data;
3101 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3102
3103 if (wpa_s->current_bss)
3104 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3105 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3106 wpa_s->dbus_new_path, wpa_s->current_bss->id);
3107 else
3108 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3109
3110 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3111 &bss_obj_path, error);
3112 }
3113
3114
3115 /**
3116 * wpas_dbus_getter_current_network - Get current network object path
3117 * @iter: Pointer to incoming dbus message iter
3118 * @error: Location to store error on failure
3119 * @user_data: Function specific data
3120 * Returns: TRUE on success, FALSE on failure
3121 *
3122 * Getter for "CurrentNetwork" property.
3123 */
wpas_dbus_getter_current_network(DBusMessageIter * iter,DBusError * error,void * user_data)3124 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3125 DBusError *error,
3126 void *user_data)
3127 {
3128 struct wpa_supplicant *wpa_s = user_data;
3129 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3130
3131 if (wpa_s->current_ssid)
3132 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3133 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3134 wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3135 else
3136 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3137
3138 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3139 &net_obj_path, error);
3140 }
3141
3142
3143 /**
3144 * wpas_dbus_getter_current_auth_mode - Get current authentication type
3145 * @iter: Pointer to incoming dbus message iter
3146 * @error: Location to store error on failure
3147 * @user_data: Function specific data
3148 * Returns: TRUE on success, FALSE on failure
3149 *
3150 * Getter for "CurrentAuthMode" property.
3151 */
wpas_dbus_getter_current_auth_mode(DBusMessageIter * iter,DBusError * error,void * user_data)3152 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3153 DBusError *error,
3154 void *user_data)
3155 {
3156 struct wpa_supplicant *wpa_s = user_data;
3157 const char *eap_mode;
3158 const char *auth_mode;
3159 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3160
3161 if (wpa_s->wpa_state != WPA_COMPLETED) {
3162 auth_mode = "INACTIVE";
3163 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3164 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3165 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3166 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3167 "EAP-%s", eap_mode);
3168 auth_mode = eap_mode_buf;
3169
3170 } else {
3171 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3172 wpa_s->current_ssid->proto);
3173 }
3174
3175 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3176 &auth_mode, error);
3177 }
3178
3179
3180 /**
3181 * wpas_dbus_getter_bridge_ifname - Get interface name
3182 * @iter: Pointer to incoming dbus message iter
3183 * @error: Location to store error on failure
3184 * @user_data: Function specific data
3185 * Returns: TRUE on success, FALSE on failure
3186 *
3187 * Getter for "BridgeIfname" property.
3188 */
wpas_dbus_getter_bridge_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)3189 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3190 DBusError *error,
3191 void *user_data)
3192 {
3193 struct wpa_supplicant *wpa_s = user_data;
3194 const char *bridge_ifname = wpa_s->bridge_ifname;
3195 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3196 &bridge_ifname, error);
3197 }
3198
3199
3200 /**
3201 * wpas_dbus_getter_bsss - Get array of BSSs objects
3202 * @iter: Pointer to incoming dbus message iter
3203 * @error: Location to store error on failure
3204 * @user_data: Function specific data
3205 * Returns: TRUE on success, FALSE on failure
3206 *
3207 * Getter for "BSSs" property.
3208 */
wpas_dbus_getter_bsss(DBusMessageIter * iter,DBusError * error,void * user_data)3209 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3210 void *user_data)
3211 {
3212 struct wpa_supplicant *wpa_s = user_data;
3213 struct wpa_bss *bss;
3214 char **paths;
3215 unsigned int i = 0;
3216 dbus_bool_t success = FALSE;
3217
3218 paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3219 if (!paths) {
3220 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3221 return FALSE;
3222 }
3223
3224 /* Loop through scan results and append each result's object path */
3225 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3226 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3227 if (paths[i] == NULL) {
3228 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3229 "no memory");
3230 goto out;
3231 }
3232 /* Construct the object path for this BSS. */
3233 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3234 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3235 wpa_s->dbus_new_path, bss->id);
3236 }
3237
3238 success = wpas_dbus_simple_array_property_getter(iter,
3239 DBUS_TYPE_OBJECT_PATH,
3240 paths, wpa_s->num_bss,
3241 error);
3242
3243 out:
3244 while (i)
3245 os_free(paths[--i]);
3246 os_free(paths);
3247 return success;
3248 }
3249
3250
3251 /**
3252 * wpas_dbus_getter_networks - Get array of networks objects
3253 * @iter: Pointer to incoming dbus message iter
3254 * @error: Location to store error on failure
3255 * @user_data: Function specific data
3256 * Returns: TRUE on success, FALSE on failure
3257 *
3258 * Getter for "Networks" property.
3259 */
wpas_dbus_getter_networks(DBusMessageIter * iter,DBusError * error,void * user_data)3260 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3261 void *user_data)
3262 {
3263 struct wpa_supplicant *wpa_s = user_data;
3264 struct wpa_ssid *ssid;
3265 char **paths;
3266 unsigned int i = 0, num = 0;
3267 dbus_bool_t success = FALSE;
3268
3269 if (wpa_s->conf == NULL) {
3270 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
3271 "networks list.", __func__);
3272 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
3273 "occurred getting the networks list", __func__);
3274 return FALSE;
3275 }
3276
3277 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3278 if (!network_is_persistent_group(ssid))
3279 num++;
3280
3281 paths = os_calloc(num, sizeof(char *));
3282 if (!paths) {
3283 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3284 return FALSE;
3285 }
3286
3287 /* Loop through configured networks and append object path of each */
3288 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3289 if (network_is_persistent_group(ssid))
3290 continue;
3291 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3292 if (paths[i] == NULL) {
3293 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3294 goto out;
3295 }
3296
3297 /* Construct the object path for this network. */
3298 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3299 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3300 wpa_s->dbus_new_path, ssid->id);
3301 }
3302
3303 success = wpas_dbus_simple_array_property_getter(iter,
3304 DBUS_TYPE_OBJECT_PATH,
3305 paths, num, error);
3306
3307 out:
3308 while (i)
3309 os_free(paths[--i]);
3310 os_free(paths);
3311 return success;
3312 }
3313
3314
3315 /**
3316 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3317 * @iter: Pointer to incoming dbus message iter
3318 * @error: Location to store error on failure
3319 * @user_data: Function specific data
3320 * Returns: A dbus message containing the PKCS #11 engine path
3321 *
3322 * Getter for "PKCS11EnginePath" property.
3323 */
wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter * iter,DBusError * error,void * user_data)3324 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3325 DBusError *error,
3326 void *user_data)
3327 {
3328 struct wpa_supplicant *wpa_s = user_data;
3329 const char *pkcs11_engine_path;
3330
3331 if (wpa_s->conf == NULL) {
3332 wpa_printf(MSG_ERROR,
3333 "wpas_dbus_getter_pkcs11_engine_path[dbus]: An "
3334 "error occurred getting the PKCS #11 engine path.");
3335 dbus_set_error_const(
3336 error, DBUS_ERROR_FAILED,
3337 "An error occured getting the PKCS #11 engine path.");
3338 return FALSE;
3339 }
3340
3341 if (wpa_s->conf->pkcs11_engine_path == NULL)
3342 pkcs11_engine_path = "";
3343 else
3344 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3345 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3346 &pkcs11_engine_path, error);
3347 }
3348
3349
3350 /**
3351 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3352 * @iter: Pointer to incoming dbus message iter
3353 * @error: Location to store error on failure
3354 * @user_data: Function specific data
3355 * Returns: A dbus message containing the PKCS #11 module path
3356 *
3357 * Getter for "PKCS11ModulePath" property.
3358 */
wpas_dbus_getter_pkcs11_module_path(DBusMessageIter * iter,DBusError * error,void * user_data)3359 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3360 DBusError *error,
3361 void *user_data)
3362 {
3363 struct wpa_supplicant *wpa_s = user_data;
3364 const char *pkcs11_module_path;
3365
3366 if (wpa_s->conf == NULL) {
3367 wpa_printf(MSG_ERROR,
3368 "wpas_dbus_getter_pkcs11_module_path[dbus]: An "
3369 "error occurred getting the PKCS #11 module path.");
3370 dbus_set_error_const(
3371 error, DBUS_ERROR_FAILED,
3372 "An error occured getting the PKCS #11 module path.");
3373 return FALSE;
3374 }
3375
3376 if (wpa_s->conf->pkcs11_module_path == NULL)
3377 pkcs11_module_path = "";
3378 else
3379 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3380 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3381 &pkcs11_module_path, error);
3382 }
3383
3384
3385 /**
3386 * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3387 * @iter: Pointer to incoming dbus message iter
3388 * @error: Location to store error on failure
3389 * @user_data: Function specific data
3390 * Returns: TRUE on success, FALSE on failure
3391 *
3392 * Getter for "Blobs" property.
3393 */
wpas_dbus_getter_blobs(DBusMessageIter * iter,DBusError * error,void * user_data)3394 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3395 void *user_data)
3396 {
3397 struct wpa_supplicant *wpa_s = user_data;
3398 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3399 struct wpa_config_blob *blob;
3400
3401 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3402 "a{say}", &variant_iter) ||
3403 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3404 "{say}", &dict_iter)) {
3405 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3406 return FALSE;
3407 }
3408
3409 blob = wpa_s->conf->blobs;
3410 while (blob) {
3411 if (!dbus_message_iter_open_container(&dict_iter,
3412 DBUS_TYPE_DICT_ENTRY,
3413 NULL, &entry_iter) ||
3414 !dbus_message_iter_append_basic(&entry_iter,
3415 DBUS_TYPE_STRING,
3416 &(blob->name)) ||
3417 !dbus_message_iter_open_container(&entry_iter,
3418 DBUS_TYPE_ARRAY,
3419 DBUS_TYPE_BYTE_AS_STRING,
3420 &array_iter) ||
3421 !dbus_message_iter_append_fixed_array(&array_iter,
3422 DBUS_TYPE_BYTE,
3423 &(blob->data),
3424 blob->len) ||
3425 !dbus_message_iter_close_container(&entry_iter,
3426 &array_iter) ||
3427 !dbus_message_iter_close_container(&dict_iter,
3428 &entry_iter)) {
3429 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3430 "no memory");
3431 return FALSE;
3432 }
3433
3434 blob = blob->next;
3435 }
3436
3437 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3438 !dbus_message_iter_close_container(iter, &variant_iter)) {
3439 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3440 return FALSE;
3441 }
3442
3443 return TRUE;
3444 }
3445
3446
get_bss_helper(struct bss_handler_args * args,DBusError * error,const char * func_name)3447 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3448 DBusError *error, const char *func_name)
3449 {
3450 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3451
3452 if (!res) {
3453 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3454 func_name, args->id);
3455 dbus_set_error(error, DBUS_ERROR_FAILED,
3456 "%s: BSS %d not found",
3457 func_name, args->id);
3458 }
3459
3460 return res;
3461 }
3462
3463
3464 /**
3465 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3466 * @iter: Pointer to incoming dbus message iter
3467 * @error: Location to store error on failure
3468 * @user_data: Function specific data
3469 * Returns: TRUE on success, FALSE on failure
3470 *
3471 * Getter for "BSSID" property.
3472 */
wpas_dbus_getter_bss_bssid(DBusMessageIter * iter,DBusError * error,void * user_data)3473 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3474 void *user_data)
3475 {
3476 struct bss_handler_args *args = user_data;
3477 struct wpa_bss *res;
3478
3479 res = get_bss_helper(args, error, __func__);
3480 if (!res)
3481 return FALSE;
3482
3483 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3484 res->bssid, ETH_ALEN,
3485 error);
3486 }
3487
3488
3489 /**
3490 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3491 * @iter: Pointer to incoming dbus message iter
3492 * @error: Location to store error on failure
3493 * @user_data: Function specific data
3494 * Returns: TRUE on success, FALSE on failure
3495 *
3496 * Getter for "SSID" property.
3497 */
wpas_dbus_getter_bss_ssid(DBusMessageIter * iter,DBusError * error,void * user_data)3498 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3499 void *user_data)
3500 {
3501 struct bss_handler_args *args = user_data;
3502 struct wpa_bss *res;
3503
3504 res = get_bss_helper(args, error, __func__);
3505 if (!res)
3506 return FALSE;
3507
3508 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3509 res->ssid, res->ssid_len,
3510 error);
3511 }
3512
3513
3514 /**
3515 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3516 * @iter: Pointer to incoming dbus message iter
3517 * @error: Location to store error on failure
3518 * @user_data: Function specific data
3519 * Returns: TRUE on success, FALSE on failure
3520 *
3521 * Getter for "Privacy" property.
3522 */
wpas_dbus_getter_bss_privacy(DBusMessageIter * iter,DBusError * error,void * user_data)3523 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3524 DBusError *error, void *user_data)
3525 {
3526 struct bss_handler_args *args = user_data;
3527 struct wpa_bss *res;
3528 dbus_bool_t privacy;
3529
3530 res = get_bss_helper(args, error, __func__);
3531 if (!res)
3532 return FALSE;
3533
3534 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3535 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3536 &privacy, error);
3537 }
3538
3539
3540 /**
3541 * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3542 * @iter: Pointer to incoming dbus message iter
3543 * @error: Location to store error on failure
3544 * @user_data: Function specific data
3545 * Returns: TRUE on success, FALSE on failure
3546 *
3547 * Getter for "Mode" property.
3548 */
wpas_dbus_getter_bss_mode(DBusMessageIter * iter,DBusError * error,void * user_data)3549 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3550 void *user_data)
3551 {
3552 struct bss_handler_args *args = user_data;
3553 struct wpa_bss *res;
3554 const char *mode;
3555
3556 res = get_bss_helper(args, error, __func__);
3557 if (!res)
3558 return FALSE;
3559 if (bss_is_dmg(res)) {
3560 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3561 case IEEE80211_CAP_DMG_PBSS:
3562 case IEEE80211_CAP_DMG_IBSS:
3563 mode = "ad-hoc";
3564 break;
3565 case IEEE80211_CAP_DMG_AP:
3566 mode = "infrastructure";
3567 break;
3568 }
3569 } else {
3570 if (res->caps & IEEE80211_CAP_IBSS)
3571 mode = "ad-hoc";
3572 else
3573 mode = "infrastructure";
3574 }
3575
3576 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3577 &mode, error);
3578 }
3579
3580
3581 /**
3582 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3583 * @iter: Pointer to incoming dbus message iter
3584 * @error: Location to store error on failure
3585 * @user_data: Function specific data
3586 * Returns: TRUE on success, FALSE on failure
3587 *
3588 * Getter for "Level" property.
3589 */
wpas_dbus_getter_bss_signal(DBusMessageIter * iter,DBusError * error,void * user_data)3590 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3591 DBusError *error, void *user_data)
3592 {
3593 struct bss_handler_args *args = user_data;
3594 struct wpa_bss *res;
3595 s16 level;
3596
3597 res = get_bss_helper(args, error, __func__);
3598 if (!res)
3599 return FALSE;
3600
3601 level = (s16) res->level;
3602 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3603 &level, error);
3604 }
3605
3606
3607 /**
3608 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3609 * @iter: Pointer to incoming dbus message iter
3610 * @error: Location to store error on failure
3611 * @user_data: Function specific data
3612 * Returns: TRUE on success, FALSE on failure
3613 *
3614 * Getter for "Frequency" property.
3615 */
wpas_dbus_getter_bss_frequency(DBusMessageIter * iter,DBusError * error,void * user_data)3616 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3617 DBusError *error, void *user_data)
3618 {
3619 struct bss_handler_args *args = user_data;
3620 struct wpa_bss *res;
3621 u16 freq;
3622
3623 res = get_bss_helper(args, error, __func__);
3624 if (!res)
3625 return FALSE;
3626
3627 freq = (u16) res->freq;
3628 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3629 &freq, error);
3630 }
3631
3632
cmp_u8s_desc(const void * a,const void * b)3633 static int cmp_u8s_desc(const void *a, const void *b)
3634 {
3635 return (*(u8 *) b - *(u8 *) a);
3636 }
3637
3638
3639 /**
3640 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3641 * @iter: Pointer to incoming dbus message iter
3642 * @error: Location to store error on failure
3643 * @user_data: Function specific data
3644 * Returns: TRUE on success, FALSE on failure
3645 *
3646 * Getter for "Rates" property.
3647 */
wpas_dbus_getter_bss_rates(DBusMessageIter * iter,DBusError * error,void * user_data)3648 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3649 DBusError *error, void *user_data)
3650 {
3651 struct bss_handler_args *args = user_data;
3652 struct wpa_bss *res;
3653 u8 *ie_rates = NULL;
3654 u32 *real_rates;
3655 int rates_num, i;
3656 dbus_bool_t success = FALSE;
3657
3658 res = get_bss_helper(args, error, __func__);
3659 if (!res)
3660 return FALSE;
3661
3662 rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3663 if (rates_num < 0)
3664 return FALSE;
3665
3666 qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3667
3668 real_rates = os_malloc(sizeof(u32) * rates_num);
3669 if (!real_rates) {
3670 os_free(ie_rates);
3671 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3672 return FALSE;
3673 }
3674
3675 for (i = 0; i < rates_num; i++)
3676 real_rates[i] = ie_rates[i] * 500000;
3677
3678 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3679 real_rates, rates_num,
3680 error);
3681
3682 os_free(ie_rates);
3683 os_free(real_rates);
3684 return success;
3685 }
3686
3687
wpas_dbus_get_bss_security_prop(DBusMessageIter * iter,struct wpa_ie_data * ie_data,DBusError * error)3688 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3689 struct wpa_ie_data *ie_data,
3690 DBusError *error)
3691 {
3692 DBusMessageIter iter_dict, variant_iter;
3693 const char *group;
3694 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3695 const char *key_mgmt[7]; /* max 7 key managements may be supported */
3696 int n;
3697
3698 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3699 "a{sv}", &variant_iter))
3700 goto nomem;
3701
3702 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3703 goto nomem;
3704
3705 /* KeyMgmt */
3706 n = 0;
3707 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3708 key_mgmt[n++] = "wpa-psk";
3709 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3710 key_mgmt[n++] = "wpa-ft-psk";
3711 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3712 key_mgmt[n++] = "wpa-psk-sha256";
3713 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3714 key_mgmt[n++] = "wpa-eap";
3715 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3716 key_mgmt[n++] = "wpa-ft-eap";
3717 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3718 key_mgmt[n++] = "wpa-eap-sha256";
3719 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3720 key_mgmt[n++] = "wpa-none";
3721
3722 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3723 key_mgmt, n))
3724 goto nomem;
3725
3726 /* Group */
3727 switch (ie_data->group_cipher) {
3728 case WPA_CIPHER_WEP40:
3729 group = "wep40";
3730 break;
3731 case WPA_CIPHER_TKIP:
3732 group = "tkip";
3733 break;
3734 case WPA_CIPHER_CCMP:
3735 group = "ccmp";
3736 break;
3737 case WPA_CIPHER_GCMP:
3738 group = "gcmp";
3739 break;
3740 case WPA_CIPHER_WEP104:
3741 group = "wep104";
3742 break;
3743 case WPA_CIPHER_CCMP_256:
3744 group = "ccmp-256";
3745 break;
3746 case WPA_CIPHER_GCMP_256:
3747 group = "gcmp-256";
3748 break;
3749 default:
3750 group = "";
3751 break;
3752 }
3753
3754 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3755 goto nomem;
3756
3757 /* Pairwise */
3758 n = 0;
3759 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3760 pairwise[n++] = "tkip";
3761 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3762 pairwise[n++] = "ccmp";
3763 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3764 pairwise[n++] = "gcmp";
3765 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3766 pairwise[n++] = "ccmp-256";
3767 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3768 pairwise[n++] = "gcmp-256";
3769
3770 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3771 pairwise, n))
3772 goto nomem;
3773
3774 /* Management group (RSN only) */
3775 if (ie_data->proto == WPA_PROTO_RSN) {
3776 switch (ie_data->mgmt_group_cipher) {
3777 #ifdef CONFIG_IEEE80211W
3778 case WPA_CIPHER_AES_128_CMAC:
3779 group = "aes128cmac";
3780 break;
3781 #endif /* CONFIG_IEEE80211W */
3782 default:
3783 group = "";
3784 break;
3785 }
3786
3787 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3788 group))
3789 goto nomem;
3790 }
3791
3792 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3793 goto nomem;
3794 if (!dbus_message_iter_close_container(iter, &variant_iter))
3795 goto nomem;
3796
3797 return TRUE;
3798
3799 nomem:
3800 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3801 return FALSE;
3802 }
3803
3804
3805 /**
3806 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3807 * @iter: Pointer to incoming dbus message iter
3808 * @error: Location to store error on failure
3809 * @user_data: Function specific data
3810 * Returns: TRUE on success, FALSE on failure
3811 *
3812 * Getter for "WPA" property.
3813 */
wpas_dbus_getter_bss_wpa(DBusMessageIter * iter,DBusError * error,void * user_data)3814 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3815 void *user_data)
3816 {
3817 struct bss_handler_args *args = user_data;
3818 struct wpa_bss *res;
3819 struct wpa_ie_data wpa_data;
3820 const u8 *ie;
3821
3822 res = get_bss_helper(args, error, __func__);
3823 if (!res)
3824 return FALSE;
3825
3826 os_memset(&wpa_data, 0, sizeof(wpa_data));
3827 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3828 if (ie) {
3829 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3830 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3831 "failed to parse WPA IE");
3832 return FALSE;
3833 }
3834 }
3835
3836 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3837 }
3838
3839
3840 /**
3841 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3842 * @iter: Pointer to incoming dbus message iter
3843 * @error: Location to store error on failure
3844 * @user_data: Function specific data
3845 * Returns: TRUE on success, FALSE on failure
3846 *
3847 * Getter for "RSN" property.
3848 */
wpas_dbus_getter_bss_rsn(DBusMessageIter * iter,DBusError * error,void * user_data)3849 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3850 void *user_data)
3851 {
3852 struct bss_handler_args *args = user_data;
3853 struct wpa_bss *res;
3854 struct wpa_ie_data wpa_data;
3855 const u8 *ie;
3856
3857 res = get_bss_helper(args, error, __func__);
3858 if (!res)
3859 return FALSE;
3860
3861 os_memset(&wpa_data, 0, sizeof(wpa_data));
3862 ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3863 if (ie) {
3864 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3865 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3866 "failed to parse RSN IE");
3867 return FALSE;
3868 }
3869 }
3870
3871 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3872 }
3873
3874
3875 /**
3876 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3877 * @iter: Pointer to incoming dbus message iter
3878 * @error: Location to store error on failure
3879 * @user_data: Function specific data
3880 * Returns: TRUE on success, FALSE on failure
3881 *
3882 * Getter for "WPS" property.
3883 */
wpas_dbus_getter_bss_wps(DBusMessageIter * iter,DBusError * error,void * user_data)3884 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3885 void *user_data)
3886 {
3887 struct bss_handler_args *args = user_data;
3888 struct wpa_bss *res;
3889 #ifdef CONFIG_WPS
3890 struct wpabuf *wps_ie;
3891 #endif /* CONFIG_WPS */
3892 DBusMessageIter iter_dict, variant_iter;
3893 const char *type = "";
3894
3895 res = get_bss_helper(args, error, __func__);
3896 if (!res)
3897 return FALSE;
3898
3899 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3900 "a{sv}", &variant_iter))
3901 goto nomem;
3902
3903 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3904 goto nomem;
3905
3906 #ifdef CONFIG_WPS
3907 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3908 if (wps_ie) {
3909 if (wps_is_selected_pbc_registrar(wps_ie))
3910 type = "pbc";
3911 else if (wps_is_selected_pin_registrar(wps_ie))
3912 type = "pin";
3913 }
3914 #endif /* CONFIG_WPS */
3915
3916 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type))
3917 goto nomem;
3918
3919 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3920 goto nomem;
3921 if (!dbus_message_iter_close_container(iter, &variant_iter))
3922 goto nomem;
3923
3924 return TRUE;
3925
3926 nomem:
3927 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3928 return FALSE;
3929 }
3930
3931
3932 /**
3933 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3934 * @iter: Pointer to incoming dbus message iter
3935 * @error: Location to store error on failure
3936 * @user_data: Function specific data
3937 * Returns: TRUE on success, FALSE on failure
3938 *
3939 * Getter for "IEs" property.
3940 */
wpas_dbus_getter_bss_ies(DBusMessageIter * iter,DBusError * error,void * user_data)3941 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3942 void *user_data)
3943 {
3944 struct bss_handler_args *args = user_data;
3945 struct wpa_bss *res;
3946
3947 res = get_bss_helper(args, error, __func__);
3948 if (!res)
3949 return FALSE;
3950
3951 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3952 res + 1, res->ie_len,
3953 error);
3954 }
3955
3956
3957 /**
3958 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3959 * @iter: Pointer to incoming dbus message iter
3960 * @error: Location to store error on failure
3961 * @user_data: Function specific data
3962 * Returns: TRUE on success, FALSE on failure
3963 *
3964 * Getter for "enabled" property of a configured network.
3965 */
wpas_dbus_getter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3966 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3967 void *user_data)
3968 {
3969 struct network_handler_args *net = user_data;
3970 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3971
3972 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3973 &enabled, error);
3974 }
3975
3976
3977 /**
3978 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3979 * @iter: Pointer to incoming dbus message iter
3980 * @error: Location to store error on failure
3981 * @user_data: Function specific data
3982 * Returns: TRUE on success, FALSE on failure
3983 *
3984 * Setter for "Enabled" property of a configured network.
3985 */
wpas_dbus_setter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3986 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3987 void *user_data)
3988 {
3989 struct network_handler_args *net = user_data;
3990 struct wpa_supplicant *wpa_s;
3991 struct wpa_ssid *ssid;
3992 dbus_bool_t enable;
3993
3994 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3995 &enable))
3996 return FALSE;
3997
3998 wpa_s = net->wpa_s;
3999 ssid = net->ssid;
4000
4001 if (enable)
4002 wpa_supplicant_enable_network(wpa_s, ssid);
4003 else
4004 wpa_supplicant_disable_network(wpa_s, ssid);
4005
4006 return TRUE;
4007 }
4008
4009
4010 /**
4011 * wpas_dbus_getter_network_properties - Get options for a configured network
4012 * @iter: Pointer to incoming dbus message iter
4013 * @error: Location to store error on failure
4014 * @user_data: Function specific data
4015 * Returns: TRUE on success, FALSE on failure
4016 *
4017 * Getter for "Properties" property of a configured network.
4018 */
wpas_dbus_getter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)4019 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
4020 DBusError *error,
4021 void *user_data)
4022 {
4023 struct network_handler_args *net = user_data;
4024 DBusMessageIter variant_iter, dict_iter;
4025 char **iterator;
4026 char **props = wpa_config_get_all(net->ssid, 1);
4027 dbus_bool_t success = FALSE;
4028
4029 if (!props) {
4030 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4031 return FALSE;
4032 }
4033
4034 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
4035 &variant_iter) ||
4036 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
4037 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4038 goto out;
4039 }
4040
4041 iterator = props;
4042 while (*iterator) {
4043 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
4044 *(iterator + 1))) {
4045 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
4046 "no memory");
4047 goto out;
4048 }
4049 iterator += 2;
4050 }
4051
4052
4053 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
4054 !dbus_message_iter_close_container(iter, &variant_iter)) {
4055 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
4056 goto out;
4057 }
4058
4059 success = TRUE;
4060
4061 out:
4062 iterator = props;
4063 while (*iterator) {
4064 os_free(*iterator);
4065 iterator++;
4066 }
4067 os_free(props);
4068 return success;
4069 }
4070
4071
4072 /**
4073 * wpas_dbus_setter_network_properties - Set options for a configured network
4074 * @iter: Pointer to incoming dbus message iter
4075 * @error: Location to store error on failure
4076 * @user_data: Function specific data
4077 * Returns: TRUE on success, FALSE on failure
4078 *
4079 * Setter for "Properties" property of a configured network.
4080 */
wpas_dbus_setter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)4081 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
4082 DBusError *error,
4083 void *user_data)
4084 {
4085 struct network_handler_args *net = user_data;
4086 struct wpa_ssid *ssid = net->ssid;
4087 DBusMessageIter variant_iter;
4088
4089 dbus_message_iter_recurse(iter, &variant_iter);
4090 return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
4091 }
4092
4093
4094 #ifdef CONFIG_AP
4095
wpas_dbus_handler_subscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)4096 DBusMessage * wpas_dbus_handler_subscribe_preq(
4097 DBusMessage *message, struct wpa_supplicant *wpa_s)
4098 {
4099 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4100 char *name;
4101
4102 if (wpa_s->preq_notify_peer != NULL) {
4103 if (os_strcmp(dbus_message_get_sender(message),
4104 wpa_s->preq_notify_peer) == 0)
4105 return NULL;
4106
4107 return dbus_message_new_error(message,
4108 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4109 "Another application is already subscribed");
4110 }
4111
4112 name = os_strdup(dbus_message_get_sender(message));
4113 if (!name)
4114 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
4115 "out of memory");
4116
4117 wpa_s->preq_notify_peer = name;
4118
4119 /* Subscribe to clean up if application closes socket */
4120 wpas_dbus_subscribe_noc(priv);
4121
4122 /*
4123 * Double-check it's still alive to make sure that we didn't
4124 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4125 */
4126 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4127 /*
4128 * Application no longer exists, clean up.
4129 * The return value is irrelevant now.
4130 *
4131 * Need to check if the NameOwnerChanged handling
4132 * already cleaned up because we have processed
4133 * DBus messages while checking if the name still
4134 * has an owner.
4135 */
4136 if (!wpa_s->preq_notify_peer)
4137 return NULL;
4138 os_free(wpa_s->preq_notify_peer);
4139 wpa_s->preq_notify_peer = NULL;
4140 wpas_dbus_unsubscribe_noc(priv);
4141 }
4142
4143 return NULL;
4144 }
4145
4146
wpas_dbus_handler_unsubscribe_preq(DBusMessage * message,struct wpa_supplicant * wpa_s)4147 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4148 DBusMessage *message, struct wpa_supplicant *wpa_s)
4149 {
4150 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4151
4152 if (!wpa_s->preq_notify_peer)
4153 return dbus_message_new_error(message,
4154 WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4155 "Not subscribed");
4156
4157 if (os_strcmp(wpa_s->preq_notify_peer,
4158 dbus_message_get_sender(message)))
4159 return dbus_message_new_error(message,
4160 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4161 "Can't unsubscribe others");
4162
4163 os_free(wpa_s->preq_notify_peer);
4164 wpa_s->preq_notify_peer = NULL;
4165 wpas_dbus_unsubscribe_noc(priv);
4166 return NULL;
4167 }
4168
4169
wpas_dbus_signal_preq(struct wpa_supplicant * wpa_s,const u8 * addr,const u8 * dst,const u8 * bssid,const u8 * ie,size_t ie_len,u32 ssi_signal)4170 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4171 const u8 *addr, const u8 *dst, const u8 *bssid,
4172 const u8 *ie, size_t ie_len, u32 ssi_signal)
4173 {
4174 DBusMessage *msg;
4175 DBusMessageIter iter, dict_iter;
4176 struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4177
4178 /* Do nothing if the control interface is not turned on */
4179 if (priv == NULL)
4180 return;
4181
4182 if (wpa_s->preq_notify_peer == NULL)
4183 return;
4184
4185 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4186 WPAS_DBUS_NEW_IFACE_INTERFACE,
4187 "ProbeRequest");
4188 if (msg == NULL)
4189 return;
4190
4191 dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4192
4193 dbus_message_iter_init_append(msg, &iter);
4194
4195 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
4196 goto fail;
4197 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4198 (const char *) addr,
4199 ETH_ALEN))
4200 goto fail;
4201 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4202 (const char *) dst,
4203 ETH_ALEN))
4204 goto fail;
4205 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4206 (const char *) bssid,
4207 ETH_ALEN))
4208 goto fail;
4209 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4210 (const char *) ie,
4211 ie_len))
4212 goto fail;
4213 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4214 ssi_signal))
4215 goto fail;
4216 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
4217 goto fail;
4218
4219 dbus_connection_send(priv->con, msg, NULL);
4220 goto out;
4221 fail:
4222 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4223 out:
4224 dbus_message_unref(msg);
4225 }
4226
4227 #endif /* CONFIG_AP */
4228