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