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 "dbus_new_helpers.h" 23 #include "dbus_new.h" 24 #include "dbus_new_handlers.h" 25 #include "dbus_dict_helpers.h" 26 27 28 struct wps_start_params { 29 int role; /* 0 - not set, 1 - enrollee, 2 - registrar */ 30 int type; /* 0 - not set, 1 - pin, 2 - pbc */ 31 u8 *bssid; 32 char *pin; 33 }; 34 35 36 static int wpas_dbus_handler_wps_role(DBusMessage *message, 37 DBusMessageIter *entry_iter, 38 struct wps_start_params *params, 39 DBusMessage **reply) 40 { 41 DBusMessageIter variant_iter; 42 char *val; 43 44 dbus_message_iter_recurse(entry_iter, &variant_iter); 45 if (dbus_message_iter_get_arg_type(&variant_iter) != 46 DBUS_TYPE_STRING) { 47 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Role type, " 48 "string required"); 49 *reply = wpas_dbus_error_invalid_args(message, 50 "Role must be a string"); 51 return -1; 52 } 53 dbus_message_iter_get_basic(&variant_iter, &val); 54 if (os_strcmp(val, "enrollee") == 0) 55 params->role = 1; 56 else if (os_strcmp(val, "registrar") == 0) 57 params->role = 2; 58 else { 59 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Uknown role %s", val); 60 *reply = wpas_dbus_error_invalid_args(message, val); 61 return -1; 62 } 63 return 0; 64 } 65 66 67 static int wpas_dbus_handler_wps_type(DBusMessage *message, 68 DBusMessageIter *entry_iter, 69 struct wps_start_params *params, 70 DBusMessage **reply) 71 { 72 DBusMessageIter variant_iter; 73 char *val; 74 75 dbus_message_iter_recurse(entry_iter, &variant_iter); 76 if (dbus_message_iter_get_arg_type(&variant_iter) != 77 DBUS_TYPE_STRING) { 78 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Type type, " 79 "string required"); 80 *reply = wpas_dbus_error_invalid_args(message, 81 "Type must be a string"); 82 return -1; 83 } 84 dbus_message_iter_get_basic(&variant_iter, &val); 85 if (os_strcmp(val, "pin") == 0) 86 params->type = 1; 87 else if (os_strcmp(val, "pbc") == 0) 88 params->type = 2; 89 else { 90 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s", 91 val); 92 *reply = wpas_dbus_error_invalid_args(message, val); 93 return -1; 94 } 95 return 0; 96 } 97 98 99 static int wpas_dbus_handler_wps_bssid(DBusMessage *message, 100 DBusMessageIter *entry_iter, 101 struct wps_start_params *params, 102 DBusMessage **reply) 103 { 104 DBusMessageIter variant_iter, array_iter; 105 int len; 106 107 dbus_message_iter_recurse(entry_iter, &variant_iter); 108 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY || 109 dbus_message_iter_get_element_type(&variant_iter) != 110 DBUS_TYPE_BYTE) { 111 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid type, " 112 "byte array required"); 113 *reply = wpas_dbus_error_invalid_args( 114 message, "Bssid must be a byte array"); 115 return -1; 116 } 117 dbus_message_iter_recurse(&variant_iter, &array_iter); 118 dbus_message_iter_get_fixed_array(&array_iter, ¶ms->bssid, &len); 119 if (len != ETH_ALEN) { 120 wpa_printf(MSG_DEBUG, "dbus: WPS.Stsrt - Wrong Bssid length " 121 "%d", len); 122 *reply = wpas_dbus_error_invalid_args(message, 123 "Bssid is wrong length"); 124 return -1; 125 } 126 return 0; 127 } 128 129 130 static int wpas_dbus_handler_wps_pin(DBusMessage *message, 131 DBusMessageIter *entry_iter, 132 struct wps_start_params *params, 133 DBusMessage **reply) 134 { 135 DBusMessageIter variant_iter; 136 137 dbus_message_iter_recurse(entry_iter, &variant_iter); 138 if (dbus_message_iter_get_arg_type(&variant_iter) != 139 DBUS_TYPE_STRING) { 140 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Pin type, " 141 "string required"); 142 *reply = wpas_dbus_error_invalid_args(message, 143 "Pin must be a string"); 144 return -1; 145 } 146 dbus_message_iter_get_basic(&variant_iter, ¶ms->pin); 147 return 0; 148 } 149 150 151 static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key, 152 DBusMessageIter *entry_iter, 153 struct wps_start_params *params, 154 DBusMessage **reply) 155 { 156 if (os_strcmp(key, "Role") == 0) 157 return wpas_dbus_handler_wps_role(message, entry_iter, 158 params, reply); 159 else if (os_strcmp(key, "Type") == 0) 160 return wpas_dbus_handler_wps_type(message, entry_iter, 161 params, reply); 162 else if (os_strcmp(key, "Bssid") == 0) 163 return wpas_dbus_handler_wps_bssid(message, entry_iter, 164 params, reply); 165 else if (os_strcmp(key, "Pin") == 0) 166 return wpas_dbus_handler_wps_pin(message, entry_iter, 167 params, reply); 168 169 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key); 170 *reply = wpas_dbus_error_invalid_args(message, key); 171 return -1; 172 } 173 174 175 /** 176 * wpas_dbus_handler_wps_start - Start WPS configuration 177 * @message: Pointer to incoming dbus message 178 * @wpa_s: %wpa_supplicant data structure 179 * Returns: DBus message dictionary on success or DBus error on failure 180 * 181 * Handler for "Start" method call. DBus dictionary argument contains 182 * information about role (enrollee or registrar), authorization method 183 * (pin or push button) and optionally pin and bssid. Returned message 184 * has a dictionary argument which may contain newly generated pin (optional). 185 */ 186 DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message, 187 struct wpa_supplicant *wpa_s) 188 { 189 DBusMessage *reply = NULL; 190 DBusMessageIter iter, dict_iter, entry_iter; 191 struct wps_start_params params; 192 char *key; 193 char npin[9] = { '\0' }; 194 int ret; 195 196 os_memset(¶ms, 0, sizeof(params)); 197 dbus_message_iter_init(message, &iter); 198 199 dbus_message_iter_recurse(&iter, &dict_iter); 200 while (dbus_message_iter_get_arg_type(&dict_iter) == 201 DBUS_TYPE_DICT_ENTRY) { 202 dbus_message_iter_recurse(&dict_iter, &entry_iter); 203 204 dbus_message_iter_get_basic(&entry_iter, &key); 205 dbus_message_iter_next(&entry_iter); 206 207 if (wpas_dbus_handler_wps_start_entry(message, key, 208 &entry_iter, 209 ¶ms, &reply)) 210 return reply; 211 212 dbus_message_iter_next(&dict_iter); 213 } 214 215 if (params.role == 0) { 216 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified"); 217 return wpas_dbus_error_invalid_args(message, 218 "Role not specified"); 219 } else if (params.role == 1 && params.type == 0) { 220 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified"); 221 return wpas_dbus_error_invalid_args(message, 222 "Type not specified"); 223 } else if (params.role == 2 && params.pin == NULL) { 224 wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Pin required for " 225 "registrar role"); 226 return wpas_dbus_error_invalid_args( 227 message, "Pin required for registrar role."); 228 } 229 230 if (params.role == 2) 231 ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin, 232 NULL); 233 else if (params.type == 1) { 234 ret = wpas_wps_start_pin(wpa_s, params.bssid, params.pin, 0, 235 DEV_PW_DEFAULT); 236 if (ret > 0) 237 os_snprintf(npin, sizeof(npin), "%08d", ret); 238 } else 239 ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0); 240 241 if (ret < 0) { 242 wpa_printf(MSG_DEBUG, "dbus: WPS.Start wpas_wps_failed in " 243 "role %s and key %s", 244 (params.role == 1 ? "enrollee" : "registrar"), 245 (params.type == 0 ? "" : 246 (params.type == 1 ? "pin" : "pbc"))); 247 return wpas_dbus_error_unknown_error(message, 248 "WPS start failed"); 249 } 250 251 reply = dbus_message_new_method_return(message); 252 if (!reply) { 253 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 254 NULL); 255 } 256 257 dbus_message_iter_init_append(reply, &iter); 258 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) { 259 dbus_message_unref(reply); 260 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 261 NULL); 262 } 263 264 if (os_strlen(npin) > 0) { 265 if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) { 266 dbus_message_unref(reply); 267 return dbus_message_new_error(message, 268 DBUS_ERROR_NO_MEMORY, 269 NULL); 270 } 271 } 272 273 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) { 274 dbus_message_unref(reply); 275 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 276 NULL); 277 } 278 279 return reply; 280 } 281 282 283 /** 284 * wpas_dbus_getter_process_credentials - Check if credentials are processed 285 * @message: Pointer to incoming dbus message 286 * @wpa_s: %wpa_supplicant data structure 287 * Returns: DBus message with a boolean on success or DBus error on failure 288 * 289 * Getter for "ProcessCredentials" property. Returns returned boolean will be 290 * true if wps_cred_processing configuration field is not equal to 1 or false 291 * if otherwise. 292 */ 293 DBusMessage * wpas_dbus_getter_process_credentials( 294 DBusMessage *message, struct wpa_supplicant *wpa_s) 295 { 296 dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1); 297 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 298 &process); 299 } 300 301 302 /** 303 * wpas_dbus_setter_process_credentials - Set credentials_processed conf param 304 * @message: Pointer to incoming dbus message 305 * @wpa_s: %wpa_supplicant data structure 306 * Returns: NULL on success or DBus error on failure 307 * 308 * Setter for "ProcessCredentials" property. Sets credentials_processed on 2 309 * if boolean argument is true or on 1 if otherwise. 310 */ 311 DBusMessage * wpas_dbus_setter_process_credentials( 312 DBusMessage *message, struct wpa_supplicant *wpa_s) 313 { 314 DBusMessage *reply = NULL; 315 dbus_bool_t process_credentials, old_pc; 316 317 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, 318 &process_credentials); 319 if (reply) 320 return reply; 321 322 old_pc = (wpa_s->conf->wps_cred_processing != 1); 323 wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1); 324 325 if ((wpa_s->conf->wps_cred_processing != 1) != old_pc) 326 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 327 wpa_s->dbus_new_path, 328 WPAS_DBUS_NEW_IFACE_WPS, 329 "ProcessCredentials"); 330 331 return NULL; 332 } 333