Home | History | Annotate | Download | only in dbus
      1 /*
      2  * WPA Supplicant / dbus-based control interface (WPS)
      3  * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc.
      4  * Copyright (c) 2009, Witold Sowa <witold.sowa (at) gmail.com>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License version 2 as
      8  * published by the Free Software Foundation.
      9  *
     10  * Alternatively, this software may be distributed under the terms of BSD
     11  * license.
     12  *
     13  * See README and COPYING for more details.
     14  */
     15 
     16 #include "includes.h"
     17 
     18 #include "common.h"
     19 #include "../config.h"
     20 #include "../wpa_supplicant_i.h"
     21 #include "../wps_supplicant.h"
     22 #include "../driver_i.h"
     23 #include "../ap.h"
     24 #include "dbus_new_helpers.h"
     25 #include "dbus_new.h"
     26 #include "dbus_new_handlers.h"
     27 #include "dbus_dict_helpers.h"
     28 
     29 
     30 struct wps_start_params {
     31 	int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
     32 	int type; /* 0 - not set, 1 - pin,      2 - pbc       */
     33 	u8 *bssid;
     34 	char *pin;
     35 	u8 *p2p_dev_addr;
     36 };
     37 
     38 
     39 static int wpas_dbus_handler_wps_role(DBusMessage *message,
     40 				      DBusMessageIter *entry_iter,
     41 				      struct wps_start_params *params,
     42 				      DBusMessage **reply)
     43 {
     44 	DBusMessageIter variant_iter;
     45 	char *val;
     46 
     47 	dbus_message_iter_recurse(entry_iter, &variant_iter);
     48 	if (dbus_message_iter_get_arg_type(&variant_iter) !=
     49 	    DBUS_TYPE_STRING) {
     50 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Role type, "
     51 			   "string required");
     52 		*reply = wpas_dbus_error_invalid_args(message,
     53 						      "Role must be a string");
     54 		return -1;
     55 	}
     56 	dbus_message_iter_get_basic(&variant_iter, &val);
     57 	if (os_strcmp(val, "enrollee") == 0)
     58 		params->role = 1;
     59 	else if (os_strcmp(val, "registrar") == 0)
     60 		params->role = 2;
     61 	else {
     62 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Uknown role %s", val);
     63 		*reply = wpas_dbus_error_invalid_args(message, val);
     64 		return -1;
     65 	}
     66 	return 0;
     67 }
     68 
     69 
     70 static int wpas_dbus_handler_wps_type(DBusMessage *message,
     71 				      DBusMessageIter *entry_iter,
     72 				      struct wps_start_params *params,
     73 				      DBusMessage **reply)
     74 {
     75 	DBusMessageIter variant_iter;
     76 	char *val;
     77 
     78 	dbus_message_iter_recurse(entry_iter, &variant_iter);
     79 	if (dbus_message_iter_get_arg_type(&variant_iter) !=
     80 	    DBUS_TYPE_STRING) {
     81 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Type type, "
     82 			   "string required");
     83 		*reply = wpas_dbus_error_invalid_args(message,
     84 						      "Type must be a string");
     85 		return -1;
     86 	}
     87 	dbus_message_iter_get_basic(&variant_iter, &val);
     88 	if (os_strcmp(val, "pin") == 0)
     89 		params->type = 1;
     90 	else if (os_strcmp(val, "pbc") == 0)
     91 		params->type = 2;
     92 	else {
     93 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
     94 			   val);
     95 		*reply = wpas_dbus_error_invalid_args(message, val);
     96 		return -1;
     97 	}
     98 	return 0;
     99 }
    100 
    101 
    102 static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
    103 				       DBusMessageIter *entry_iter,
    104 				       struct wps_start_params *params,
    105 				       DBusMessage **reply)
    106 {
    107 	DBusMessageIter variant_iter, array_iter;
    108 	int len;
    109 
    110 	dbus_message_iter_recurse(entry_iter, &variant_iter);
    111 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
    112 	    dbus_message_iter_get_element_type(&variant_iter) !=
    113 	    DBUS_TYPE_BYTE) {
    114 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid type, "
    115 			   "byte array required");
    116 		*reply = wpas_dbus_error_invalid_args(
    117 			message, "Bssid must be a byte array");
    118 		return -1;
    119 	}
    120 	dbus_message_iter_recurse(&variant_iter, &array_iter);
    121 	dbus_message_iter_get_fixed_array(&array_iter, &params->bssid, &len);
    122 	if (len != ETH_ALEN) {
    123 		wpa_printf(MSG_DEBUG, "dbus: WPS.Stsrt - Wrong Bssid length "
    124 			   "%d", len);
    125 		*reply = wpas_dbus_error_invalid_args(message,
    126 						      "Bssid is wrong length");
    127 		return -1;
    128 	}
    129 	return 0;
    130 }
    131 
    132 
    133 static int wpas_dbus_handler_wps_pin(DBusMessage *message,
    134 				     DBusMessageIter *entry_iter,
    135 				     struct wps_start_params *params,
    136 				     DBusMessage **reply)
    137 {
    138 	DBusMessageIter variant_iter;
    139 
    140 	dbus_message_iter_recurse(entry_iter, &variant_iter);
    141 	if (dbus_message_iter_get_arg_type(&variant_iter) !=
    142 	    DBUS_TYPE_STRING) {
    143 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Pin type, "
    144 			   "string required");
    145 		*reply = wpas_dbus_error_invalid_args(message,
    146 						      "Pin must be a string");
    147 		return -1;
    148 	}
    149 	dbus_message_iter_get_basic(&variant_iter, &params->pin);
    150 	return 0;
    151 }
    152 
    153 
    154 #ifdef CONFIG_P2P
    155 static int wpas_dbus_handler_wps_p2p_dev_addr(DBusMessage *message,
    156 					      DBusMessageIter *entry_iter,
    157 					      struct wps_start_params *params,
    158 					      DBusMessage **reply)
    159 {
    160 	DBusMessageIter variant_iter, array_iter;
    161 	int len;
    162 
    163 	dbus_message_iter_recurse(entry_iter, &variant_iter);
    164 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
    165 	    dbus_message_iter_get_element_type(&variant_iter) !=
    166 	    DBUS_TYPE_BYTE) {
    167 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong "
    168 			   "P2PDeviceAddress type, byte array required");
    169 		*reply = wpas_dbus_error_invalid_args(
    170 			message, "P2PDeviceAddress must be a byte array");
    171 		return -1;
    172 	}
    173 	dbus_message_iter_recurse(&variant_iter, &array_iter);
    174 	dbus_message_iter_get_fixed_array(&array_iter, &params->p2p_dev_addr,
    175 					  &len);
    176 	if (len != ETH_ALEN) {
    177 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong "
    178 			   "P2PDeviceAddress length %d", len);
    179 		*reply = wpas_dbus_error_invalid_args(message,
    180 						      "P2PDeviceAddress "
    181 						      "has wrong length");
    182 		return -1;
    183 	}
    184 	return 0;
    185 }
    186 #endif /* CONFIG_P2P */
    187 
    188 
    189 static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
    190 					     DBusMessageIter *entry_iter,
    191 					     struct wps_start_params *params,
    192 					     DBusMessage **reply)
    193 {
    194 	if (os_strcmp(key, "Role") == 0)
    195 		return wpas_dbus_handler_wps_role(message, entry_iter,
    196 						  params, reply);
    197 	else if (os_strcmp(key, "Type") == 0)
    198 		return wpas_dbus_handler_wps_type(message, entry_iter,
    199 						  params, reply);
    200 	else if (os_strcmp(key, "Bssid") == 0)
    201 		return wpas_dbus_handler_wps_bssid(message, entry_iter,
    202 						   params, reply);
    203 	else if (os_strcmp(key, "Pin") == 0)
    204 		return wpas_dbus_handler_wps_pin(message, entry_iter,
    205 						 params, reply);
    206 #ifdef CONFIG_P2P
    207 	else if (os_strcmp(key, "P2PDeviceAddress") == 0)
    208 		return wpas_dbus_handler_wps_p2p_dev_addr(message, entry_iter,
    209 							  params, reply);
    210 #endif /* CONFIG_P2P */
    211 
    212 	wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
    213 	*reply = wpas_dbus_error_invalid_args(message, key);
    214 	return -1;
    215 }
    216 
    217 
    218 /**
    219  * wpas_dbus_handler_wps_start - Start WPS configuration
    220  * @message: Pointer to incoming dbus message
    221  * @wpa_s: %wpa_supplicant data structure
    222  * Returns: DBus message dictionary on success or DBus error on failure
    223  *
    224  * Handler for "Start" method call. DBus dictionary argument contains
    225  * information about role (enrollee or registrar), authorization method
    226  * (pin or push button) and optionally pin and bssid. Returned message
    227  * has a dictionary argument which may contain newly generated pin (optional).
    228  */
    229 DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
    230 					  struct wpa_supplicant *wpa_s)
    231 {
    232 	DBusMessage *reply = NULL;
    233 	DBusMessageIter iter, dict_iter, entry_iter;
    234 	struct wps_start_params params;
    235 	char *key;
    236 	char npin[9] = { '\0' };
    237 	int ret;
    238 
    239 	os_memset(&params, 0, sizeof(params));
    240 	dbus_message_iter_init(message, &iter);
    241 
    242 	dbus_message_iter_recurse(&iter, &dict_iter);
    243 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
    244 	       DBUS_TYPE_DICT_ENTRY) {
    245 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
    246 
    247 		dbus_message_iter_get_basic(&entry_iter, &key);
    248 		dbus_message_iter_next(&entry_iter);
    249 
    250 		if (wpas_dbus_handler_wps_start_entry(message, key,
    251 						      &entry_iter,
    252 						      &params, &reply))
    253 			return reply;
    254 
    255 		dbus_message_iter_next(&dict_iter);
    256 	}
    257 
    258 	if (params.role == 0) {
    259 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
    260 		return wpas_dbus_error_invalid_args(message,
    261 						    "Role not specified");
    262 	} else if (params.role == 1 && params.type == 0) {
    263 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
    264 		return wpas_dbus_error_invalid_args(message,
    265 						    "Type not specified");
    266 	} else if (params.role == 2 && params.pin == NULL) {
    267 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Pin required for "
    268 			   "registrar role");
    269 		return wpas_dbus_error_invalid_args(
    270 			message, "Pin required for registrar role.");
    271 	}
    272 
    273 	if (params.role == 2)
    274 		ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
    275 					 NULL);
    276 	else if (params.type == 1) {
    277 #ifdef CONFIG_AP
    278 		if (wpa_s->ap_iface)
    279 			ret = wpa_supplicant_ap_wps_pin(wpa_s,
    280 							params.bssid,
    281 							params.pin,
    282 							npin, sizeof(npin));
    283 		else
    284 #endif /* CONFIG_AP */
    285 		{
    286 			ret = wpas_wps_start_pin(wpa_s, params.bssid,
    287 						 params.pin, 0,
    288 						 DEV_PW_DEFAULT);
    289 			if (ret > 0)
    290 				os_snprintf(npin, sizeof(npin), "%08d", ret);
    291 		}
    292 	} else {
    293 #ifdef CONFIG_AP
    294 		if (wpa_s->ap_iface)
    295 			ret = wpa_supplicant_ap_wps_pbc(wpa_s,
    296 							params.bssid,
    297 							params.p2p_dev_addr);
    298 		else
    299 #endif /* CONFIG_AP */
    300 		ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
    301 	}
    302 
    303 	if (ret < 0) {
    304 		wpa_printf(MSG_DEBUG, "dbus: WPS.Start wpas_wps_failed in "
    305 			   "role %s and key %s",
    306 			   (params.role == 1 ? "enrollee" : "registrar"),
    307 			   (params.type == 0 ? "" :
    308 			    (params.type == 1 ? "pin" : "pbc")));
    309 		return wpas_dbus_error_unknown_error(message,
    310 						     "WPS start failed");
    311 	}
    312 
    313 	reply = dbus_message_new_method_return(message);
    314 	if (!reply) {
    315 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
    316 					      NULL);
    317 	}
    318 
    319 	dbus_message_iter_init_append(reply, &iter);
    320 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
    321 		dbus_message_unref(reply);
    322 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
    323 					      NULL);
    324 	}
    325 
    326 	if (os_strlen(npin) > 0) {
    327 		if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
    328 			dbus_message_unref(reply);
    329 			return dbus_message_new_error(message,
    330 						      DBUS_ERROR_NO_MEMORY,
    331 						      NULL);
    332 		}
    333 	}
    334 
    335 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
    336 		dbus_message_unref(reply);
    337 		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
    338 					      NULL);
    339 	}
    340 
    341 	return reply;
    342 }
    343 
    344 
    345 /**
    346  * wpas_dbus_getter_process_credentials - Check if credentials are processed
    347  * @message: Pointer to incoming dbus message
    348  * @wpa_s: %wpa_supplicant data structure
    349  * Returns: TRUE on success, FALSE on failure
    350  *
    351  * Getter for "ProcessCredentials" property. Returns returned boolean will be
    352  * true if wps_cred_processing configuration field is not equal to 1 or false
    353  * if otherwise.
    354  */
    355 dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter,
    356 						 DBusError *error,
    357 						 void *user_data)
    358 {
    359 	struct wpa_supplicant *wpa_s = user_data;
    360 	dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
    361 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    362 						&process, error);
    363 }
    364 
    365 
    366 /**
    367  * wpas_dbus_setter_process_credentials - Set credentials_processed conf param
    368  * @iter: Pointer to incoming dbus message iter
    369  * @error: Location to store error on failure
    370  * @user_data: Function specific data
    371  * Returns: TRUE on success, FALSE on failure
    372  *
    373  * Setter for "ProcessCredentials" property. Sets credentials_processed on 2
    374  * if boolean argument is true or on 1 if otherwise.
    375  */
    376 dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
    377 						 DBusError *error,
    378 						 void *user_data)
    379 {
    380 	struct wpa_supplicant *wpa_s = user_data;
    381 	dbus_bool_t process_credentials, old_pc;
    382 
    383 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
    384 					      &process_credentials))
    385 		return FALSE;
    386 
    387 	old_pc = (wpa_s->conf->wps_cred_processing != 1);
    388 	wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
    389 
    390 	if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
    391 		wpa_dbus_mark_property_changed(wpa_s->global->dbus,
    392 					       wpa_s->dbus_new_path,
    393 					       WPAS_DBUS_NEW_IFACE_WPS,
    394 					       "ProcessCredentials");
    395 
    396 	return TRUE;
    397 }
    398