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