• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16 
17 #include "includes.h"
18 
19 #include "common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "eap_peer/eap_methods.h"
22 #include "eapol_supp/eapol_supp_sm.h"
23 #include "rsn_supp/wpa.h"
24 #include "../config.h"
25 #include "../wpa_supplicant_i.h"
26 #include "../driver_i.h"
27 #include "../notify.h"
28 #include "../bss.h"
29 #include "../scan.h"
30 #include "../ctrl_iface.h"
31 #include "dbus_new_helpers.h"
32 #include "dbus_new.h"
33 #include "dbus_new_handlers.h"
34 #include "dbus_dict_helpers.h"
35 
36 extern int wpa_debug_level;
37 extern int wpa_debug_show_keys;
38 extern int wpa_debug_timestamp;
39 
40 static const char *debug_strings[] = {
41 	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
42 };
43 
44 
45 /**
46  * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
47  * @message: Pointer to incoming dbus message this error refers to
48  * @arg: Optional string appended to error message
49  * Returns: a dbus error message
50  *
51  * Convenience function to create and return an UnknownError
52  */
wpas_dbus_error_unknown_error(DBusMessage * message,const char * arg)53 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
54 					    const char *arg)
55 {
56 	/*
57 	 * This function can be called as a result of a failure
58 	 * within internal getter calls, which will call this function
59 	 * with a NULL message parameter.  However, dbus_message_new_error
60 	 * looks very unkindly (i.e, abort()) on a NULL message, so
61 	 * in this case, we should not call it.
62 	 */
63 	if (message == NULL) {
64 		wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
65 			   "called with NULL message (arg=%s)",
66 			   arg ? arg : "N/A");
67 		return NULL;
68 	}
69 
70 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
71 				      arg);
72 }
73 
74 
75 /**
76  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
77  * @message: Pointer to incoming dbus message this error refers to
78  * Returns: A dbus error message
79  *
80  * Convenience function to create and return an invalid interface error
81  */
wpas_dbus_error_iface_unknown(DBusMessage * message)82 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
83 {
84 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
85 				      "wpa_supplicant knows nothing about "
86 				      "this interface.");
87 }
88 
89 
90 /**
91  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
92  * @message: Pointer to incoming dbus message this error refers to
93  * Returns: a dbus error message
94  *
95  * Convenience function to create and return an invalid network error
96  */
wpas_dbus_error_network_unknown(DBusMessage * message)97 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
98 {
99 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
100 				      "There is no such a network in this "
101 				      "interface.");
102 }
103 
104 
105 /**
106  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
107  * @message: Pointer to incoming dbus message this error refers to
108  * Returns: a dbus error message
109  *
110  * Convenience function to create and return an invalid options error
111  */
wpas_dbus_error_invalid_args(DBusMessage * message,const char * arg)112 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
113 					  const char *arg)
114 {
115 	DBusMessage *reply;
116 
117 	reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
118 				       "Did not receive correct message "
119 				       "arguments.");
120 	if (arg != NULL)
121 		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
122 					 DBUS_TYPE_INVALID);
123 
124 	return reply;
125 }
126 
127 
128 static const char *dont_quote[] = {
129 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
130 	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
131 	"bssid", NULL
132 };
133 
should_quote_opt(const char * key)134 static dbus_bool_t should_quote_opt(const char *key)
135 {
136 	int i = 0;
137 	while (dont_quote[i] != NULL) {
138 		if (os_strcmp(key, dont_quote[i]) == 0)
139 			return FALSE;
140 		i++;
141 	}
142 	return TRUE;
143 }
144 
145 /**
146  * get_iface_by_dbus_path - Get a new network interface
147  * @global: Pointer to global data from wpa_supplicant_init()
148  * @path: Pointer to a dbus object path representing an interface
149  * Returns: Pointer to the interface or %NULL if not found
150  */
get_iface_by_dbus_path(struct wpa_global * global,const char * path)151 static struct wpa_supplicant * get_iface_by_dbus_path(
152 	struct wpa_global *global, const char *path)
153 {
154 	struct wpa_supplicant *wpa_s;
155 
156 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
157 		if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
158 			return wpa_s;
159 	}
160 	return NULL;
161 }
162 
163 
164 /**
165  * set_network_properties - Set properties of a configured network
166  * @wpa_s: wpa_supplicant structure for a network interface
167  * @ssid: wpa_ssid structure for a configured network
168  * @iter: DBus message iterator containing dictionary of network
169  * properties to set.
170  * @error: On failure, an error describing the failure
171  * Returns: TRUE if the request succeeds, FALSE if it failed
172  *
173  * Sets network configuration with parameters given id DBus dictionary
174  */
set_network_properties(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,DBusMessageIter * iter,DBusError * error)175 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
176 				   struct wpa_ssid *ssid,
177 				   DBusMessageIter *iter,
178 				   DBusError *error)
179 {
180 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
181 	DBusMessageIter	iter_dict;
182 	char *value = NULL;
183 
184 	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
185 		return FALSE;
186 
187 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
188 		size_t size = 50;
189 		int ret;
190 
191 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
192 			goto error;
193 
194 		value = NULL;
195 		if (entry.type == DBUS_TYPE_ARRAY &&
196 		    entry.array_type == DBUS_TYPE_BYTE) {
197 			if (entry.array_len <= 0)
198 				goto error;
199 
200 			size = entry.array_len * 2 + 1;
201 			value = os_zalloc(size);
202 			if (value == NULL)
203 				goto error;
204 
205 			ret = wpa_snprintf_hex(value, size,
206 					       (u8 *) entry.bytearray_value,
207 					       entry.array_len);
208 			if (ret <= 0)
209 				goto error;
210 		} else if (entry.type == DBUS_TYPE_STRING) {
211 			if (should_quote_opt(entry.key)) {
212 				size = os_strlen(entry.str_value);
213 				if (size <= 0)
214 					goto error;
215 
216 				size += 3;
217 				value = os_zalloc(size);
218 				if (value == NULL)
219 					goto error;
220 
221 				ret = os_snprintf(value, size, "\"%s\"",
222 						  entry.str_value);
223 				if (ret < 0 || (size_t) ret != (size - 1))
224 					goto error;
225 			} else {
226 				value = os_strdup(entry.str_value);
227 				if (value == NULL)
228 					goto error;
229 			}
230 		} else if (entry.type == DBUS_TYPE_UINT32) {
231 			value = os_zalloc(size);
232 			if (value == NULL)
233 				goto error;
234 
235 			ret = os_snprintf(value, size, "%u",
236 					  entry.uint32_value);
237 			if (ret <= 0)
238 				goto error;
239 		} else if (entry.type == DBUS_TYPE_INT32) {
240 			value = os_zalloc(size);
241 			if (value == NULL)
242 				goto error;
243 
244 			ret = os_snprintf(value, size, "%d",
245 					  entry.int32_value);
246 			if (ret <= 0)
247 				goto error;
248 		} else
249 			goto error;
250 
251 		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
252 			goto error;
253 
254 		if ((os_strcmp(entry.key, "psk") == 0 &&
255 		     value[0] == '"' && ssid->ssid_len) ||
256 		    (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
257 			wpa_config_update_psk(ssid);
258 		else if (os_strcmp(entry.key, "priority") == 0)
259 			wpa_config_update_prio_list(wpa_s->conf);
260 
261 		os_free(value);
262 		wpa_dbus_dict_entry_clear(&entry);
263 	}
264 
265 	return TRUE;
266 
267 error:
268 	os_free(value);
269 	wpa_dbus_dict_entry_clear(&entry);
270 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
271 			     "invalid message format");
272 	return FALSE;
273 }
274 
275 
276 /**
277  * wpas_dbus_simple_property_getter - Get basic type property
278  * @iter: Message iter to use when appending arguments
279  * @type: DBus type of property (must be basic type)
280  * @val: pointer to place holding property value
281  * @error: On failure an error describing the failure
282  * Returns: TRUE if the request was successful, FALSE if it failed
283  *
284  * Generic getter for basic type properties. Type is required to be basic.
285  */
wpas_dbus_simple_property_getter(DBusMessageIter * iter,const int type,const void * val,DBusError * error)286 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
287 					     const int type,
288 					     const void *val,
289 					     DBusError *error)
290 {
291 	DBusMessageIter variant_iter;
292 
293 	if (!dbus_type_is_basic(type)) {
294 		dbus_set_error(error, DBUS_ERROR_FAILED,
295 		               "%s: given type is not basic", __func__);
296 		return FALSE;
297 	}
298 
299 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
300 	                                      wpa_dbus_type_as_string(type),
301 	                                      &variant_iter))
302 		goto error;
303 
304 	if (!dbus_message_iter_append_basic(&variant_iter, type, val))
305 		goto error;
306 
307 	if (!dbus_message_iter_close_container(iter, &variant_iter))
308 		goto error;
309 
310 	return TRUE;
311 
312 error:
313 	dbus_set_error(error, DBUS_ERROR_FAILED,
314 	               "%s: error constructing reply", __func__);
315 	return FALSE;
316 }
317 
318 
319 /**
320  * wpas_dbus_simple_property_setter - Set basic type property
321  * @message: Pointer to incoming dbus message
322  * @type: DBus type of property (must be basic type)
323  * @val: pointer to place where value being set will be stored
324  * Returns: TRUE if the request was successful, FALSE if it failed
325  *
326  * Generic setter for basic type properties. Type is required to be basic.
327  */
wpas_dbus_simple_property_setter(DBusMessageIter * iter,DBusError * error,const int type,void * val)328 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
329 					     DBusError *error,
330 					     const int type, void *val)
331 {
332 	DBusMessageIter variant_iter;
333 
334 	if (!dbus_type_is_basic(type)) {
335 		dbus_set_error(error, DBUS_ERROR_FAILED,
336 			       "%s: given type is not basic", __func__);
337 		return FALSE;
338 	}
339 
340 	/* Look at the new value */
341 	dbus_message_iter_recurse(iter, &variant_iter);
342 	if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
343 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
344 				     "wrong property type");
345 		return FALSE;
346 	}
347 	dbus_message_iter_get_basic(&variant_iter, val);
348 
349 	return TRUE;
350 }
351 
352 
353 /**
354  * wpas_dbus_simple_array_property_getter - Get array type property
355  * @iter: Pointer to incoming dbus message iterator
356  * @type: DBus type of property array elements (must be basic type)
357  * @array: pointer to array of elements to put into response message
358  * @array_len: length of above array
359  * @error: a pointer to an error to fill on failure
360  * Returns: TRUE if the request succeeded, FALSE if it failed
361  *
362  * Generic getter for array type properties. Array elements type is
363  * required to be basic.
364  */
wpas_dbus_simple_array_property_getter(DBusMessageIter * iter,const int type,const void * array,size_t array_len,DBusError * error)365 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
366 						   const int type,
367 						   const void *array,
368 						   size_t array_len,
369 						   DBusError *error)
370 {
371 	DBusMessageIter variant_iter, array_iter;
372 	char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
373 	const char *sub_type_str;
374 	size_t element_size, i;
375 
376 	if (!dbus_type_is_basic(type)) {
377 		dbus_set_error(error, DBUS_ERROR_FAILED,
378 		               "%s: given type is not basic", __func__);
379 		return FALSE;
380 	}
381 
382 	sub_type_str = wpa_dbus_type_as_string(type);
383 	type_str[1] = sub_type_str[0];
384 
385 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
386 					      type_str, &variant_iter)) {
387 		dbus_set_error(error, DBUS_ERROR_FAILED,
388 		               "%s: failed to construct message 1", __func__);
389 		return FALSE;
390 	}
391 
392 	if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
393 					      sub_type_str, &array_iter)) {
394 		dbus_set_error(error, DBUS_ERROR_FAILED,
395 		               "%s: failed to construct message 2", __func__);
396 		return FALSE;
397 	}
398 
399 	switch(type) {
400 	case DBUS_TYPE_BYTE:
401 	case DBUS_TYPE_BOOLEAN:
402 		element_size = 1;
403 		break;
404 	case DBUS_TYPE_INT16:
405 	case DBUS_TYPE_UINT16:
406 		element_size = sizeof(uint16_t);
407 		break;
408 	case DBUS_TYPE_INT32:
409 	case DBUS_TYPE_UINT32:
410 		element_size = sizeof(uint32_t);
411 		break;
412 	case DBUS_TYPE_INT64:
413 	case DBUS_TYPE_UINT64:
414 		element_size = sizeof(uint64_t);
415 		break;
416 	case DBUS_TYPE_DOUBLE:
417 		element_size = sizeof(double);
418 		break;
419 	case DBUS_TYPE_STRING:
420 	case DBUS_TYPE_OBJECT_PATH:
421 		element_size = sizeof(char *);
422 		break;
423 	default:
424 		dbus_set_error(error, DBUS_ERROR_FAILED,
425 		               "%s: unknown element type %d", __func__, type);
426 		return FALSE;
427 	}
428 
429 	for (i = 0; i < array_len; i++) {
430 		dbus_message_iter_append_basic(&array_iter, type,
431 					       array + i * element_size);
432 	}
433 
434 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
435 		dbus_set_error(error, DBUS_ERROR_FAILED,
436 		               "%s: failed to construct message 3", __func__);
437 		return FALSE;
438 	}
439 
440 	if (!dbus_message_iter_close_container(iter, &variant_iter)) {
441 		dbus_set_error(error, DBUS_ERROR_FAILED,
442 		               "%s: failed to construct message 4", __func__);
443 		return FALSE;
444 	}
445 
446 	return TRUE;
447 }
448 
449 
450 /**
451  * wpas_dbus_handler_create_interface - Request registration of a network iface
452  * @message: Pointer to incoming dbus message
453  * @global: %wpa_supplicant global data structure
454  * Returns: The object path of the new interface object,
455  *          or a dbus error message with more information
456  *
457  * Handler function for "CreateInterface" method call. Handles requests
458  * by dbus clients to register a network interface that wpa_supplicant
459  * will manage.
460  */
wpas_dbus_handler_create_interface(DBusMessage * message,struct wpa_global * global)461 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
462 						 struct wpa_global *global)
463 {
464 	DBusMessageIter iter_dict;
465 	DBusMessage *reply = NULL;
466 	DBusMessageIter iter;
467 	struct wpa_dbus_dict_entry entry;
468 	char *driver = NULL;
469 	char *ifname = NULL;
470 	char *confname = NULL;
471 	char *bridge_ifname = NULL;
472 
473 	dbus_message_iter_init(message, &iter);
474 
475 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
476 		goto error;
477 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
478 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
479 			goto error;
480 		if (!strcmp(entry.key, "Driver") &&
481 		    (entry.type == DBUS_TYPE_STRING)) {
482 			driver = os_strdup(entry.str_value);
483 			wpa_dbus_dict_entry_clear(&entry);
484 			if (driver == NULL)
485 				goto error;
486 		} else if (!strcmp(entry.key, "Ifname") &&
487 			   (entry.type == DBUS_TYPE_STRING)) {
488 			ifname = os_strdup(entry.str_value);
489 			wpa_dbus_dict_entry_clear(&entry);
490 			if (ifname == NULL)
491 				goto error;
492 		} else if (!strcmp(entry.key, "ConfigFile") &&
493 			   (entry.type == DBUS_TYPE_STRING)) {
494 			confname = os_strdup(entry.str_value);
495 			wpa_dbus_dict_entry_clear(&entry);
496 			if (confname == NULL)
497 				goto error;
498 		} else if (!strcmp(entry.key, "BridgeIfname") &&
499 			   (entry.type == DBUS_TYPE_STRING)) {
500 			bridge_ifname = os_strdup(entry.str_value);
501 			wpa_dbus_dict_entry_clear(&entry);
502 			if (bridge_ifname == NULL)
503 				goto error;
504 		} else {
505 			wpa_dbus_dict_entry_clear(&entry);
506 			goto error;
507 		}
508 	}
509 
510 	if (ifname == NULL)
511 		goto error; /* Required Ifname argument missing */
512 
513 	/*
514 	 * Try to get the wpa_supplicant record for this iface, return
515 	 * an error if we already control it.
516 	 */
517 	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
518 		reply = dbus_message_new_error(message,
519 					       WPAS_DBUS_ERROR_IFACE_EXISTS,
520 					       "wpa_supplicant already "
521 					       "controls this interface.");
522 	} else {
523 		struct wpa_supplicant *wpa_s;
524 		struct wpa_interface iface;
525 		os_memset(&iface, 0, sizeof(iface));
526 		iface.driver = driver;
527 		iface.ifname = ifname;
528 		iface.confname = confname;
529 		iface.bridge_ifname = bridge_ifname;
530 		/* Otherwise, have wpa_supplicant attach to it. */
531 		if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
532 			const char *path = wpa_s->dbus_new_path;
533 			reply = dbus_message_new_method_return(message);
534 			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
535 			                         &path, DBUS_TYPE_INVALID);
536 		} else {
537 			reply = wpas_dbus_error_unknown_error(
538 				message, "wpa_supplicant couldn't grab this "
539 				"interface.");
540 		}
541 	}
542 
543 out:
544 	os_free(driver);
545 	os_free(ifname);
546 	os_free(bridge_ifname);
547 	return reply;
548 
549 error:
550 	reply = wpas_dbus_error_invalid_args(message, NULL);
551 	goto out;
552 }
553 
554 
555 /**
556  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
557  * @message: Pointer to incoming dbus message
558  * @global: wpa_supplicant global data structure
559  * Returns: a dbus message containing a UINT32 indicating success (1) or
560  *          failure (0), or returns a dbus error message with more information
561  *
562  * Handler function for "removeInterface" method call.  Handles requests
563  * by dbus clients to deregister a network interface that wpa_supplicant
564  * currently manages.
565  */
wpas_dbus_handler_remove_interface(DBusMessage * message,struct wpa_global * global)566 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
567 						 struct wpa_global *global)
568 {
569 	struct wpa_supplicant *wpa_s;
570 	char *path;
571 	DBusMessage *reply = NULL;
572 
573 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
574 			      DBUS_TYPE_INVALID);
575 
576 	wpa_s = get_iface_by_dbus_path(global, path);
577 	if (wpa_s == NULL)
578 		reply = wpas_dbus_error_iface_unknown(message);
579 	else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
580 		reply = wpas_dbus_error_unknown_error(
581 			message, "wpa_supplicant couldn't remove this "
582 			"interface.");
583 	}
584 
585 	return reply;
586 }
587 
588 
589 /**
590  * wpas_dbus_handler_get_interface - Get the object path for an interface name
591  * @message: Pointer to incoming dbus message
592  * @global: %wpa_supplicant global data structure
593  * Returns: The object path of the interface object,
594  *          or a dbus error message with more information
595  *
596  * Handler function for "getInterface" method call.
597  */
wpas_dbus_handler_get_interface(DBusMessage * message,struct wpa_global * global)598 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
599 					      struct wpa_global *global)
600 {
601 	DBusMessage *reply = NULL;
602 	const char *ifname;
603 	const char *path;
604 	struct wpa_supplicant *wpa_s;
605 
606 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
607 			      DBUS_TYPE_INVALID);
608 
609 	wpa_s = wpa_supplicant_get_iface(global, ifname);
610 	if (wpa_s == NULL)
611 		return wpas_dbus_error_iface_unknown(message);
612 
613 	path = wpa_s->dbus_new_path;
614 	reply = dbus_message_new_method_return(message);
615 	if (reply == NULL)
616 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
617 					      NULL);
618 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
619 				      DBUS_TYPE_INVALID)) {
620 		dbus_message_unref(reply);
621 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
622 					      NULL);
623 	}
624 
625 	return reply;
626 }
627 
628 
629 /**
630  * wpas_dbus_getter_debug_level - Get debug level
631  * @iter: Pointer to incoming dbus message iter
632  * @error: Location to store error on failure
633  * @user_data: Function specific data
634  * Returns: TRUE on success, FALSE on failure
635  *
636  * Getter for "DebugLevel" property.
637  */
wpas_dbus_getter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)638 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
639 					 DBusError *error,
640 					 void *user_data)
641 {
642 	const char *str;
643 	int idx = wpa_debug_level;
644 
645 	if (idx < 0)
646 		idx = 0;
647 	if (idx > 5)
648 		idx = 5;
649 	str = debug_strings[idx];
650 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
651 						&str, error);
652 }
653 
654 
655 /**
656  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
657  * @iter: Pointer to incoming dbus message iter
658  * @error: Location to store error on failure
659  * @user_data: Function specific data
660  * Returns: TRUE on success, FALSE on failure
661  *
662  * Getter for "DebugTimestamp" property.
663  */
wpas_dbus_getter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)664 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
665                                              DBusError *error,
666                                              void *user_data)
667 {
668 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
669 						&wpa_debug_timestamp, error);
670 
671 }
672 
673 
674 /**
675  * wpas_dbus_getter_debug_show_keys - Get debug show keys
676  * @iter: Pointer to incoming dbus message iter
677  * @error: Location to store error on failure
678  * @user_data: Function specific data
679  * Returns: TRUE on success, FALSE on failure
680  *
681  * Getter for "DebugShowKeys" property.
682  */
wpas_dbus_getter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)683 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
684 					     DBusError *error,
685 					     void *user_data)
686 {
687 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
688 						&wpa_debug_show_keys, error);
689 
690 }
691 
692 /**
693  * wpas_dbus_setter_debug_level - Set debug level
694  * @iter: Pointer to incoming dbus message iter
695  * @error: Location to store error on failure
696  * @user_data: Function specific data
697  * Returns: TRUE on success, FALSE on failure
698  *
699  * Setter for "DebugLevel" property.
700  */
wpas_dbus_setter_debug_level(DBusMessageIter * iter,DBusError * error,void * user_data)701 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
702 					 DBusError *error, void *user_data)
703 {
704 	struct wpa_global *global = user_data;
705 	const char *str = NULL;
706 	int i, val = -1;
707 
708 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
709 					      &str))
710 		return FALSE;
711 
712 	for (i = 0; debug_strings[i]; i++)
713 		if (os_strcmp(debug_strings[i], str) == 0) {
714 			val = i;
715 			break;
716 		}
717 
718 	if (val < 0 ||
719 	    wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
720 					    wpa_debug_show_keys)) {
721 		dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug "
722 				     "level value");
723 		return FALSE;
724 	}
725 
726 	return TRUE;
727 }
728 
729 
730 /**
731  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
732  * @iter: Pointer to incoming dbus message iter
733  * @error: Location to store error on failure
734  * @user_data: Function specific data
735  * Returns: TRUE on success, FALSE on failure
736  *
737  * Setter for "DebugTimestamp" property.
738  */
wpas_dbus_setter_debug_timestamp(DBusMessageIter * iter,DBusError * error,void * user_data)739 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
740 					     DBusError *error,
741 					     void *user_data)
742 {
743 	struct wpa_global *global = user_data;
744 	dbus_bool_t val;
745 
746 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
747 					      &val))
748 		return FALSE;
749 
750 	wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
751 					wpa_debug_show_keys);
752 	return TRUE;
753 }
754 
755 
756 /**
757  * wpas_dbus_setter_debug_show_keys - Set debug show keys
758  * @iter: Pointer to incoming dbus message iter
759  * @error: Location to store error on failure
760  * @user_data: Function specific data
761  * Returns: TRUE on success, FALSE on failure
762  *
763  * Setter for "DebugShowKeys" property.
764  */
wpas_dbus_setter_debug_show_keys(DBusMessageIter * iter,DBusError * error,void * user_data)765 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
766 					     DBusError *error,
767 					     void *user_data)
768 {
769 	struct wpa_global *global = user_data;
770 	dbus_bool_t val;
771 
772 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
773 					      &val))
774 		return FALSE;
775 
776 	wpa_supplicant_set_debug_params(global, wpa_debug_level,
777 					wpa_debug_timestamp,
778 					val ? 1 : 0);
779 	return TRUE;
780 }
781 
782 
783 /**
784  * wpas_dbus_getter_interfaces - Request registered interfaces list
785  * @iter: Pointer to incoming dbus message iter
786  * @error: Location to store error on failure
787  * @user_data: Function specific data
788  * Returns: TRUE on success, FALSE on failure
789  *
790  * Getter for "Interfaces" property. Handles requests
791  * by dbus clients to return list of registered interfaces objects
792  * paths
793  */
wpas_dbus_getter_interfaces(DBusMessageIter * iter,DBusError * error,void * user_data)794 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
795 					DBusError *error,
796 					void *user_data)
797 {
798 	struct wpa_global *global = user_data;
799 	struct wpa_supplicant *wpa_s;
800 	const char **paths;
801 	unsigned int i = 0, num = 0;
802 	dbus_bool_t success;
803 
804 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
805 		num++;
806 
807 	paths = os_zalloc(num * sizeof(char*));
808 	if (!paths) {
809 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
810 		return FALSE;
811 	}
812 
813 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
814 		paths[i++] = wpa_s->dbus_new_path;
815 
816 	success = wpas_dbus_simple_array_property_getter(iter,
817 							 DBUS_TYPE_OBJECT_PATH,
818 							 paths, num, error);
819 
820 	os_free(paths);
821 	return success;
822 }
823 
824 
825 /**
826  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
827  * @iter: Pointer to incoming dbus message iter
828  * @error: Location to store error on failure
829  * @user_data: Function specific data
830  * Returns: TRUE on success, FALSE on failure
831  *
832  * Getter for "EapMethods" property. Handles requests
833  * by dbus clients to return list of strings with supported EAP methods
834  */
wpas_dbus_getter_eap_methods(DBusMessageIter * iter,DBusError * error,void * user_data)835 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
836 					 DBusError *error, void *user_data)
837 {
838 	char **eap_methods;
839 	size_t num_items = 0;
840 	dbus_bool_t success;
841 
842 	eap_methods = eap_get_names_as_string_array(&num_items);
843 	if (!eap_methods) {
844 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
845 		return FALSE;
846 	}
847 
848 	success = wpas_dbus_simple_array_property_getter(iter,
849 							 DBUS_TYPE_STRING,
850 							 eap_methods,
851 							 num_items, error);
852 
853 	while (num_items)
854 		os_free(eap_methods[--num_items]);
855 	os_free(eap_methods);
856 	return success;
857 }
858 
859 
wpas_dbus_get_scan_type(DBusMessage * message,DBusMessageIter * var,char ** type,DBusMessage ** reply)860 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
861 				   char **type, DBusMessage **reply)
862 {
863 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
864 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
865 			   "Type must be a string");
866 		*reply = wpas_dbus_error_invalid_args(
867 			message, "Wrong Type value type. String required");
868 		return -1;
869 	}
870 	dbus_message_iter_get_basic(var, type);
871 	return 0;
872 }
873 
874 
wpas_dbus_get_scan_ssids(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)875 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
876 				    struct wpa_driver_scan_params *params,
877 				    DBusMessage **reply)
878 {
879 	struct wpa_driver_scan_ssid *ssids = params->ssids;
880 	size_t ssids_num = 0;
881 	u8 *ssid;
882 	DBusMessageIter array_iter, sub_array_iter;
883 	char *val;
884 	int len;
885 
886 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
887 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
888 			   "must be an array of arrays of bytes");
889 		*reply = wpas_dbus_error_invalid_args(
890 			message, "Wrong SSIDs value type. Array of arrays of "
891 			"bytes required");
892 		return -1;
893 	}
894 
895 	dbus_message_iter_recurse(var, &array_iter);
896 
897 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
898 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
899 	{
900 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
901 			   "must be an array of arrays of bytes");
902 		*reply = wpas_dbus_error_invalid_args(
903 			message, "Wrong SSIDs value type. Array of arrays of "
904 			"bytes required");
905 		return -1;
906 	}
907 
908 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
909 	{
910 		if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
911 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
912 				   "Too many ssids specified on scan dbus "
913 				   "call");
914 			*reply = wpas_dbus_error_invalid_args(
915 				message, "Too many ssids specified. Specify "
916 				"at most four");
917 			return -1;
918 		}
919 
920 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
921 
922 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
923 
924 		if (len > MAX_SSID_LEN) {
925 			wpa_printf(MSG_DEBUG,
926 				   "wpas_dbus_handler_scan[dbus]: "
927 				   "SSID too long (len=%d max_len=%d)",
928 				   len, MAX_SSID_LEN);
929 			*reply = wpas_dbus_error_invalid_args(
930 				message, "Invalid SSID: too long");
931 			return -1;
932 		}
933 
934 		if (len != 0) {
935 			ssid = os_malloc(len);
936 			if (ssid == NULL) {
937 				wpa_printf(MSG_DEBUG,
938 					   "wpas_dbus_handler_scan[dbus]: "
939 					   "out of memory. Cannot allocate "
940 					   "memory for SSID");
941 				*reply = dbus_message_new_error(
942 					message, DBUS_ERROR_NO_MEMORY, NULL);
943 				return -1;
944 			}
945 			os_memcpy(ssid, val, len);
946 		} else {
947 			/* Allow zero-length SSIDs */
948 			ssid = NULL;
949 		}
950 
951 		ssids[ssids_num].ssid = ssid;
952 		ssids[ssids_num].ssid_len = len;
953 
954 		dbus_message_iter_next(&array_iter);
955 		ssids_num++;
956 	}
957 
958 	params->num_ssids = ssids_num;
959 	return 0;
960 }
961 
962 
wpas_dbus_get_scan_ies(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)963 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
964 				  struct wpa_driver_scan_params *params,
965 				  DBusMessage **reply)
966 {
967 	u8 *ies = NULL, *nies;
968 	int ies_len = 0;
969 	DBusMessageIter array_iter, sub_array_iter;
970 	char *val;
971 	int len;
972 
973 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
974 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
975 			   "be an array of arrays of bytes");
976 		*reply = wpas_dbus_error_invalid_args(
977 			message, "Wrong IEs value type. Array of arrays of "
978 			"bytes required");
979 		return -1;
980 	}
981 
982 	dbus_message_iter_recurse(var, &array_iter);
983 
984 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
985 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
986 	{
987 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
988 			   "be an array of arrays of bytes");
989 		*reply = wpas_dbus_error_invalid_args(
990 			message, "Wrong IEs value type. Array required");
991 		return -1;
992 	}
993 
994 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
995 	{
996 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
997 
998 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
999 		if (len == 0) {
1000 			dbus_message_iter_next(&array_iter);
1001 			continue;
1002 		}
1003 
1004 		nies = os_realloc(ies, ies_len + len);
1005 		if (nies == NULL) {
1006 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1007 				   "out of memory. Cannot allocate memory for "
1008 				   "IE");
1009 			os_free(ies);
1010 			*reply = dbus_message_new_error(
1011 				message, DBUS_ERROR_NO_MEMORY, NULL);
1012 			return -1;
1013 		}
1014 		ies = nies;
1015 		os_memcpy(ies + ies_len, val, len);
1016 		ies_len += len;
1017 
1018 		dbus_message_iter_next(&array_iter);
1019 	}
1020 
1021 	params->extra_ies = ies;
1022 	params->extra_ies_len = ies_len;
1023 	return 0;
1024 }
1025 
1026 
wpas_dbus_get_scan_channels(DBusMessage * message,DBusMessageIter * var,struct wpa_driver_scan_params * params,DBusMessage ** reply)1027 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1028 				       DBusMessageIter *var,
1029 				       struct wpa_driver_scan_params *params,
1030 				       DBusMessage **reply)
1031 {
1032 	DBusMessageIter array_iter, sub_array_iter;
1033 	int *freqs = NULL, *nfreqs;
1034 	int freqs_num = 0;
1035 
1036 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1037 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1038 			   "Channels must be an array of structs");
1039 		*reply = wpas_dbus_error_invalid_args(
1040 			message, "Wrong Channels value type. Array of structs "
1041 			"required");
1042 		return -1;
1043 	}
1044 
1045 	dbus_message_iter_recurse(var, &array_iter);
1046 
1047 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1048 		wpa_printf(MSG_DEBUG,
1049 			   "wpas_dbus_handler_scan[dbus]: Channels must be an "
1050 			   "array of structs");
1051 		*reply = wpas_dbus_error_invalid_args(
1052 			message, "Wrong Channels value type. Array of structs "
1053 			"required");
1054 		return -1;
1055 	}
1056 
1057 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1058 	{
1059 		int freq, width;
1060 
1061 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1062 
1063 		if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1064 		    DBUS_TYPE_UINT32) {
1065 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1066 				   "Channel must by specified by struct of "
1067 				   "two UINT32s %c",
1068 				   dbus_message_iter_get_arg_type(
1069 					   &sub_array_iter));
1070 			*reply = wpas_dbus_error_invalid_args(
1071 				message, "Wrong Channel struct. Two UINT32s "
1072 				"required");
1073 			os_free(freqs);
1074 			return -1;
1075 		}
1076 		dbus_message_iter_get_basic(&sub_array_iter, &freq);
1077 
1078 		if (!dbus_message_iter_next(&sub_array_iter) ||
1079 		    dbus_message_iter_get_arg_type(&sub_array_iter) !=
1080 		    DBUS_TYPE_UINT32) {
1081 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1082 				   "Channel must by specified by struct of "
1083 				   "two UINT32s");
1084 			*reply = wpas_dbus_error_invalid_args(
1085 				message,
1086 				"Wrong Channel struct. Two UINT32s required");
1087 			os_free(freqs);
1088 			return -1;
1089 		}
1090 
1091 		dbus_message_iter_get_basic(&sub_array_iter, &width);
1092 
1093 #define FREQS_ALLOC_CHUNK 32
1094 		if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1095 			nfreqs = os_realloc(freqs, sizeof(int) *
1096 					    (freqs_num + FREQS_ALLOC_CHUNK));
1097 			if (nfreqs == NULL)
1098 				os_free(freqs);
1099 			freqs = nfreqs;
1100 		}
1101 		if (freqs == NULL) {
1102 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1103 				   "out of memory. can't allocate memory for "
1104 				   "freqs");
1105 			*reply = dbus_message_new_error(
1106 				message, DBUS_ERROR_NO_MEMORY, NULL);
1107 			return -1;
1108 		}
1109 
1110 		freqs[freqs_num] = freq;
1111 
1112 		freqs_num++;
1113 		dbus_message_iter_next(&array_iter);
1114 	}
1115 
1116 	nfreqs = os_realloc(freqs,
1117 			    sizeof(int) * (freqs_num + 1));
1118 	if (nfreqs == NULL)
1119 		os_free(freqs);
1120 	freqs = nfreqs;
1121 	if (freqs == NULL) {
1122 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1123 			   "out of memory. Can't allocate memory for freqs");
1124 		*reply = dbus_message_new_error(
1125 			message, DBUS_ERROR_NO_MEMORY, NULL);
1126 		return -1;
1127 	}
1128 	freqs[freqs_num] = 0;
1129 
1130 	params->freqs = freqs;
1131 	return 0;
1132 }
1133 
1134 
1135 /**
1136  * wpas_dbus_handler_scan - Request a wireless scan on an interface
1137  * @message: Pointer to incoming dbus message
1138  * @wpa_s: wpa_supplicant structure for a network interface
1139  * Returns: NULL indicating success or DBus error message on failure
1140  *
1141  * Handler function for "Scan" method call of a network device. Requests
1142  * that wpa_supplicant perform a wireless scan as soon as possible
1143  * on a particular wireless interface.
1144  */
wpas_dbus_handler_scan(DBusMessage * message,struct wpa_supplicant * wpa_s)1145 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1146 				     struct wpa_supplicant *wpa_s)
1147 {
1148 	DBusMessage *reply = NULL;
1149 	DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1150 	char *key = NULL, *type = NULL;
1151 	struct wpa_driver_scan_params params;
1152 	size_t i;
1153 
1154 	os_memset(&params, 0, sizeof(params));
1155 
1156 	dbus_message_iter_init(message, &iter);
1157 
1158 	dbus_message_iter_recurse(&iter, &dict_iter);
1159 
1160 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
1161 			DBUS_TYPE_DICT_ENTRY) {
1162 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
1163 		dbus_message_iter_get_basic(&entry_iter, &key);
1164 		dbus_message_iter_next(&entry_iter);
1165 		dbus_message_iter_recurse(&entry_iter, &variant_iter);
1166 
1167 		if (os_strcmp(key, "Type") == 0) {
1168 			if (wpas_dbus_get_scan_type(message, &variant_iter,
1169 						    &type, &reply) < 0)
1170 				goto out;
1171 		} else if (os_strcmp(key, "SSIDs") == 0) {
1172 			if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1173 						     &params, &reply) < 0)
1174 				goto out;
1175 		} else if (os_strcmp(key, "IEs") == 0) {
1176 			if (wpas_dbus_get_scan_ies(message, &variant_iter,
1177 						   &params, &reply) < 0)
1178 				goto out;
1179 		} else if (os_strcmp(key, "Channels") == 0) {
1180 			if (wpas_dbus_get_scan_channels(message, &variant_iter,
1181 							&params, &reply) < 0)
1182 				goto out;
1183 		} else {
1184 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1185 				   "Unknown argument %s", key);
1186 			reply = wpas_dbus_error_invalid_args(message, key);
1187 			goto out;
1188 		}
1189 
1190 		dbus_message_iter_next(&dict_iter);
1191 	}
1192 
1193 	if (!type) {
1194 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1195 			   "Scan type not specified");
1196 		reply = wpas_dbus_error_invalid_args(message, key);
1197 		goto out;
1198 	}
1199 
1200 	if (!os_strcmp(type, "passive")) {
1201 		if (params.num_ssids || params.extra_ies_len) {
1202 			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1203 				   "SSIDs or IEs specified for passive scan.");
1204 			reply = wpas_dbus_error_invalid_args(
1205 				message, "You can specify only Channels in "
1206 				"passive scan");
1207 			goto out;
1208 		} else if (params.freqs && params.freqs[0]) {
1209 			wpa_supplicant_trigger_scan(wpa_s, &params);
1210 		} else {
1211 			wpa_s->scan_req = 2;
1212 			wpa_supplicant_req_scan(wpa_s, 0, 0);
1213 		}
1214 	} else if (!os_strcmp(type, "active")) {
1215 		if (!params.num_ssids) {
1216 			/* Add wildcard ssid */
1217 			params.num_ssids++;
1218 		}
1219 		wpa_supplicant_trigger_scan(wpa_s, &params);
1220 	} else {
1221 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1222 			   "Unknown scan type: %s", type);
1223 		reply = wpas_dbus_error_invalid_args(message,
1224 						     "Wrong scan type");
1225 		goto out;
1226 	}
1227 
1228 out:
1229 	for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1230 		os_free((u8 *) params.ssids[i].ssid);
1231 	os_free((u8 *) params.extra_ies);
1232 	os_free(params.freqs);
1233 	return reply;
1234 }
1235 
1236 
1237 /*
1238  * wpas_dbus_handler_disconnect - Terminate the current connection
1239  * @message: Pointer to incoming dbus message
1240  * @wpa_s: wpa_supplicant structure for a network interface
1241  * Returns: NotConnected DBus error message if already not connected
1242  * or NULL otherwise.
1243  *
1244  * Handler function for "Disconnect" method call of network interface.
1245  */
wpas_dbus_handler_disconnect(DBusMessage * message,struct wpa_supplicant * wpa_s)1246 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1247 					   struct wpa_supplicant *wpa_s)
1248 {
1249 	if (wpa_s->current_ssid != NULL) {
1250 		wpa_s->disconnected = 1;
1251 		wpa_supplicant_deauthenticate(wpa_s,
1252 					      WLAN_REASON_DEAUTH_LEAVING);
1253 
1254 		return NULL;
1255 	}
1256 
1257 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1258 				      "This interface is not connected");
1259 }
1260 
1261 
1262 /**
1263  * wpas_dbus_new_iface_add_network - Add a new configured network
1264  * @message: Pointer to incoming dbus message
1265  * @wpa_s: wpa_supplicant structure for a network interface
1266  * Returns: A dbus message containing the object path of the new network
1267  *
1268  * Handler function for "AddNetwork" method call of a network interface.
1269  */
wpas_dbus_handler_add_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1270 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1271 					    struct wpa_supplicant *wpa_s)
1272 {
1273 	DBusMessage *reply = NULL;
1274 	DBusMessageIter	iter;
1275 	struct wpa_ssid *ssid = NULL;
1276 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1277 	DBusError error;
1278 
1279 	dbus_message_iter_init(message, &iter);
1280 
1281 	ssid = wpa_config_add_network(wpa_s->conf);
1282 	if (ssid == NULL) {
1283 		wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1284 			   "can't add new interface.");
1285 		reply = wpas_dbus_error_unknown_error(
1286 			message,
1287 			"wpa_supplicant could not add "
1288 			"a network on this interface.");
1289 		goto err;
1290 	}
1291 	wpas_notify_network_added(wpa_s, ssid);
1292 	ssid->disabled = 1;
1293 	wpa_config_set_network_defaults(ssid);
1294 
1295 	dbus_error_init(&error);
1296 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1297 		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1298 			   "control interface couldn't set network "
1299 			   "properties");
1300 		reply = wpas_dbus_reply_new_from_error(message, &error,
1301 						       DBUS_ERROR_INVALID_ARGS,
1302 						       "Failed to add network");
1303 		dbus_error_free(&error);
1304 		goto err;
1305 	}
1306 
1307 	/* Construct the object path for this network. */
1308 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1309 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1310 		    wpa_s->dbus_new_path, ssid->id);
1311 
1312 	reply = dbus_message_new_method_return(message);
1313 	if (reply == NULL) {
1314 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1315 					       NULL);
1316 		goto err;
1317 	}
1318 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1319 				      DBUS_TYPE_INVALID)) {
1320 		dbus_message_unref(reply);
1321 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1322 					       NULL);
1323 		goto err;
1324 	}
1325 
1326 	return reply;
1327 
1328 err:
1329 	if (ssid) {
1330 		wpas_notify_network_removed(wpa_s, ssid);
1331 		wpa_config_remove_network(wpa_s->conf, ssid->id);
1332 	}
1333 	return reply;
1334 }
1335 
1336 
1337 /**
1338  * wpas_dbus_handler_remove_network - Remove a configured network
1339  * @message: Pointer to incoming dbus message
1340  * @wpa_s: wpa_supplicant structure for a network interface
1341  * Returns: NULL on success or dbus error on failure
1342  *
1343  * Handler function for "RemoveNetwork" method call of a network interface.
1344  */
wpas_dbus_handler_remove_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1345 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1346 					       struct wpa_supplicant *wpa_s)
1347 {
1348 	DBusMessage *reply = NULL;
1349 	const char *op;
1350 	char *iface = NULL, *net_id = NULL;
1351 	int id;
1352 	struct wpa_ssid *ssid;
1353 
1354 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1355 			      DBUS_TYPE_INVALID);
1356 
1357 	/* Extract the network ID and ensure the network */
1358 	/* is actually a child of this interface */
1359 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1360 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1361 		reply = wpas_dbus_error_invalid_args(message, op);
1362 		goto out;
1363 	}
1364 
1365 	id = strtoul(net_id, NULL, 10);
1366 	if (errno == EINVAL) {
1367 		reply = wpas_dbus_error_invalid_args(message, op);
1368 		goto out;
1369 	}
1370 
1371 	ssid = wpa_config_get_network(wpa_s->conf, id);
1372 	if (ssid == NULL) {
1373 		reply = wpas_dbus_error_network_unknown(message);
1374 		goto out;
1375 	}
1376 
1377 	wpas_notify_network_removed(wpa_s, ssid);
1378 
1379 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1380 		wpa_printf(MSG_ERROR,
1381 			   "wpas_dbus_handler_remove_network[dbus]: "
1382 			   "error occurred when removing network %d", id);
1383 		reply = wpas_dbus_error_unknown_error(
1384 			message, "error removing the specified network on "
1385 			"this interface.");
1386 		goto out;
1387 	}
1388 
1389 	if (ssid == wpa_s->current_ssid)
1390 		wpa_supplicant_deauthenticate(wpa_s,
1391 					      WLAN_REASON_DEAUTH_LEAVING);
1392 
1393 out:
1394 	os_free(iface);
1395 	os_free(net_id);
1396 	return reply;
1397 }
1398 
1399 
remove_network(void * arg,struct wpa_ssid * ssid)1400 static void remove_network(void *arg, struct wpa_ssid *ssid)
1401 {
1402 	struct wpa_supplicant *wpa_s = arg;
1403 
1404 	wpas_notify_network_removed(wpa_s, ssid);
1405 
1406 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1407 		wpa_printf(MSG_ERROR,
1408 			   "wpas_dbus_handler_remove_all_networks[dbus]: "
1409 			   "error occurred when removing network %d",
1410 			   ssid->id);
1411 		return;
1412 	}
1413 
1414 	if (ssid == wpa_s->current_ssid)
1415 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1416 }
1417 
1418 
1419 /**
1420  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1421  * @message: Pointer to incoming dbus message
1422  * @wpa_s: wpa_supplicant structure for a network interface
1423  * Returns: NULL on success or dbus error on failure
1424  *
1425  * Handler function for "RemoveAllNetworks" method call of a network interface.
1426  */
wpas_dbus_handler_remove_all_networks(DBusMessage * message,struct wpa_supplicant * wpa_s)1427 DBusMessage * wpas_dbus_handler_remove_all_networks(
1428 	DBusMessage *message, struct wpa_supplicant *wpa_s)
1429 {
1430 	/* NB: could check for failure and return an error */
1431 	wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1432 	return NULL;
1433 }
1434 
1435 
1436 /**
1437  * wpas_dbus_handler_select_network - Attempt association with a network
1438  * @message: Pointer to incoming dbus message
1439  * @wpa_s: wpa_supplicant structure for a network interface
1440  * Returns: NULL on success or dbus error on failure
1441  *
1442  * Handler function for "SelectNetwork" method call of network interface.
1443  */
wpas_dbus_handler_select_network(DBusMessage * message,struct wpa_supplicant * wpa_s)1444 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1445 					       struct wpa_supplicant *wpa_s)
1446 {
1447 	DBusMessage *reply = NULL;
1448 	const char *op;
1449 	char *iface = NULL, *net_id = NULL;
1450 	int id;
1451 	struct wpa_ssid *ssid;
1452 
1453 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1454 			      DBUS_TYPE_INVALID);
1455 
1456 	/* Extract the network ID and ensure the network */
1457 	/* is actually a child of this interface */
1458 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1459 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1460 		reply = wpas_dbus_error_invalid_args(message, op);
1461 		goto out;
1462 	}
1463 
1464 	id = strtoul(net_id, NULL, 10);
1465 	if (errno == EINVAL) {
1466 		reply = wpas_dbus_error_invalid_args(message, op);
1467 		goto out;
1468 	}
1469 
1470 	ssid = wpa_config_get_network(wpa_s->conf, id);
1471 	if (ssid == NULL) {
1472 		reply = wpas_dbus_error_network_unknown(message);
1473 		goto out;
1474 	}
1475 
1476 	/* Finally, associate with the network */
1477 	wpa_supplicant_select_network(wpa_s, ssid);
1478 
1479 out:
1480 	os_free(iface);
1481 	os_free(net_id);
1482 	return reply;
1483 }
1484 
1485 
1486 /**
1487  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1488  * @message: Pointer to incoming dbus message
1489  * @wpa_s: wpa_supplicant structure for a network interface
1490  * Returns: NULL on success or dbus error on failure
1491  *
1492  * Handler function for "NetworkReply" method call of network interface.
1493  */
wpas_dbus_handler_network_reply(DBusMessage * message,struct wpa_supplicant * wpa_s)1494 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1495 					      struct wpa_supplicant *wpa_s)
1496 {
1497 #ifdef IEEE8021X_EAPOL
1498 	DBusMessage *reply = NULL;
1499 	const char *op, *field, *value;
1500 	char *iface = NULL, *net_id = NULL;
1501 	int id;
1502 	struct wpa_ssid *ssid;
1503 
1504 	if (!dbus_message_get_args(message, NULL,
1505 	                           DBUS_TYPE_OBJECT_PATH, &op,
1506 	                           DBUS_TYPE_STRING, &field,
1507 	                           DBUS_TYPE_STRING, &value,
1508 			           DBUS_TYPE_INVALID))
1509 		return wpas_dbus_error_invalid_args(message, NULL);
1510 
1511 	/* Extract the network ID and ensure the network */
1512 	/* is actually a child of this interface */
1513 	iface = wpas_dbus_new_decompose_object_path(op, 0, &net_id, NULL);
1514 	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1515 		reply = wpas_dbus_error_invalid_args(message, op);
1516 		goto out;
1517 	}
1518 
1519 	id = strtoul(net_id, NULL, 10);
1520 	if (errno == EINVAL) {
1521 		reply = wpas_dbus_error_invalid_args(message, net_id);
1522 		goto out;
1523 	}
1524 
1525 	ssid = wpa_config_get_network(wpa_s->conf, id);
1526 	if (ssid == NULL) {
1527 		reply = wpas_dbus_error_network_unknown(message);
1528 		goto out;
1529 	}
1530 
1531 	if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1532 						      field, value) < 0)
1533 		reply = wpas_dbus_error_invalid_args(message, field);
1534 	else {
1535 		/* Tell EAP to retry immediately */
1536 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
1537 	}
1538 
1539 out:
1540 	os_free(iface);
1541 	os_free(net_id);
1542 	return reply;
1543 #else /* IEEE8021X_EAPOL */
1544 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1545 	return wpas_dbus_error_unknown_error(message, "802.1X not included");
1546 #endif /* IEEE8021X_EAPOL */
1547 }
1548 
1549 
1550 /**
1551  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1552  * @message: Pointer to incoming dbus message
1553  * @wpa_s: %wpa_supplicant data structure
1554  * Returns: A dbus message containing an error on failure or NULL on success
1555  *
1556  * Asks wpa_supplicant to internally store a binary blobs.
1557  */
wpas_dbus_handler_add_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1558 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1559 					 struct wpa_supplicant *wpa_s)
1560 {
1561 	DBusMessage *reply = NULL;
1562 	DBusMessageIter	iter, array_iter;
1563 
1564 	char *blob_name;
1565 	u8 *blob_data;
1566 	int blob_len;
1567 	struct wpa_config_blob *blob = NULL;
1568 
1569 	dbus_message_iter_init(message, &iter);
1570 	dbus_message_iter_get_basic(&iter, &blob_name);
1571 
1572 	if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1573 		return dbus_message_new_error(message,
1574 					      WPAS_DBUS_ERROR_BLOB_EXISTS,
1575 					      NULL);
1576 	}
1577 
1578 	dbus_message_iter_next(&iter);
1579 	dbus_message_iter_recurse(&iter, &array_iter);
1580 
1581 	dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1582 
1583 	blob = os_zalloc(sizeof(*blob));
1584 	if (!blob) {
1585 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1586 					       NULL);
1587 		goto err;
1588 	}
1589 
1590 	blob->data = os_malloc(blob_len);
1591 	if (!blob->data) {
1592 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1593 					       NULL);
1594 		goto err;
1595 	}
1596 	os_memcpy(blob->data, blob_data, blob_len);
1597 
1598 	blob->len = blob_len;
1599 	blob->name = os_strdup(blob_name);
1600 	if (!blob->name) {
1601 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1602 					       NULL);
1603 		goto err;
1604 	}
1605 
1606 	wpa_config_set_blob(wpa_s->conf, blob);
1607 	wpas_notify_blob_added(wpa_s, blob->name);
1608 
1609 	return reply;
1610 
1611 err:
1612 	if (blob) {
1613 		os_free(blob->name);
1614 		os_free(blob->data);
1615 		os_free(blob);
1616 	}
1617 	return reply;
1618 }
1619 
1620 
1621 /**
1622  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1623  * @message: Pointer to incoming dbus message
1624  * @wpa_s: %wpa_supplicant data structure
1625  * Returns: A dbus message containing array of bytes (blob)
1626  *
1627  * Gets one wpa_supplicant's binary blobs.
1628  */
wpas_dbus_handler_get_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1629 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1630 					 struct wpa_supplicant *wpa_s)
1631 {
1632 	DBusMessage *reply = NULL;
1633 	DBusMessageIter	iter, array_iter;
1634 
1635 	char *blob_name;
1636 	const struct wpa_config_blob *blob;
1637 
1638 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1639 			      DBUS_TYPE_INVALID);
1640 
1641 	blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1642 	if (!blob) {
1643 		return dbus_message_new_error(message,
1644 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1645 					      "Blob id not set");
1646 	}
1647 
1648 	reply = dbus_message_new_method_return(message);
1649 	if (!reply) {
1650 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1651 					       NULL);
1652 		goto out;
1653 	}
1654 
1655 	dbus_message_iter_init_append(reply, &iter);
1656 
1657 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1658 					      DBUS_TYPE_BYTE_AS_STRING,
1659 					      &array_iter)) {
1660 		dbus_message_unref(reply);
1661 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1662 					       NULL);
1663 		goto out;
1664 	}
1665 
1666 	if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1667 						  &(blob->data), blob->len)) {
1668 		dbus_message_unref(reply);
1669 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1670 					       NULL);
1671 		goto out;
1672 	}
1673 
1674 	if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1675 		dbus_message_unref(reply);
1676 		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1677 					       NULL);
1678 		goto out;
1679 	}
1680 
1681 out:
1682 	return reply;
1683 }
1684 
1685 
1686 /**
1687  * wpas_remove_handler_remove_blob - Remove named binary blob
1688  * @message: Pointer to incoming dbus message
1689  * @wpa_s: %wpa_supplicant data structure
1690  * Returns: NULL on success or dbus error
1691  *
1692  * Asks wpa_supplicant to internally remove a binary blobs.
1693  */
wpas_dbus_handler_remove_blob(DBusMessage * message,struct wpa_supplicant * wpa_s)1694 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1695 					    struct wpa_supplicant *wpa_s)
1696 {
1697 	DBusMessage *reply = NULL;
1698 	char *blob_name;
1699 
1700 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1701 			      DBUS_TYPE_INVALID);
1702 
1703 	if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1704 		return dbus_message_new_error(message,
1705 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1706 					      "Blob id not set");
1707 	}
1708 	wpas_notify_blob_removed(wpa_s, blob_name);
1709 
1710 	return reply;
1711 
1712 }
1713 
1714 /*
1715  * wpas_dbus_handler_flush_bss - Flush the BSS cache
1716  * @message: Pointer to incoming dbus message
1717  * @wpa_s: wpa_supplicant structure for a network interface
1718  * Returns: NULL
1719  *
1720  * Handler function for "FlushBSS" method call of network interface.
1721  */
wpas_dbus_handler_flush_bss(DBusMessage * message,struct wpa_supplicant * wpa_s)1722 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1723 					  struct wpa_supplicant *wpa_s)
1724 {
1725 	dbus_uint32_t age;
1726 
1727 	dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1728 			      DBUS_TYPE_INVALID);
1729 
1730 	if (age == 0)
1731 		wpa_bss_flush(wpa_s);
1732 	else
1733 		wpa_bss_flush_by_age(wpa_s, age);
1734 
1735 	return NULL;
1736 }
1737 
1738 
1739 /**
1740  * wpas_dbus_getter_capabilities - Return interface capabilities
1741  * @iter: Pointer to incoming dbus message iter
1742  * @error: Location to store error on failure
1743  * @user_data: Function specific data
1744  * Returns: TRUE on success, FALSE on failure
1745  *
1746  * Getter for "Capabilities" property of an interface.
1747  */
wpas_dbus_getter_capabilities(DBusMessageIter * iter,DBusError * error,void * user_data)1748 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
1749 					  DBusError *error, void *user_data)
1750 {
1751 	struct wpa_supplicant *wpa_s = user_data;
1752 	struct wpa_driver_capa capa;
1753 	int res;
1754 	DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
1755 		variant_iter;
1756 	const char *scans[] = { "active", "passive", "ssid" };
1757 
1758 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1759 					      "a{sv}", &variant_iter))
1760 		goto nomem;
1761 
1762 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1763 		goto nomem;
1764 
1765 	res = wpa_drv_get_capa(wpa_s, &capa);
1766 
1767 	/***** pairwise cipher */
1768 	if (res < 0) {
1769 		const char *args[] = {"ccmp", "tkip", "none"};
1770 		if (!wpa_dbus_dict_append_string_array(
1771 			    &iter_dict, "Pairwise", args,
1772 			    sizeof(args) / sizeof(char*)))
1773 			goto nomem;
1774 	} else {
1775 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1776 						      &iter_dict_entry,
1777 						      &iter_dict_val,
1778 						      &iter_array))
1779 			goto nomem;
1780 
1781 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1782 			if (!wpa_dbus_dict_string_array_add_element(
1783 				    &iter_array, "ccmp"))
1784 				goto nomem;
1785 		}
1786 
1787 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1788 			if (!wpa_dbus_dict_string_array_add_element(
1789 				    &iter_array, "tkip"))
1790 				goto nomem;
1791 		}
1792 
1793 		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1794 			if (!wpa_dbus_dict_string_array_add_element(
1795 				    &iter_array, "none"))
1796 				goto nomem;
1797 		}
1798 
1799 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
1800 						    &iter_dict_entry,
1801 						    &iter_dict_val,
1802 						    &iter_array))
1803 			goto nomem;
1804 	}
1805 
1806 	/***** group cipher */
1807 	if (res < 0) {
1808 		const char *args[] = {
1809 			"ccmp", "tkip", "wep104", "wep40"
1810 		};
1811 		if (!wpa_dbus_dict_append_string_array(
1812 			    &iter_dict, "Group", args,
1813 			    sizeof(args) / sizeof(char*)))
1814 			goto nomem;
1815 	} else {
1816 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1817 						      &iter_dict_entry,
1818 						      &iter_dict_val,
1819 						      &iter_array))
1820 			goto nomem;
1821 
1822 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1823 			if (!wpa_dbus_dict_string_array_add_element(
1824 				    &iter_array, "ccmp"))
1825 				goto nomem;
1826 		}
1827 
1828 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1829 			if (!wpa_dbus_dict_string_array_add_element(
1830 				    &iter_array, "tkip"))
1831 				goto nomem;
1832 		}
1833 
1834 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1835 			if (!wpa_dbus_dict_string_array_add_element(
1836 				    &iter_array, "wep104"))
1837 				goto nomem;
1838 		}
1839 
1840 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1841 			if (!wpa_dbus_dict_string_array_add_element(
1842 				    &iter_array, "wep40"))
1843 				goto nomem;
1844 		}
1845 
1846 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
1847 						    &iter_dict_entry,
1848 						    &iter_dict_val,
1849 						    &iter_array))
1850 			goto nomem;
1851 	}
1852 
1853 	/***** key management */
1854 	if (res < 0) {
1855 		const char *args[] = {
1856 			"wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1857 #ifdef CONFIG_WPS
1858 			"wps",
1859 #endif /* CONFIG_WPS */
1860 			"none"
1861 		};
1862 		if (!wpa_dbus_dict_append_string_array(
1863 			    &iter_dict, "KeyMgmt", args,
1864 			    sizeof(args) / sizeof(char*)))
1865 			goto nomem;
1866 	} else {
1867 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1868 						      &iter_dict_entry,
1869 						      &iter_dict_val,
1870 						      &iter_array))
1871 			goto nomem;
1872 
1873 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1874 							    "none"))
1875 			goto nomem;
1876 
1877 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1878 							    "ieee8021x"))
1879 			goto nomem;
1880 
1881 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1882 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1883 			if (!wpa_dbus_dict_string_array_add_element(
1884 				    &iter_array, "wpa-eap"))
1885 				goto nomem;
1886 
1887 			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
1888 				if (!wpa_dbus_dict_string_array_add_element(
1889 					    &iter_array, "wpa-ft-eap"))
1890 					goto nomem;
1891 
1892 /* TODO: Ensure that driver actually supports sha256 encryption. */
1893 #ifdef CONFIG_IEEE80211W
1894 			if (!wpa_dbus_dict_string_array_add_element(
1895 				    &iter_array, "wpa-eap-sha256"))
1896 				goto nomem;
1897 #endif /* CONFIG_IEEE80211W */
1898 		}
1899 
1900 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1901 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1902 			if (!wpa_dbus_dict_string_array_add_element(
1903 				    &iter_array, "wpa-psk"))
1904 				goto nomem;
1905 
1906 			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
1907 				if (!wpa_dbus_dict_string_array_add_element(
1908 					    &iter_array, "wpa-ft-psk"))
1909 					goto nomem;
1910 
1911 /* TODO: Ensure that driver actually supports sha256 encryption. */
1912 #ifdef CONFIG_IEEE80211W
1913 			if (!wpa_dbus_dict_string_array_add_element(
1914 				    &iter_array, "wpa-psk-sha256"))
1915 				goto nomem;
1916 #endif /* CONFIG_IEEE80211W */
1917 		}
1918 
1919 		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1920 			if (!wpa_dbus_dict_string_array_add_element(
1921 				    &iter_array, "wpa-none"))
1922 				goto nomem;
1923 		}
1924 
1925 
1926 #ifdef CONFIG_WPS
1927 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1928 							    "wps"))
1929 			goto nomem;
1930 #endif /* CONFIG_WPS */
1931 
1932 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
1933 						    &iter_dict_entry,
1934 						    &iter_dict_val,
1935 						    &iter_array))
1936 			goto nomem;
1937 	}
1938 
1939 	/***** WPA protocol */
1940 	if (res < 0) {
1941 		const char *args[] = { "rsn", "wpa" };
1942 		if (!wpa_dbus_dict_append_string_array(
1943 			    &iter_dict, "Protocol", args,
1944 			    sizeof(args) / sizeof(char*)))
1945 			goto nomem;
1946 	} else {
1947 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1948 						      &iter_dict_entry,
1949 						      &iter_dict_val,
1950 						      &iter_array))
1951 			goto nomem;
1952 
1953 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1954 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1955 			if (!wpa_dbus_dict_string_array_add_element(
1956 				    &iter_array, "rsn"))
1957 				goto nomem;
1958 		}
1959 
1960 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1961 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1962 			if (!wpa_dbus_dict_string_array_add_element(
1963 				    &iter_array, "wpa"))
1964 				goto nomem;
1965 		}
1966 
1967 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
1968 						    &iter_dict_entry,
1969 						    &iter_dict_val,
1970 						    &iter_array))
1971 			goto nomem;
1972 	}
1973 
1974 	/***** auth alg */
1975 	if (res < 0) {
1976 		const char *args[] = { "open", "shared", "leap" };
1977 		if (!wpa_dbus_dict_append_string_array(
1978 			    &iter_dict, "AuthAlg", args,
1979 			    sizeof(args) / sizeof(char*)))
1980 			goto nomem;
1981 	} else {
1982 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1983 						      &iter_dict_entry,
1984 						      &iter_dict_val,
1985 						      &iter_array))
1986 			goto nomem;
1987 
1988 		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1989 			if (!wpa_dbus_dict_string_array_add_element(
1990 				    &iter_array, "open"))
1991 				goto nomem;
1992 		}
1993 
1994 		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1995 			if (!wpa_dbus_dict_string_array_add_element(
1996 				    &iter_array, "shared"))
1997 				goto nomem;
1998 		}
1999 
2000 		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
2001 			if (!wpa_dbus_dict_string_array_add_element(
2002 				    &iter_array, "leap"))
2003 				goto nomem;
2004 		}
2005 
2006 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
2007 						    &iter_dict_entry,
2008 						    &iter_dict_val,
2009 						    &iter_array))
2010 			goto nomem;
2011 	}
2012 
2013 	/***** Scan */
2014 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2015 					       sizeof(scans) / sizeof(char *)))
2016 		goto nomem;
2017 
2018 	/***** Modes */
2019 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2020 					      &iter_dict_entry,
2021 					      &iter_dict_val,
2022 					      &iter_array))
2023 		goto nomem;
2024 
2025 	if (!wpa_dbus_dict_string_array_add_element(
2026 			    &iter_array, "infrastructure"))
2027 		goto nomem;
2028 
2029 	if (!wpa_dbus_dict_string_array_add_element(
2030 			    &iter_array, "ad-hoc"))
2031 		goto nomem;
2032 
2033 	if (res >= 0) {
2034 		if (capa.flags & (WPA_DRIVER_FLAGS_AP)) {
2035 			if (!wpa_dbus_dict_string_array_add_element(
2036 				    &iter_array, "ap"))
2037 				goto nomem;
2038 		}
2039 
2040 		if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) {
2041 			if (!wpa_dbus_dict_string_array_add_element(
2042 				    &iter_array, "p2p"))
2043 				goto nomem;
2044 		}
2045 	}
2046 
2047 	if (!wpa_dbus_dict_end_string_array(&iter_dict,
2048 					    &iter_dict_entry,
2049 					    &iter_dict_val,
2050 					    &iter_array))
2051 		goto nomem;
2052 	/***** Modes end */
2053 
2054 	if (res >= 0) {
2055 		dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2056 
2057 		if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2058 						max_scan_ssid))
2059 			goto nomem;
2060 	}
2061 
2062 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
2063 		goto nomem;
2064 	if (!dbus_message_iter_close_container(iter, &variant_iter))
2065 		goto nomem;
2066 
2067 	return TRUE;
2068 
2069 nomem:
2070 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2071 	return FALSE;
2072 }
2073 
2074 
2075 /**
2076  * wpas_dbus_getter_state - Get interface state
2077  * @iter: Pointer to incoming dbus message iter
2078  * @error: Location to store error on failure
2079  * @user_data: Function specific data
2080  * Returns: TRUE on success, FALSE on failure
2081  *
2082  * Getter for "State" property.
2083  */
wpas_dbus_getter_state(DBusMessageIter * iter,DBusError * error,void * user_data)2084 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2085 				   void *user_data)
2086 {
2087 	struct wpa_supplicant *wpa_s = user_data;
2088 	const char *str_state;
2089 	char *state_ls, *tmp;
2090 	dbus_bool_t success = FALSE;
2091 
2092 	str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2093 
2094 	/* make state string lowercase to fit new DBus API convention
2095 	 */
2096 	state_ls = tmp = os_strdup(str_state);
2097 	if (!tmp) {
2098 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2099 		return FALSE;
2100 	}
2101 	while (*tmp) {
2102 		*tmp = tolower(*tmp);
2103 		tmp++;
2104 	}
2105 
2106 	success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2107 						   &state_ls, error);
2108 
2109 	os_free(state_ls);
2110 
2111 	return success;
2112 }
2113 
2114 
2115 /**
2116  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2117  * @iter: Pointer to incoming dbus message iter
2118  * @error: Location to store error on failure
2119  * @user_data: Function specific data
2120  * Returns: TRUE on success, FALSE on failure
2121  *
2122  * Getter for "scanning" property.
2123  */
wpas_dbus_getter_scanning(DBusMessageIter * iter,DBusError * error,void * user_data)2124 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2125                                       void *user_data)
2126 {
2127 	struct wpa_supplicant *wpa_s = user_data;
2128 	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2129 
2130 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2131 						&scanning, error);
2132 }
2133 
2134 
2135 /**
2136  * wpas_dbus_getter_ap_scan - Control roaming mode
2137  * @iter: Pointer to incoming dbus message iter
2138  * @error: Location to store error on failure
2139  * @user_data: Function specific data
2140  * Returns: TRUE on success, FALSE on failure
2141  *
2142  * Getter function for "ApScan" property.
2143  */
wpas_dbus_getter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2144 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2145 				     void *user_data)
2146 {
2147 	struct wpa_supplicant *wpa_s = user_data;
2148 	dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2149 
2150 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2151 						&ap_scan, error);
2152 }
2153 
2154 
2155 /**
2156  * wpas_dbus_setter_ap_scan - Control roaming mode
2157  * @iter: Pointer to incoming dbus message iter
2158  * @error: Location to store error on failure
2159  * @user_data: Function specific data
2160  * Returns: TRUE on success, FALSE on failure
2161  *
2162  * Setter function for "ApScan" property.
2163  */
wpas_dbus_setter_ap_scan(DBusMessageIter * iter,DBusError * error,void * user_data)2164 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2165 				     void *user_data)
2166 {
2167 	struct wpa_supplicant *wpa_s = user_data;
2168 	dbus_uint32_t ap_scan;
2169 
2170 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2171 					      &ap_scan))
2172 		return FALSE;
2173 
2174 	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2175 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2176 				     "ap_scan must be 0, 1, or 2");
2177 		return FALSE;
2178 	}
2179 	return TRUE;
2180 }
2181 
2182 
2183 /**
2184  * wpas_dbus_getter_fast_reauth - Control fast
2185  * reauthentication (TLS session resumption)
2186  * @iter: Pointer to incoming dbus message iter
2187  * @error: Location to store error on failure
2188  * @user_data: Function specific data
2189  * Returns: TRUE on success, FALSE on failure
2190  *
2191  * Getter function for "FastReauth" property.
2192  */
wpas_dbus_getter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2193 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2194 					 DBusError *error,
2195 					 void *user_data)
2196 {
2197 	struct wpa_supplicant *wpa_s = user_data;
2198 	dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2199 
2200 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2201 						&fast_reauth, error);
2202 }
2203 
2204 
2205 /**
2206  * wpas_dbus_setter_fast_reauth - Control fast
2207  * reauthentication (TLS session resumption)
2208  * @iter: Pointer to incoming dbus message iter
2209  * @error: Location to store error on failure
2210  * @user_data: Function specific data
2211  * Returns: TRUE on success, FALSE on failure
2212  *
2213  * Setter function for "FastReauth" property.
2214  */
wpas_dbus_setter_fast_reauth(DBusMessageIter * iter,DBusError * error,void * user_data)2215 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2216 				     DBusError *error,
2217 				     void *user_data)
2218 {
2219 	struct wpa_supplicant *wpa_s = user_data;
2220 	dbus_bool_t fast_reauth;
2221 
2222 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2223 					      &fast_reauth))
2224 		return FALSE;
2225 
2226 	wpa_s->conf->fast_reauth = fast_reauth;
2227 	return TRUE;
2228 }
2229 
2230 
2231 /**
2232  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2233  * @iter: Pointer to incoming dbus message iter
2234  * @error: Location to store error on failure
2235  * @user_data: Function specific data
2236  * Returns: TRUE on success, FALSE on failure
2237  *
2238  * Getter function for "BSSExpireAge" property.
2239  */
wpas_dbus_getter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2240 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2241 					    DBusError *error,
2242 					    void *user_data)
2243 {
2244 	struct wpa_supplicant *wpa_s = user_data;
2245 	dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2246 
2247 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2248 						&expire_age, error);
2249 }
2250 
2251 
2252 /**
2253  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2254  * @iter: Pointer to incoming dbus message iter
2255  * @error: Location to store error on failure
2256  * @user_data: Function specific data
2257  * Returns: TRUE on success, FALSE on failure
2258  *
2259  * Setter function for "BSSExpireAge" property.
2260  */
wpas_dbus_setter_bss_expire_age(DBusMessageIter * iter,DBusError * error,void * user_data)2261 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2262 					    DBusError *error,
2263 					    void *user_data)
2264 {
2265 	struct wpa_supplicant *wpa_s = user_data;
2266 	dbus_uint32_t expire_age;
2267 
2268 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2269 					      &expire_age))
2270 		return FALSE;
2271 
2272 	if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2273 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2274 				     "BSSExpireAge must be >= 10");
2275 		return FALSE;
2276 	}
2277 	return TRUE;
2278 }
2279 
2280 
2281 /**
2282  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2283  * @iter: Pointer to incoming dbus message iter
2284  * @error: Location to store error on failure
2285  * @user_data: Function specific data
2286  * Returns: TRUE on success, FALSE on failure
2287  *
2288  * Getter function for "BSSExpireCount" property.
2289  */
wpas_dbus_getter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2290 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2291 					      DBusError *error,
2292 					      void *user_data)
2293 {
2294 	struct wpa_supplicant *wpa_s = user_data;
2295 	dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_age;
2296 
2297 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2298 						&expire_count, error);
2299 }
2300 
2301 
2302 /**
2303  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2304  * @iter: Pointer to incoming dbus message iter
2305  * @error: Location to store error on failure
2306  * @user_data: Function specific data
2307  * Returns: TRUE on success, FALSE on failure
2308  *
2309  * Setter function for "BSSExpireCount" property.
2310  */
wpas_dbus_setter_bss_expire_count(DBusMessageIter * iter,DBusError * error,void * user_data)2311 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2312 					      DBusError *error,
2313 					      void *user_data)
2314 {
2315 	struct wpa_supplicant *wpa_s = user_data;
2316 	dbus_uint32_t expire_count;
2317 
2318 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2319 					      &expire_count))
2320 		return FALSE;
2321 
2322 	if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2323 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2324 				     "BSSExpireCount must be > 0");
2325 		return FALSE;
2326 	}
2327 	return TRUE;
2328 }
2329 
2330 
2331 /**
2332  * wpas_dbus_getter_country - Control country code
2333  * @iter: Pointer to incoming dbus message iter
2334  * @error: Location to store error on failure
2335  * @user_data: Function specific data
2336  * Returns: TRUE on success, FALSE on failure
2337  *
2338  * Getter function for "Country" property.
2339  */
wpas_dbus_getter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2340 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2341 				     void *user_data)
2342 {
2343 	struct wpa_supplicant *wpa_s = user_data;
2344 	char country[3];
2345 	char *str = country;
2346 
2347 	country[0] = wpa_s->conf->country[0];
2348 	country[1] = wpa_s->conf->country[1];
2349 	country[2] = '\0';
2350 
2351 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2352 						&str, error);
2353 }
2354 
2355 
2356 /**
2357  * wpas_dbus_setter_country - Control country code
2358  * @iter: Pointer to incoming dbus message iter
2359  * @error: Location to store error on failure
2360  * @user_data: Function specific data
2361  * Returns: TRUE on success, FALSE on failure
2362  *
2363  * Setter function for "Country" property.
2364  */
wpas_dbus_setter_country(DBusMessageIter * iter,DBusError * error,void * user_data)2365 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2366 				     void *user_data)
2367 {
2368 	struct wpa_supplicant *wpa_s = user_data;
2369 	const char *country;
2370 
2371 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2372 					      &country))
2373 		return FALSE;
2374 
2375 	if (!country[0] || !country[1]) {
2376 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2377 				     "invalid country code");
2378 		return FALSE;
2379 	}
2380 
2381 	if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2382 		wpa_printf(MSG_DEBUG, "Failed to set country");
2383 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
2384 				     "failed to set country code");
2385 		return FALSE;
2386 	}
2387 
2388 	wpa_s->conf->country[0] = country[0];
2389 	wpa_s->conf->country[1] = country[1];
2390 	return TRUE;
2391 }
2392 
2393 
2394 /**
2395  * wpas_dbus_getter_ifname - Get interface name
2396  * @iter: Pointer to incoming dbus message iter
2397  * @error: Location to store error on failure
2398  * @user_data: Function specific data
2399  * Returns: TRUE on success, FALSE on failure
2400  *
2401  * Getter for "Ifname" property.
2402  */
wpas_dbus_getter_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)2403 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2404 				    void *user_data)
2405 {
2406 	struct wpa_supplicant *wpa_s = user_data;
2407 	const char *ifname = wpa_s->ifname;
2408 
2409 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2410 						&ifname, error);
2411 }
2412 
2413 
2414 /**
2415  * wpas_dbus_getter_driver - Get interface name
2416  * @iter: Pointer to incoming dbus message iter
2417  * @error: Location to store error on failure
2418  * @user_data: Function specific data
2419  * Returns: TRUE on success, FALSE on failure
2420  *
2421  * Getter for "Driver" property.
2422  */
wpas_dbus_getter_driver(DBusMessageIter * iter,DBusError * error,void * user_data)2423 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2424 				    void *user_data)
2425 {
2426 	struct wpa_supplicant *wpa_s = user_data;
2427 	const char *driver;
2428 
2429 	if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2430 		wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2431 			   "wpa_s has no driver set");
2432 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
2433 			       __func__);
2434 		return FALSE;
2435 	}
2436 
2437 	driver = wpa_s->driver->name;
2438 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2439 						&driver, error);
2440 }
2441 
2442 
2443 /**
2444  * wpas_dbus_getter_current_bss - Get current bss object path
2445  * @iter: Pointer to incoming dbus message iter
2446  * @error: Location to store error on failure
2447  * @user_data: Function specific data
2448  * Returns: TRUE on success, FALSE on failure
2449  *
2450  * Getter for "CurrentBSS" property.
2451  */
wpas_dbus_getter_current_bss(DBusMessageIter * iter,DBusError * error,void * user_data)2452 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
2453 					 DBusError *error,
2454 					 void *user_data)
2455 {
2456 	struct wpa_supplicant *wpa_s = user_data;
2457 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2458 
2459 	if (wpa_s->current_bss)
2460 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2461 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2462 			    wpa_s->dbus_new_path, wpa_s->current_bss->id);
2463 	else
2464 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2465 
2466 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2467 						&bss_obj_path, error);
2468 }
2469 
2470 
2471 /**
2472  * wpas_dbus_getter_current_network - Get current network object path
2473  * @iter: Pointer to incoming dbus message iter
2474  * @error: Location to store error on failure
2475  * @user_data: Function specific data
2476  * Returns: TRUE on success, FALSE on failure
2477  *
2478  * Getter for "CurrentNetwork" property.
2479  */
wpas_dbus_getter_current_network(DBusMessageIter * iter,DBusError * error,void * user_data)2480 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
2481 					     DBusError *error,
2482 					     void *user_data)
2483 {
2484 	struct wpa_supplicant *wpa_s = user_data;
2485 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2486 
2487 	if (wpa_s->current_ssid)
2488 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2489 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2490 			    wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2491 	else
2492 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2493 
2494 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
2495 						&net_obj_path, error);
2496 }
2497 
2498 
2499 /**
2500  * wpas_dbus_getter_current_auth_mode - Get current authentication type
2501  * @iter: Pointer to incoming dbus message iter
2502  * @error: Location to store error on failure
2503  * @user_data: Function specific data
2504  * Returns: TRUE on success, FALSE on failure
2505  *
2506  * Getter for "CurrentAuthMode" property.
2507  */
wpas_dbus_getter_current_auth_mode(DBusMessageIter * iter,DBusError * error,void * user_data)2508 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
2509 					       DBusError *error,
2510 					       void *user_data)
2511 {
2512 	struct wpa_supplicant *wpa_s = user_data;
2513 	const char *eap_mode;
2514 	const char *auth_mode;
2515 	char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
2516 
2517 	if (wpa_s->wpa_state != WPA_COMPLETED) {
2518 		auth_mode = "INACTIVE";
2519 	} else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
2520 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2521 		eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
2522 		os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
2523 			    "EAP-%s", eap_mode);
2524 		auth_mode = eap_mode_buf;
2525 
2526 	} else {
2527 		auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
2528 					     wpa_s->current_ssid->proto);
2529 	}
2530 
2531 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2532 						&auth_mode, error);
2533 }
2534 
2535 
2536 /**
2537  * wpas_dbus_getter_bridge_ifname - Get interface name
2538  * @iter: Pointer to incoming dbus message iter
2539  * @error: Location to store error on failure
2540  * @user_data: Function specific data
2541  * Returns: TRUE on success, FALSE on failure
2542  *
2543  * Getter for "BridgeIfname" property.
2544  */
wpas_dbus_getter_bridge_ifname(DBusMessageIter * iter,DBusError * error,void * user_data)2545 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
2546 					   DBusError *error,
2547 					   void *user_data)
2548 {
2549 	struct wpa_supplicant *wpa_s = user_data;
2550 	const char *bridge_ifname = wpa_s->bridge_ifname;
2551 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2552 						&bridge_ifname, error);
2553 }
2554 
2555 
2556 /**
2557  * wpas_dbus_getter_bsss - Get array of BSSs objects
2558  * @iter: Pointer to incoming dbus message iter
2559  * @error: Location to store error on failure
2560  * @user_data: Function specific data
2561  * Returns: TRUE on success, FALSE on failure
2562  *
2563  * Getter for "BSSs" property.
2564  */
wpas_dbus_getter_bsss(DBusMessageIter * iter,DBusError * error,void * user_data)2565 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
2566 				  void *user_data)
2567 {
2568 	struct wpa_supplicant *wpa_s = user_data;
2569 	struct wpa_bss *bss;
2570 	char **paths;
2571 	unsigned int i = 0;
2572 	dbus_bool_t success = FALSE;
2573 
2574 	paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
2575 	if (!paths) {
2576 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2577 		return FALSE;
2578 	}
2579 
2580 	/* Loop through scan results and append each result's object path */
2581 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2582 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2583 		if (paths[i] == NULL) {
2584 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2585 					     "no memory");
2586 			goto out;
2587 		}
2588 		/* Construct the object path for this BSS. */
2589 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2590 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2591 			    wpa_s->dbus_new_path, bss->id);
2592 	}
2593 
2594 	success = wpas_dbus_simple_array_property_getter(iter,
2595 							 DBUS_TYPE_OBJECT_PATH,
2596 							 paths, wpa_s->num_bss,
2597 							 error);
2598 
2599 out:
2600 	while (i)
2601 		os_free(paths[--i]);
2602 	os_free(paths);
2603 	return success;
2604 }
2605 
2606 
2607 /**
2608  * wpas_dbus_getter_networks - Get array of networks objects
2609  * @iter: Pointer to incoming dbus message iter
2610  * @error: Location to store error on failure
2611  * @user_data: Function specific data
2612  * Returns: TRUE on success, FALSE on failure
2613  *
2614  * Getter for "Networks" property.
2615  */
wpas_dbus_getter_networks(DBusMessageIter * iter,DBusError * error,void * user_data)2616 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
2617 				      void *user_data)
2618 {
2619 	struct wpa_supplicant *wpa_s = user_data;
2620 	struct wpa_ssid *ssid;
2621 	char **paths;
2622 	unsigned int i = 0, num = 0;
2623 	dbus_bool_t success = FALSE;
2624 
2625 	if (wpa_s->conf == NULL) {
2626 		wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting "
2627 			   "networks list.", __func__);
2628 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error "
2629 			       "occurred getting the networks list", __func__);
2630 		return FALSE;
2631 	}
2632 
2633 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2634 		if (!network_is_persistent_group(ssid))
2635 			num++;
2636 
2637 	paths = os_zalloc(num * sizeof(char *));
2638 	if (!paths) {
2639 		dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2640 		return FALSE;
2641 	}
2642 
2643 	/* Loop through configured networks and append object path of each */
2644 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2645 		if (network_is_persistent_group(ssid))
2646 			continue;
2647 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2648 		if (paths[i] == NULL) {
2649 			dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
2650 			goto out;
2651 		}
2652 
2653 		/* Construct the object path for this network. */
2654 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2655 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2656 			    wpa_s->dbus_new_path, ssid->id);
2657 	}
2658 
2659 	success = wpas_dbus_simple_array_property_getter(iter,
2660 							 DBUS_TYPE_OBJECT_PATH,
2661 							 paths, num, error);
2662 
2663 out:
2664 	while (i)
2665 		os_free(paths[--i]);
2666 	os_free(paths);
2667 	return success;
2668 }
2669 
2670 
2671 /**
2672  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2673  * @iter: Pointer to incoming dbus message iter
2674  * @error: Location to store error on failure
2675  * @user_data: Function specific data
2676  * Returns: TRUE on success, FALSE on failure
2677  *
2678  * Getter for "Blobs" property.
2679  */
wpas_dbus_getter_blobs(DBusMessageIter * iter,DBusError * error,void * user_data)2680 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
2681 				   void *user_data)
2682 {
2683 	struct wpa_supplicant *wpa_s = user_data;
2684 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
2685 	struct wpa_config_blob *blob;
2686 
2687 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2688 					      "a{say}", &variant_iter) ||
2689 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2690 					      "{say}", &dict_iter)) {
2691 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2692 		return FALSE;
2693 	}
2694 
2695 	blob = wpa_s->conf->blobs;
2696 	while (blob) {
2697 		if (!dbus_message_iter_open_container(&dict_iter,
2698 						      DBUS_TYPE_DICT_ENTRY,
2699 						      NULL, &entry_iter) ||
2700 		    !dbus_message_iter_append_basic(&entry_iter,
2701 						    DBUS_TYPE_STRING,
2702 						    &(blob->name)) ||
2703 		    !dbus_message_iter_open_container(&entry_iter,
2704 						      DBUS_TYPE_ARRAY,
2705 						      DBUS_TYPE_BYTE_AS_STRING,
2706 						      &array_iter) ||
2707 		    !dbus_message_iter_append_fixed_array(&array_iter,
2708 							  DBUS_TYPE_BYTE,
2709 							  &(blob->data),
2710 							  blob->len) ||
2711 		    !dbus_message_iter_close_container(&entry_iter,
2712 						       &array_iter) ||
2713 		    !dbus_message_iter_close_container(&dict_iter,
2714 						       &entry_iter)) {
2715 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2716 					     "no memory");
2717 			return FALSE;
2718 		}
2719 
2720 		blob = blob->next;
2721 	}
2722 
2723 	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2724 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
2725 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2726 		return FALSE;
2727 	}
2728 
2729 	return TRUE;
2730 }
2731 
2732 
get_bss_helper(struct bss_handler_args * args,DBusError * error,const char * func_name)2733 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
2734 				       DBusError *error, const char *func_name)
2735 {
2736 	struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
2737 
2738 	if (!res) {
2739 		wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
2740 		           func_name, args->id);
2741 		dbus_set_error(error, DBUS_ERROR_FAILED,
2742 			       "%s: BSS %d not found",
2743 			       func_name, args->id);
2744 	}
2745 
2746 	return res;
2747 }
2748 
2749 
2750 /**
2751  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
2752  * @iter: Pointer to incoming dbus message iter
2753  * @error: Location to store error on failure
2754  * @user_data: Function specific data
2755  * Returns: TRUE on success, FALSE on failure
2756  *
2757  * Getter for "BSSID" property.
2758  */
wpas_dbus_getter_bss_bssid(DBusMessageIter * iter,DBusError * error,void * user_data)2759 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
2760 				       void *user_data)
2761 {
2762 	struct bss_handler_args *args = user_data;
2763 	struct wpa_bss *res;
2764 
2765 	res = get_bss_helper(args, error, __func__);
2766 	if (!res)
2767 		return FALSE;
2768 
2769 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2770 						      res->bssid, ETH_ALEN,
2771 						      error);
2772 }
2773 
2774 
2775 /**
2776  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
2777  * @iter: Pointer to incoming dbus message iter
2778  * @error: Location to store error on failure
2779  * @user_data: Function specific data
2780  * Returns: TRUE on success, FALSE on failure
2781  *
2782  * Getter for "SSID" property.
2783  */
wpas_dbus_getter_bss_ssid(DBusMessageIter * iter,DBusError * error,void * user_data)2784 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
2785 				      void *user_data)
2786 {
2787 	struct bss_handler_args *args = user_data;
2788 	struct wpa_bss *res;
2789 
2790 	res = get_bss_helper(args, error, __func__);
2791 	if (!res)
2792 		return FALSE;
2793 
2794 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2795 						      res->ssid, res->ssid_len,
2796 						      error);
2797 }
2798 
2799 
2800 /**
2801  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
2802  * @iter: Pointer to incoming dbus message iter
2803  * @error: Location to store error on failure
2804  * @user_data: Function specific data
2805  * Returns: TRUE on success, FALSE on failure
2806  *
2807  * Getter for "Privacy" property.
2808  */
wpas_dbus_getter_bss_privacy(DBusMessageIter * iter,DBusError * error,void * user_data)2809 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
2810 					 DBusError *error, void *user_data)
2811 {
2812 	struct bss_handler_args *args = user_data;
2813 	struct wpa_bss *res;
2814 	dbus_bool_t privacy;
2815 
2816 	res = get_bss_helper(args, error, __func__);
2817 	if (!res)
2818 		return FALSE;
2819 
2820 	privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
2821 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2822 						&privacy, error);
2823 }
2824 
2825 
2826 /**
2827  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
2828  * @iter: Pointer to incoming dbus message iter
2829  * @error: Location to store error on failure
2830  * @user_data: Function specific data
2831  * Returns: TRUE on success, FALSE on failure
2832  *
2833  * Getter for "Mode" property.
2834  */
wpas_dbus_getter_bss_mode(DBusMessageIter * iter,DBusError * error,void * user_data)2835 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
2836 				      void *user_data)
2837 {
2838 	struct bss_handler_args *args = user_data;
2839 	struct wpa_bss *res;
2840 	const char *mode;
2841 
2842 	res = get_bss_helper(args, error, __func__);
2843 	if (!res)
2844 		return FALSE;
2845 
2846 	if (res->caps & IEEE80211_CAP_IBSS)
2847 		mode = "ad-hoc";
2848 	else
2849 		mode = "infrastructure";
2850 
2851 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2852 						&mode, error);
2853 }
2854 
2855 
2856 /**
2857  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
2858  * @iter: Pointer to incoming dbus message iter
2859  * @error: Location to store error on failure
2860  * @user_data: Function specific data
2861  * Returns: TRUE on success, FALSE on failure
2862  *
2863  * Getter for "Level" property.
2864  */
wpas_dbus_getter_bss_signal(DBusMessageIter * iter,DBusError * error,void * user_data)2865 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
2866 					DBusError *error, void *user_data)
2867 {
2868 	struct bss_handler_args *args = user_data;
2869 	struct wpa_bss *res;
2870 	s16 level;
2871 
2872 	res = get_bss_helper(args, error, __func__);
2873 	if (!res)
2874 		return FALSE;
2875 
2876 	level = (s16) res->level;
2877 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
2878 						&level, error);
2879 }
2880 
2881 
2882 /**
2883  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
2884  * @iter: Pointer to incoming dbus message iter
2885  * @error: Location to store error on failure
2886  * @user_data: Function specific data
2887  * Returns: TRUE on success, FALSE on failure
2888  *
2889  * Getter for "Frequency" property.
2890  */
wpas_dbus_getter_bss_frequency(DBusMessageIter * iter,DBusError * error,void * user_data)2891 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
2892 					   DBusError *error, void *user_data)
2893 {
2894 	struct bss_handler_args *args = user_data;
2895 	struct wpa_bss *res;
2896 	u16 freq;
2897 
2898 	res = get_bss_helper(args, error, __func__);
2899 	if (!res)
2900 		return FALSE;
2901 
2902 	freq = (u16) res->freq;
2903 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2904 						&freq, error);
2905 }
2906 
2907 
cmp_u8s_desc(const void * a,const void * b)2908 static int cmp_u8s_desc(const void *a, const void *b)
2909 {
2910 	return (*(u8 *) b - *(u8 *) a);
2911 }
2912 
2913 
2914 /**
2915  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
2916  * @iter: Pointer to incoming dbus message iter
2917  * @error: Location to store error on failure
2918  * @user_data: Function specific data
2919  * Returns: TRUE on success, FALSE on failure
2920  *
2921  * Getter for "Rates" property.
2922  */
wpas_dbus_getter_bss_rates(DBusMessageIter * iter,DBusError * error,void * user_data)2923 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
2924 				       DBusError *error, void *user_data)
2925 {
2926 	struct bss_handler_args *args = user_data;
2927 	struct wpa_bss *res;
2928 	u8 *ie_rates = NULL;
2929 	u32 *real_rates;
2930 	int rates_num, i;
2931 	dbus_bool_t success = FALSE;
2932 
2933 	res = get_bss_helper(args, error, __func__);
2934 	if (!res)
2935 		return FALSE;
2936 
2937 	rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
2938 	if (rates_num < 0)
2939 		return FALSE;
2940 
2941 	qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
2942 
2943 	real_rates = os_malloc(sizeof(u32) * rates_num);
2944 	if (!real_rates) {
2945 		os_free(ie_rates);
2946 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2947 		return FALSE;
2948 	}
2949 
2950 	for (i = 0; i < rates_num; i++)
2951 		real_rates[i] = ie_rates[i] * 500000;
2952 
2953 	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
2954 							 real_rates, rates_num,
2955 							 error);
2956 
2957 	os_free(ie_rates);
2958 	os_free(real_rates);
2959 	return success;
2960 }
2961 
2962 
wpas_dbus_get_bss_security_prop(DBusMessageIter * iter,struct wpa_ie_data * ie_data,DBusError * error)2963 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
2964 						   struct wpa_ie_data *ie_data,
2965 						   DBusError *error)
2966 {
2967 	DBusMessageIter iter_dict, variant_iter;
2968 	const char *group;
2969 	const char *pairwise[2]; /* max 2 pairwise ciphers is supported */
2970 	const char *key_mgmt[7]; /* max 7 key managements may be supported */
2971 	int n;
2972 
2973 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2974 					      "a{sv}", &variant_iter))
2975 		goto nomem;
2976 
2977 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2978 		goto nomem;
2979 
2980 	/* KeyMgmt */
2981 	n = 0;
2982 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
2983 		key_mgmt[n++] = "wpa-psk";
2984 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
2985 		key_mgmt[n++] = "wpa-ft-psk";
2986 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
2987 		key_mgmt[n++] = "wpa-psk-sha256";
2988 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
2989 		key_mgmt[n++] = "wpa-eap";
2990 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
2991 		key_mgmt[n++] = "wpa-ft-eap";
2992 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
2993 		key_mgmt[n++] = "wpa-eap-sha256";
2994 	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
2995 		key_mgmt[n++] = "wpa-none";
2996 
2997 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
2998 					       key_mgmt, n))
2999 		goto nomem;
3000 
3001 	/* Group */
3002 	switch (ie_data->group_cipher) {
3003 	case WPA_CIPHER_WEP40:
3004 		group = "wep40";
3005 		break;
3006 	case WPA_CIPHER_TKIP:
3007 		group = "tkip";
3008 		break;
3009 	case WPA_CIPHER_CCMP:
3010 		group = "ccmp";
3011 		break;
3012 	case WPA_CIPHER_WEP104:
3013 		group = "wep104";
3014 		break;
3015 	default:
3016 		group = "";
3017 		break;
3018 	}
3019 
3020 	if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3021 		goto nomem;
3022 
3023 	/* Pairwise */
3024 	n = 0;
3025 	if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3026 		pairwise[n++] = "tkip";
3027 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3028 		pairwise[n++] = "ccmp";
3029 
3030 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3031 					       pairwise, n))
3032 		goto nomem;
3033 
3034 	/* Management group (RSN only) */
3035 	if (ie_data->proto == WPA_PROTO_RSN) {
3036 		switch (ie_data->mgmt_group_cipher) {
3037 #ifdef CONFIG_IEEE80211W
3038 		case WPA_CIPHER_AES_128_CMAC:
3039 			group = "aes128cmac";
3040 			break;
3041 #endif /* CONFIG_IEEE80211W */
3042 		default:
3043 			group = "";
3044 			break;
3045 		}
3046 
3047 		if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3048 						 group))
3049 			goto nomem;
3050 	}
3051 
3052 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
3053 		goto nomem;
3054 	if (!dbus_message_iter_close_container(iter, &variant_iter))
3055 		goto nomem;
3056 
3057 	return TRUE;
3058 
3059 nomem:
3060 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3061 	return FALSE;
3062 }
3063 
3064 
3065 /**
3066  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3067  * @iter: Pointer to incoming dbus message iter
3068  * @error: Location to store error on failure
3069  * @user_data: Function specific data
3070  * Returns: TRUE on success, FALSE on failure
3071  *
3072  * Getter for "WPA" property.
3073  */
wpas_dbus_getter_bss_wpa(DBusMessageIter * iter,DBusError * error,void * user_data)3074 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3075 				     void *user_data)
3076 {
3077 	struct bss_handler_args *args = user_data;
3078 	struct wpa_bss *res;
3079 	struct wpa_ie_data wpa_data;
3080 	const u8 *ie;
3081 
3082 	res = get_bss_helper(args, error, __func__);
3083 	if (!res)
3084 		return FALSE;
3085 
3086 	os_memset(&wpa_data, 0, sizeof(wpa_data));
3087 	ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3088 	if (ie) {
3089 		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3090 			dbus_set_error_const(error, DBUS_ERROR_FAILED,
3091 					     "failed to parse WPA IE");
3092 			return FALSE;
3093 		}
3094 	}
3095 
3096 	return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3097 }
3098 
3099 
3100 /**
3101  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3102  * @iter: Pointer to incoming dbus message iter
3103  * @error: Location to store error on failure
3104  * @user_data: Function specific data
3105  * Returns: TRUE on success, FALSE on failure
3106  *
3107  * Getter for "RSN" property.
3108  */
wpas_dbus_getter_bss_rsn(DBusMessageIter * iter,DBusError * error,void * user_data)3109 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3110 				     void *user_data)
3111 {
3112 	struct bss_handler_args *args = user_data;
3113 	struct wpa_bss *res;
3114 	struct wpa_ie_data wpa_data;
3115 	const u8 *ie;
3116 
3117 	res = get_bss_helper(args, error, __func__);
3118 	if (!res)
3119 		return FALSE;
3120 
3121 	os_memset(&wpa_data, 0, sizeof(wpa_data));
3122 	ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3123 	if (ie) {
3124 		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3125 			dbus_set_error_const(error, DBUS_ERROR_FAILED,
3126 					     "failed to parse RSN IE");
3127 			return FALSE;
3128 		}
3129 	}
3130 
3131 	return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3132 }
3133 
3134 
3135 /**
3136  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3137  * @iter: Pointer to incoming dbus message iter
3138  * @error: Location to store error on failure
3139  * @user_data: Function specific data
3140  * Returns: TRUE on success, FALSE on failure
3141  *
3142  * Getter for "IEs" property.
3143  */
wpas_dbus_getter_bss_ies(DBusMessageIter * iter,DBusError * error,void * user_data)3144 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3145 				     void *user_data)
3146 {
3147 	struct bss_handler_args *args = user_data;
3148 	struct wpa_bss *res;
3149 
3150 	res = get_bss_helper(args, error, __func__);
3151 	if (!res)
3152 		return FALSE;
3153 
3154 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3155 						      res + 1, res->ie_len,
3156 						      error);
3157 }
3158 
3159 
3160 /**
3161  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3162  * @iter: Pointer to incoming dbus message iter
3163  * @error: Location to store error on failure
3164  * @user_data: Function specific data
3165  * Returns: TRUE on success, FALSE on failure
3166  *
3167  * Getter for "enabled" property of a configured network.
3168  */
wpas_dbus_getter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3169 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3170 				     void *user_data)
3171 {
3172 	struct network_handler_args *net = user_data;
3173 	dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3174 
3175 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3176 						&enabled, error);
3177 }
3178 
3179 
3180 /**
3181  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
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  * Setter for "Enabled" property of a configured network.
3188  */
wpas_dbus_setter_enabled(DBusMessageIter * iter,DBusError * error,void * user_data)3189 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3190 				     void *user_data)
3191 {
3192 	struct network_handler_args *net = user_data;
3193 	struct wpa_supplicant *wpa_s;
3194 	struct wpa_ssid *ssid;
3195 	dbus_bool_t enable;
3196 
3197 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3198 					      &enable))
3199 		return FALSE;
3200 
3201 	wpa_s = net->wpa_s;
3202 	ssid = net->ssid;
3203 
3204 	if (enable)
3205 		wpa_supplicant_enable_network(wpa_s, ssid);
3206 	else
3207 		wpa_supplicant_disable_network(wpa_s, ssid);
3208 
3209 	return TRUE;
3210 }
3211 
3212 
3213 /**
3214  * wpas_dbus_getter_network_properties - Get options for a configured network
3215  * @iter: Pointer to incoming dbus message iter
3216  * @error: Location to store error on failure
3217  * @user_data: Function specific data
3218  * Returns: TRUE on success, FALSE on failure
3219  *
3220  * Getter for "Properties" property of a configured network.
3221  */
wpas_dbus_getter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)3222 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3223 						DBusError *error,
3224 						void *user_data)
3225 {
3226 	struct network_handler_args *net = user_data;
3227 	DBusMessageIter	variant_iter, dict_iter;
3228 	char **iterator;
3229 	char **props = wpa_config_get_all(net->ssid, 1);
3230 	dbus_bool_t success = FALSE;
3231 
3232 	if (!props) {
3233 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3234 		return FALSE;
3235 	}
3236 
3237 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3238 					      &variant_iter) ||
3239 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3240 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3241 		goto out;
3242 	}
3243 
3244 	iterator = props;
3245 	while (*iterator) {
3246 		if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3247 						 *(iterator + 1))) {
3248 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3249 					     "no memory");
3250 			goto out;
3251 		}
3252 		iterator += 2;
3253 	}
3254 
3255 
3256 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3257 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
3258 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3259 		goto out;
3260 	}
3261 
3262 	success = TRUE;
3263 
3264 out:
3265 	iterator = props;
3266 	while (*iterator) {
3267 		os_free(*iterator);
3268 		iterator++;
3269 	}
3270 	os_free(props);
3271 	return success;
3272 }
3273 
3274 
3275 /**
3276  * wpas_dbus_setter_network_properties - Set options for a configured network
3277  * @iter: Pointer to incoming dbus message iter
3278  * @error: Location to store error on failure
3279  * @user_data: Function specific data
3280  * Returns: TRUE on success, FALSE on failure
3281  *
3282  * Setter for "Properties" property of a configured network.
3283  */
wpas_dbus_setter_network_properties(DBusMessageIter * iter,DBusError * error,void * user_data)3284 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
3285 						DBusError *error,
3286 						void *user_data)
3287 {
3288 	struct network_handler_args *net = user_data;
3289 	struct wpa_ssid *ssid = net->ssid;
3290 	DBusMessageIter	variant_iter;
3291 
3292 	dbus_message_iter_recurse(iter, &variant_iter);
3293 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
3294 }
3295