dbus: Remove perror() calls
[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                                 return wpas_dbus_error_invald_args(
71                                         message, "Role must be a string");
72                         }
73                         dbus_message_iter_get_basic(&variant_iter, &val);
74                         if (os_strcmp(val, "enrollee") == 0)
75                                 role = 1;
76                         else if (os_strcmp(val, "registrar") == 0)
77                                 role = 2;
78                         else {
79                                 wpa_printf(MSG_DEBUG,
80                                            "wpas_dbus_handler_wps_start[dbus]: "
81                                            "unknown role %s", val);
82                                 return wpas_dbus_error_invald_args(message,
83                                                                    val);
84                         }
85                 } else if (strcmp(key, "Type") == 0) {
86                         dbus_message_iter_recurse(&entry_iter, &variant_iter);
87                         if (dbus_message_iter_get_arg_type(&variant_iter) !=
88                             DBUS_TYPE_STRING) {
89                                 wpa_printf(MSG_DEBUG,
90                                            "wpas_dbus_handler_wps_start[dbus]: "
91                                            "wrong Type type. string required");
92                                 return wpas_dbus_error_invald_args(
93                                         message, "Type must be a string");
94                         }
95                         dbus_message_iter_get_basic(&variant_iter, &val);
96                         if (os_strcmp(val, "pin") == 0)
97                                 type = 1;
98                         else if (os_strcmp(val, "pbc") == 0)
99                                 type = 2;
100                         else {
101                                 wpa_printf(MSG_DEBUG,
102                                            "wpas_dbus_handler_wps_start[dbus]: "
103                                            "unknown type %s", val);
104                                 return wpas_dbus_error_invald_args(message,
105                                                                    val);
106                         }
107                 } else if (strcmp(key, "Bssid") == 0) {
108                         dbus_message_iter_recurse(&entry_iter, &variant_iter);
109                         if (dbus_message_iter_get_arg_type(&variant_iter) !=
110                             DBUS_TYPE_ARRAY ||
111                             dbus_message_iter_get_element_type(&variant_iter) !=
112                             DBUS_TYPE_ARRAY) {
113                                 wpa_printf(MSG_DEBUG,
114                                            "wpas_dbus_handler_wps_start[dbus]: "
115                                            "wrong Bssid type. byte array required");
116                                 return wpas_dbus_error_invald_args(
117                                         message, "Bssid must be a byte array");
118                         }
119                         dbus_message_iter_recurse(&variant_iter, &array_iter);
120                         dbus_message_iter_get_fixed_array(&array_iter, &bssid,
121                                                           &len);
122                         if (len != ETH_ALEN) {
123                                 wpa_printf(MSG_DEBUG,
124                                            "wpas_dbus_handler_wps_start[dbus]: "
125                                            "wrong Bssid length %d", len);
126                                 return wpas_dbus_error_invald_args(
127                                         message, "Bssid is wrong length");
128                         }
129                 }
130                 else if (os_strcmp(key, "Pin") == 0) {
131                         dbus_message_iter_recurse(&entry_iter, &variant_iter);
132                         if (dbus_message_iter_get_arg_type(&variant_iter) !=
133                             DBUS_TYPE_STRING) {
134                                 wpa_printf(MSG_DEBUG,
135                                            "wpas_dbus_handler_wps_start[dbus]: "
136                                            "wrong Pin type. string required");
137                                 return wpas_dbus_error_invald_args(
138                                         message, "Pin must be a string");
139                         }
140                         dbus_message_iter_get_basic(&variant_iter, &pin);
141                 } else {
142                         wpa_printf(MSG_DEBUG,
143                                    "wpas_dbus_handler_wps_start[dbus]: "
144                                    "unknown key %s", key);
145                         return wpas_dbus_error_invald_args(message, key);
146                 }
147
148                 dbus_message_iter_next(&dict_iter);
149         }
150
151         if (role == 0) {
152                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
153                            "Role not specified");
154                 return wpas_dbus_error_invald_args(message,
155                                                    "Role not specified");
156         }
157         else if (role == 1 && type == 0) {
158                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
159                            "Type not specified");
160                 return wpas_dbus_error_invald_args(message,
161                                                    "Type not specified");
162         }
163         else if (role == 2 && pin == NULL) {
164                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
165                            "Pin required for registrar role.");
166                 return wpas_dbus_error_invald_args(
167                         message, "Pin required for registrar role.");
168         }
169
170         if (role == 2)
171                 ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
172         else if (type == 1) {
173                 ret = wpas_wps_start_pin(wpa_s, bssid, pin);
174                 if (ret > 0)
175                         os_snprintf(npin, sizeof(npin), "%08d", ret);
176         } else
177                 ret = wpas_wps_start_pbc(wpa_s, bssid);
178
179         if (ret < 0) {
180                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
181                            "wpas_wps_failed in role %s and key %s.",
182                            (role == 1 ? "enrollee" : "registrar"),
183                            (type == 0 ? "" : (type == 1 ? "pin" : "pbc")));
184                 return wpas_dbus_error_unknown_error(message,
185                                                      "wps start failed");
186         }
187
188         reply = dbus_message_new_method_return(message);
189         if (!reply) {
190                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
191                                               NULL);
192         }
193
194         dbus_message_iter_init_append(reply, &iter);
195         if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
196                 dbus_message_unref(reply);
197                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
198                                               NULL);
199         }
200
201         if (os_strlen(npin) > 0) {
202                 if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
203                         dbus_message_unref(reply);
204                         return dbus_message_new_error(message,
205                                                       DBUS_ERROR_NO_MEMORY,
206                                                       NULL);
207                 }
208         }
209
210         if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
211                 dbus_message_unref(reply);
212                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
213                                               NULL);
214         }
215
216         return reply;
217 }
218
219
220 /**
221  * wpas_dbus_getter_process_credentials - Check if credentials are processed
222  * @message: Pointer to incoming dbus message
223  * @wpa_s: %wpa_supplicant data structure
224  * Returns: DBus message with a boolean on success or DBus error on failure
225  *
226  * Getter for "ProcessCredentials" property. Returns returned boolean will be
227  * true if wps_cred_processing configuration field is not equal to 1 or false
228  * if otherwise.
229  */
230 DBusMessage * wpas_dbus_getter_process_credentials(
231         DBusMessage *message, struct wpa_supplicant *wpa_s)
232 {
233         dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
234         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
235                                                 &process);
236 }
237
238
239 /**
240  * wpas_dbus_setter_process_credentials - Set credentials_processed conf param
241  * @message: Pointer to incoming dbus message
242  * @wpa_s: %wpa_supplicant data structure
243  * Returns: NULL on success or DBus error on failure
244  *
245  * Setter for "ProcessCredentials" property. Sets credentials_processed on 2
246  * if boolean argument is true or on 1 if otherwise.
247  */
248 DBusMessage * wpas_dbus_setter_process_credentials(
249         DBusMessage *message, struct wpa_supplicant *wpa_s)
250 {
251         DBusMessage *reply = NULL;
252         dbus_bool_t process_credentials, old_pc;
253
254         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
255                                                  &process_credentials);
256         if (reply)
257                 return reply;
258
259         old_pc = (wpa_s->conf->wps_cred_processing != 1);
260         wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
261
262         if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
263                 wpa_dbus_signal_property_changed(
264                         wpa_s->global->dbus,
265                         (WPADBusPropertyAccessor)
266                         wpas_dbus_getter_process_credentials,
267                         wpa_s, wpa_s->dbus_new_path,
268                         WPAS_DBUS_NEW_IFACE_WPS,
269                         "ProcessCredentials");
270
271         return NULL;
272 }