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