1 /* 2 * WPA Supplicant / dbus-based control interface (WPS) 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009, Witold Sowa <witold.sowa@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_ARRAY) { 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); 235 if (ret > 0) 236 os_snprintf(npin, sizeof(npin), "%08d", ret); 237 } else 238 ret = wpas_wps_start_pbc(wpa_s, params.bssid); 239 240 if (ret < 0) { 241 wpa_printf(MSG_DEBUG, "dbus: WPS.Start wpas_wps_failed in " 242 "role %s and key %s", 243 (params.role == 1 ? "enrollee" : "registrar"), 244 (params.type == 0 ? "" : 245 (params.type == 1 ? "pin" : "pbc"))); 246 return wpas_dbus_error_unknown_error(message, 247 "WPS start failed"); 248 } 249 250 reply = dbus_message_new_method_return(message); 251 if (!reply) { 252 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 253 NULL); 254 } 255 256 dbus_message_iter_init_append(reply, &iter); 257 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) { 258 dbus_message_unref(reply); 259 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 260 NULL); 261 } 262 263 if (os_strlen(npin) > 0) { 264 if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) { 265 dbus_message_unref(reply); 266 return dbus_message_new_error(message, 267 DBUS_ERROR_NO_MEMORY, 268 NULL); 269 } 270 } 271 272 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) { 273 dbus_message_unref(reply); 274 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 275 NULL); 276 } 277 278 return reply; 279 } 280 281 282 /** 283 * wpas_dbus_getter_process_credentials - Check if credentials are processed 284 * @message: Pointer to incoming dbus message 285 * @wpa_s: %wpa_supplicant data structure 286 * Returns: DBus message with a boolean on success or DBus error on failure 287 * 288 * Getter for "ProcessCredentials" property. Returns returned boolean will be 289 * true if wps_cred_processing configuration field is not equal to 1 or false 290 * if otherwise. 291 */ 292 DBusMessage * wpas_dbus_getter_process_credentials( 293 DBusMessage *message, struct wpa_supplicant *wpa_s) 294 { 295 dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1); 296 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 297 &process); 298 } 299 300 301 /** 302 * wpas_dbus_setter_process_credentials - Set credentials_processed conf param 303 * @message: Pointer to incoming dbus message 304 * @wpa_s: %wpa_supplicant data structure 305 * Returns: NULL on success or DBus error on failure 306 * 307 * Setter for "ProcessCredentials" property. Sets credentials_processed on 2 308 * if boolean argument is true or on 1 if otherwise. 309 */ 310 DBusMessage * wpas_dbus_setter_process_credentials( 311 DBusMessage *message, struct wpa_supplicant *wpa_s) 312 { 313 DBusMessage *reply = NULL; 314 dbus_bool_t process_credentials, old_pc; 315 316 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, 317 &process_credentials); 318 if (reply) 319 return reply; 320 321 old_pc = (wpa_s->conf->wps_cred_processing != 1); 322 wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1); 323 324 if ((wpa_s->conf->wps_cred_processing != 1) != old_pc) 325 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 326 wpa_s->dbus_new_path, 327 WPAS_DBUS_NEW_IFACE_WPS, 328 "ProcessCredentials"); 329 330 return NULL; 331 } 332