~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to wpa_supplicant/dbus/dbus_old_handlers.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * WPA Supplicant / dbus-based control interface
 
3
 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include "includes.h"
 
16
#include <dbus/dbus.h>
 
17
 
 
18
#include "common.h"
 
19
#include "eap_peer/eap_methods.h"
 
20
#include "common/ieee802_11_defs.h"
 
21
#include "eapol_supp/eapol_supp_sm.h"
 
22
#include "rsn_supp/wpa.h"
 
23
#include "../config.h"
 
24
#include "../wpa_supplicant_i.h"
 
25
#include "../driver_i.h"
 
26
#include "../notify.h"
 
27
#include "../wpas_glue.h"
 
28
#include "../bss.h"
 
29
#include "../scan.h"
 
30
#include "dbus_old.h"
 
31
#include "dbus_old_handlers.h"
 
32
#include "dbus_dict_helpers.h"
 
33
 
 
34
extern int wpa_debug_level;
 
35
extern int wpa_debug_show_keys;
 
36
extern int wpa_debug_timestamp;
 
37
 
 
38
/**
 
39
 * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
 
40
 * @message: Pointer to incoming dbus message this error refers to
 
41
 * Returns: a dbus error message
 
42
 *
 
43
 * Convenience function to create and return an invalid options error
 
44
 */
 
45
DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
 
46
                                               const char *arg)
 
47
{
 
48
        DBusMessage *reply;
 
49
 
 
50
        reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
 
51
                                       "Did not receive correct message "
 
52
                                       "arguments.");
 
53
        if (arg != NULL)
 
54
                dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
 
55
                                         DBUS_TYPE_INVALID);
 
56
 
 
57
        return reply;
 
58
}
 
59
 
 
60
 
 
61
/**
 
62
 * wpas_dbus_new_success_reply - Return a new success reply message
 
63
 * @message: Pointer to incoming dbus message this reply refers to
 
64
 * Returns: a dbus message containing a single UINT32 that indicates
 
65
 *          success (ie, a value of 1)
 
66
 *
 
67
 * Convenience function to create and return a success reply message
 
68
 */
 
69
DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
 
70
{
 
71
        DBusMessage *reply;
 
72
        unsigned int success = 1;
 
73
 
 
74
        reply = dbus_message_new_method_return(message);
 
75
        dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
 
76
                                 DBUS_TYPE_INVALID);
 
77
        return reply;
 
78
}
 
79
 
 
80
 
 
81
/**
 
82
 * wpas_dbus_global_add_interface - Request registration of a network interface
 
83
 * @message: Pointer to incoming dbus message
 
84
 * @global: %wpa_supplicant global data structure
 
85
 * Returns: The object path of the new interface object,
 
86
 *          or a dbus error message with more information
 
87
 *
 
88
 * Handler function for "addInterface" method call. Handles requests
 
89
 * by dbus clients to register a network interface that wpa_supplicant
 
90
 * will manage.
 
91
 */
 
92
DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
 
93
                                             struct wpa_global *global)
 
94
{
 
95
        char *ifname = NULL;
 
96
        char *driver = NULL;
 
97
        char *driver_param = NULL;
 
98
        char *confname = NULL;
 
99
        char *bridge_ifname = NULL;
 
100
        DBusMessage *reply = NULL;
 
101
        DBusMessageIter iter;
 
102
 
 
103
        dbus_message_iter_init(message, &iter);
 
104
 
 
105
        /* First argument: interface name (DBUS_TYPE_STRING)
 
106
         *    Required; must be non-zero length
 
107
         */
 
108
        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 
109
                goto error;
 
110
        dbus_message_iter_get_basic(&iter, &ifname);
 
111
        if (!os_strlen(ifname))
 
112
                goto error;
 
113
 
 
114
        /* Second argument: dict of options */
 
115
        if (dbus_message_iter_next(&iter)) {
 
116
                DBusMessageIter iter_dict;
 
117
                struct wpa_dbus_dict_entry entry;
 
118
 
 
119
                if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
 
120
                        goto error;
 
121
                while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
122
                        if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
 
123
                                goto error;
 
124
                        if (!strcmp(entry.key, "driver") &&
 
125
                            (entry.type == DBUS_TYPE_STRING)) {
 
126
                                driver = os_strdup(entry.str_value);
 
127
                                wpa_dbus_dict_entry_clear(&entry);
 
128
                                if (driver == NULL)
 
129
                                        goto error;
 
130
                        } else if (!strcmp(entry.key, "driver-params") &&
 
131
                                   (entry.type == DBUS_TYPE_STRING)) {
 
132
                                driver_param = os_strdup(entry.str_value);
 
133
                                wpa_dbus_dict_entry_clear(&entry);
 
134
                                if (driver_param == NULL)
 
135
                                        goto error;
 
136
                        } else if (!strcmp(entry.key, "config-file") &&
 
137
                                   (entry.type == DBUS_TYPE_STRING)) {
 
138
                                confname = os_strdup(entry.str_value);
 
139
                                wpa_dbus_dict_entry_clear(&entry);
 
140
                                if (confname == NULL)
 
141
                                        goto error;
 
142
                        } else if (!strcmp(entry.key, "bridge-ifname") &&
 
143
                                   (entry.type == DBUS_TYPE_STRING)) {
 
144
                                bridge_ifname = os_strdup(entry.str_value);
 
145
                                wpa_dbus_dict_entry_clear(&entry);
 
146
                                if (bridge_ifname == NULL)
 
147
                                        goto error;
 
148
                        } else {
 
149
                                wpa_dbus_dict_entry_clear(&entry);
 
150
                                goto error;
 
151
                        }
 
152
                }
 
153
        }
 
154
 
 
155
        /*
 
156
         * Try to get the wpa_supplicant record for this iface, return
 
157
         * an error if we already control it.
 
158
         */
 
159
        if (wpa_supplicant_get_iface(global, ifname) != NULL) {
 
160
                reply = dbus_message_new_error(message,
 
161
                                               WPAS_ERROR_EXISTS_ERROR,
 
162
                                               "wpa_supplicant already "
 
163
                                               "controls this interface.");
 
164
        } else {
 
165
                struct wpa_supplicant *wpa_s;
 
166
                struct wpa_interface iface;
 
167
                os_memset(&iface, 0, sizeof(iface));
 
168
                iface.ifname = ifname;
 
169
                iface.driver = driver;
 
170
                iface.driver_param = driver_param;
 
171
                iface.confname = confname;
 
172
                iface.bridge_ifname = bridge_ifname;
 
173
                /* Otherwise, have wpa_supplicant attach to it. */
 
174
                if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
 
175
                        const char *path = wpa_s->dbus_path;
 
176
                        reply = dbus_message_new_method_return(message);
 
177
                        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
 
178
                                                 &path, DBUS_TYPE_INVALID);
 
179
                } else {
 
180
                        reply = dbus_message_new_error(message,
 
181
                                                       WPAS_ERROR_ADD_ERROR,
 
182
                                                       "wpa_supplicant "
 
183
                                                       "couldn't grab this "
 
184
                                                       "interface.");
 
185
                }
 
186
        }
 
187
 
 
188
out:
 
189
        os_free(driver);
 
190
        os_free(driver_param);
 
191
        os_free(confname);
 
192
        os_free(bridge_ifname);
 
193
        return reply;
 
194
 
 
195
error:
 
196
        reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
197
        goto out;
 
198
}
 
199
 
 
200
 
 
201
/**
 
202
 * wpas_dbus_global_remove_interface - Request deregistration of an interface
 
203
 * @message: Pointer to incoming dbus message
 
204
 * @global: wpa_supplicant global data structure
 
205
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
206
 *          failure (0), or returns a dbus error message with more information
 
207
 *
 
208
 * Handler function for "removeInterface" method call.  Handles requests
 
209
 * by dbus clients to deregister a network interface that wpa_supplicant
 
210
 * currently manages.
 
211
 */
 
212
DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
 
213
                                                struct wpa_global *global)
 
214
{
 
215
        struct wpa_supplicant *wpa_s;
 
216
        char *path;
 
217
        DBusMessage *reply = NULL;
 
218
 
 
219
        if (!dbus_message_get_args(message, NULL,
 
220
                                   DBUS_TYPE_OBJECT_PATH, &path,
 
221
                                   DBUS_TYPE_INVALID)) {
 
222
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
223
                goto out;
 
224
        }
 
225
 
 
226
        wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
 
227
        if (wpa_s == NULL) {
 
228
                reply = wpas_dbus_new_invalid_iface_error(message);
 
229
                goto out;
 
230
        }
 
231
 
 
232
        if (!wpa_supplicant_remove_iface(global, wpa_s)) {
 
233
                reply = wpas_dbus_new_success_reply(message);
 
234
        } else {
 
235
                reply = dbus_message_new_error(message,
 
236
                                               WPAS_ERROR_REMOVE_ERROR,
 
237
                                               "wpa_supplicant couldn't "
 
238
                                               "remove this interface.");
 
239
        }
 
240
 
 
241
out:
 
242
        return reply;
 
243
}
 
244
 
 
245
 
 
246
/**
 
247
 * wpas_dbus_global_get_interface - Get the object path for an interface name
 
248
 * @message: Pointer to incoming dbus message
 
249
 * @global: %wpa_supplicant global data structure
 
250
 * Returns: The object path of the interface object,
 
251
 *          or a dbus error message with more information
 
252
 *
 
253
 * Handler function for "getInterface" method call. Handles requests
 
254
 * by dbus clients for the object path of an specific network interface.
 
255
 */
 
256
DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
 
257
                                             struct wpa_global *global)
 
258
{
 
259
        DBusMessage *reply = NULL;
 
260
        const char *ifname;
 
261
        const char *path;
 
262
        struct wpa_supplicant *wpa_s;
 
263
 
 
264
        if (!dbus_message_get_args(message, NULL,
 
265
                                   DBUS_TYPE_STRING, &ifname,
 
266
                                   DBUS_TYPE_INVALID)) {
 
267
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
268
                goto out;
 
269
        }
 
270
 
 
271
        wpa_s = wpa_supplicant_get_iface(global, ifname);
 
272
        if (wpa_s == NULL) {
 
273
                reply = wpas_dbus_new_invalid_iface_error(message);
 
274
                goto out;
 
275
        }
 
276
 
 
277
        path = wpa_s->dbus_path;
 
278
        reply = dbus_message_new_method_return(message);
 
279
        dbus_message_append_args(reply,
 
280
                                 DBUS_TYPE_OBJECT_PATH, &path,
 
281
                                 DBUS_TYPE_INVALID);
 
282
 
 
283
out:
 
284
        return reply;
 
285
}
 
286
 
 
287
 
 
288
/**
 
289
 * wpas_dbus_global_set_debugparams- Set the debug params
 
290
 * @message: Pointer to incoming dbus message
 
291
 * @global: %wpa_supplicant global data structure
 
292
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
293
 *          failure (0), or returns a dbus error message with more information
 
294
 *
 
295
 * Handler function for "setDebugParams" method call. Handles requests
 
296
 * by dbus clients for the object path of an specific network interface.
 
297
 */
 
298
DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
 
299
                                               struct wpa_global *global)
 
300
{
 
301
        DBusMessage *reply = NULL;
 
302
        int debug_level;
 
303
        dbus_bool_t debug_timestamp;
 
304
        dbus_bool_t debug_show_keys;
 
305
 
 
306
        if (!dbus_message_get_args(message, NULL,
 
307
                                   DBUS_TYPE_INT32, &debug_level,
 
308
                                   DBUS_TYPE_BOOLEAN, &debug_timestamp,
 
309
                                   DBUS_TYPE_BOOLEAN, &debug_show_keys,
 
310
                                   DBUS_TYPE_INVALID)) {
 
311
                return wpas_dbus_new_invalid_opts_error(message, NULL);
 
312
        }
 
313
 
 
314
        if (wpa_supplicant_set_debug_params(global, debug_level,
 
315
                                            debug_timestamp ? 1 : 0,
 
316
                                            debug_show_keys ? 1 : 0)) {
 
317
                return wpas_dbus_new_invalid_opts_error(message, NULL);
 
318
        }
 
319
 
 
320
        reply = wpas_dbus_new_success_reply(message);
 
321
 
 
322
        return reply;
 
323
}
 
324
 
 
325
 
 
326
/**
 
327
 * wpas_dbus_iface_scan - Request a wireless scan on an interface
 
328
 * @message: Pointer to incoming dbus message
 
329
 * @wpa_s: wpa_supplicant structure for a network interface
 
330
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
331
 *          failure (0)
 
332
 *
 
333
 * Handler function for "scan" method call of a network device. Requests
 
334
 * that wpa_supplicant perform a wireless scan as soon as possible
 
335
 * on a particular wireless interface.
 
336
 */
 
337
DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
 
338
                                   struct wpa_supplicant *wpa_s)
 
339
{
 
340
        wpa_s->scan_req = 2;
 
341
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
342
        return wpas_dbus_new_success_reply(message);
 
343
}
 
344
 
 
345
 
 
346
/**
 
347
 * wpas_dbus_iface_scan_results - Get the results of a recent scan request
 
348
 * @message: Pointer to incoming dbus message
 
349
 * @wpa_s: wpa_supplicant structure for a network interface
 
350
 * Returns: a dbus message containing a dbus array of objects paths, or returns
 
351
 *          a dbus error message if not scan results could be found
 
352
 *
 
353
 * Handler function for "scanResults" method call of a network device. Returns
 
354
 * a dbus message containing the object paths of wireless networks found.
 
355
 */
 
356
DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
 
357
                                           struct wpa_supplicant *wpa_s)
 
358
{
 
359
        DBusMessage *reply = NULL;
 
360
        DBusMessageIter iter;
 
361
        DBusMessageIter sub_iter;
 
362
        struct wpa_bss *bss;
 
363
 
 
364
        /* Create and initialize the return message */
 
365
        reply = dbus_message_new_method_return(message);
 
366
        dbus_message_iter_init_append(reply, &iter);
 
367
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 
368
                                         DBUS_TYPE_OBJECT_PATH_AS_STRING,
 
369
                                         &sub_iter);
 
370
 
 
371
        /* Loop through scan results and append each result's object path */
 
372
        dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
 
373
                char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
 
374
                char *path = path_buf;
 
375
 
 
376
                /* Construct the object path for this network.  Note that ':'
 
377
                 * is not a valid character in dbus object paths.
 
378
                 */
 
379
                os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
 
380
                            "%s/" WPAS_DBUS_BSSIDS_PART "/"
 
381
                            WPAS_DBUS_BSSID_FORMAT,
 
382
                            wpa_s->dbus_path, MAC2STR(bss->bssid));
 
383
                dbus_message_iter_append_basic(&sub_iter,
 
384
                                               DBUS_TYPE_OBJECT_PATH, &path);
 
385
        }
 
386
 
 
387
        dbus_message_iter_close_container(&iter, &sub_iter);
 
388
 
 
389
        return reply;
 
390
}
 
391
 
 
392
 
 
393
/**
 
394
 * wpas_dbus_bssid_properties - Return the properties of a scanned network
 
395
 * @message: Pointer to incoming dbus message
 
396
 * @wpa_s: wpa_supplicant structure for a network interface
 
397
 * @res: wpa_supplicant scan result for which to get properties
 
398
 * Returns: a dbus message containing the properties for the requested network
 
399
 *
 
400
 * Handler function for "properties" method call of a scanned network.
 
401
 * Returns a dbus message containing the the properties.
 
402
 */
 
403
DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
 
404
                                         struct wpa_supplicant *wpa_s,
 
405
                                         struct wpa_bss *bss)
 
406
{
 
407
        DBusMessage *reply;
 
408
        DBusMessageIter iter, iter_dict;
 
409
        const u8 *ie;
 
410
 
 
411
        /* Dump the properties into a dbus message */
 
412
        reply = dbus_message_new_method_return(message);
 
413
 
 
414
        dbus_message_iter_init_append(reply, &iter);
 
415
        if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
 
416
                goto error;
 
417
 
 
418
        if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
 
419
                                             (const char *) bss->bssid,
 
420
                                             ETH_ALEN))
 
421
                goto error;
 
422
 
 
423
        ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
 
424
        if (ie) {
 
425
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
 
426
                                                     (const char *) (ie + 2),
 
427
                                                     ie[1]))
 
428
                goto error;
 
429
        }
 
430
 
 
431
        ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 
432
        if (ie) {
 
433
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
 
434
                                                     (const char *) ie,
 
435
                                                     ie[1] + 2))
 
436
                        goto error;
 
437
        }
 
438
 
 
439
        ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 
440
        if (ie) {
 
441
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
 
442
                                                     (const char *) ie,
 
443
                                                     ie[1] + 2))
 
444
                        goto error;
 
445
        }
 
446
 
 
447
        ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
 
448
        if (ie) {
 
449
                if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
 
450
                                                     (const char *) ie,
 
451
                                                     ie[1] + 2))
 
452
                        goto error;
 
453
        }
 
454
 
 
455
        if (bss->freq) {
 
456
                if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
 
457
                                                bss->freq))
 
458
                        goto error;
 
459
        }
 
460
        if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
 
461
                                         bss->caps))
 
462
                goto error;
 
463
        if (!(bss->flags & WPA_BSS_QUAL_INVALID) &&
 
464
            !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual))
 
465
                goto error;
 
466
        if (!(bss->flags & WPA_BSS_NOISE_INVALID) &&
 
467
            !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise))
 
468
                goto error;
 
469
        if (!(bss->flags & WPA_BSS_LEVEL_INVALID) &&
 
470
            !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level))
 
471
                goto error;
 
472
        if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
 
473
                                        wpa_bss_get_max_rate(bss) * 500000))
 
474
                goto error;
 
475
 
 
476
        if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
 
477
                goto error;
 
478
 
 
479
        return reply;
 
480
 
 
481
error:
 
482
        if (reply)
 
483
                dbus_message_unref(reply);
 
484
        return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
 
485
                                      "an internal error occurred returning "
 
486
                                      "BSSID properties.");
 
487
}
 
488
 
 
489
 
 
490
/**
 
491
 * wpas_dbus_iface_capabilities - Return interface capabilities
 
492
 * @message: Pointer to incoming dbus message
 
493
 * @wpa_s: wpa_supplicant structure for a network interface
 
494
 * Returns: A dbus message containing a dict of strings
 
495
 *
 
496
 * Handler function for "capabilities" method call of an interface.
 
497
 */
 
498
DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
 
499
                                           struct wpa_supplicant *wpa_s)
 
500
{
 
501
        DBusMessage *reply = NULL;
 
502
        struct wpa_driver_capa capa;
 
503
        int res;
 
504
        DBusMessageIter iter, iter_dict;
 
505
        char **eap_methods;
 
506
        size_t num_items;
 
507
        dbus_bool_t strict = FALSE;
 
508
        DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
 
509
 
 
510
        if (!dbus_message_get_args(message, NULL,
 
511
                                   DBUS_TYPE_BOOLEAN, &strict,
 
512
                                   DBUS_TYPE_INVALID))
 
513
                strict = FALSE;
 
514
 
 
515
        reply = dbus_message_new_method_return(message);
 
516
 
 
517
        dbus_message_iter_init_append(reply, &iter);
 
518
        if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
 
519
                goto error;
 
520
 
 
521
        /* EAP methods */
 
522
        eap_methods = eap_get_names_as_string_array(&num_items);
 
523
        if (eap_methods) {
 
524
                dbus_bool_t success = FALSE;
 
525
                size_t i = 0;
 
526
 
 
527
                success = wpa_dbus_dict_append_string_array(
 
528
                        &iter_dict, "eap", (const char **) eap_methods,
 
529
                        num_items);
 
530
 
 
531
                /* free returned method array */
 
532
                while (eap_methods[i])
 
533
                        os_free(eap_methods[i++]);
 
534
                os_free(eap_methods);
 
535
 
 
536
                if (!success)
 
537
                        goto error;
 
538
        }
 
539
 
 
540
        res = wpa_drv_get_capa(wpa_s, &capa);
 
541
 
 
542
        /***** pairwise cipher */
 
543
        if (res < 0) {
 
544
                if (!strict) {
 
545
                        const char *args[] = {"CCMP", "TKIP", "NONE"};
 
546
                        if (!wpa_dbus_dict_append_string_array(
 
547
                                    &iter_dict, "pairwise", args,
 
548
                                    sizeof(args) / sizeof(char*)))
 
549
                                goto error;
 
550
                }
 
551
        } else {
 
552
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
 
553
                                                      &iter_dict_entry,
 
554
                                                      &iter_dict_val,
 
555
                                                      &iter_array))
 
556
                        goto error;
 
557
 
 
558
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
559
                        if (!wpa_dbus_dict_string_array_add_element(
 
560
                                    &iter_array, "CCMP"))
 
561
                                goto error;
 
562
                }
 
563
 
 
564
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
565
                        if (!wpa_dbus_dict_string_array_add_element(
 
566
                                    &iter_array, "TKIP"))
 
567
                                goto error;
 
568
                }
 
569
 
 
570
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
571
                        if (!wpa_dbus_dict_string_array_add_element(
 
572
                                    &iter_array, "NONE"))
 
573
                                goto error;
 
574
                }
 
575
 
 
576
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
577
                                                    &iter_dict_entry,
 
578
                                                    &iter_dict_val,
 
579
                                                    &iter_array))
 
580
                        goto error;
 
581
        }
 
582
 
 
583
        /***** group cipher */
 
584
        if (res < 0) {
 
585
                if (!strict) {
 
586
                        const char *args[] = {
 
587
                                "CCMP", "TKIP", "WEP104", "WEP40"
 
588
                        };
 
589
                        if (!wpa_dbus_dict_append_string_array(
 
590
                                    &iter_dict, "group", args,
 
591
                                    sizeof(args) / sizeof(char*)))
 
592
                                goto error;
 
593
                }
 
594
        } else {
 
595
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
 
596
                                                      &iter_dict_entry,
 
597
                                                      &iter_dict_val,
 
598
                                                      &iter_array))
 
599
                        goto error;
 
600
 
 
601
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
602
                        if (!wpa_dbus_dict_string_array_add_element(
 
603
                                    &iter_array, "CCMP"))
 
604
                                goto error;
 
605
                }
 
606
 
 
607
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
608
                        if (!wpa_dbus_dict_string_array_add_element(
 
609
                                    &iter_array, "TKIP"))
 
610
                                goto error;
 
611
                }
 
612
 
 
613
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
 
614
                        if (!wpa_dbus_dict_string_array_add_element(
 
615
                                    &iter_array, "WEP104"))
 
616
                                goto error;
 
617
                }
 
618
 
 
619
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
 
620
                        if (!wpa_dbus_dict_string_array_add_element(
 
621
                                    &iter_array, "WEP40"))
 
622
                                goto error;
 
623
                }
 
624
 
 
625
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
626
                                                    &iter_dict_entry,
 
627
                                                    &iter_dict_val,
 
628
                                                    &iter_array))
 
629
                        goto error;
 
630
        }
 
631
 
 
632
        /***** key management */
 
633
        if (res < 0) {
 
634
                if (!strict) {
 
635
                        const char *args[] = {
 
636
                                "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
 
637
                                "NONE"
 
638
                        };
 
639
                        if (!wpa_dbus_dict_append_string_array(
 
640
                                    &iter_dict, "key_mgmt", args,
 
641
                                    sizeof(args) / sizeof(char*)))
 
642
                                goto error;
 
643
                }
 
644
        } else {
 
645
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
 
646
                                                      &iter_dict_entry,
 
647
                                                      &iter_dict_val,
 
648
                                                      &iter_array))
 
649
                        goto error;
 
650
 
 
651
                if (!wpa_dbus_dict_string_array_add_element(&iter_array,
 
652
                                                            "NONE"))
 
653
                        goto error;
 
654
 
 
655
                if (!wpa_dbus_dict_string_array_add_element(&iter_array,
 
656
                                                            "IEEE8021X"))
 
657
                        goto error;
 
658
 
 
659
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
660
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
 
661
                        if (!wpa_dbus_dict_string_array_add_element(
 
662
                                    &iter_array, "WPA-EAP"))
 
663
                                goto error;
 
664
                }
 
665
 
 
666
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
 
667
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
668
                        if (!wpa_dbus_dict_string_array_add_element(
 
669
                                    &iter_array, "WPA-PSK"))
 
670
                                goto error;
 
671
                }
 
672
 
 
673
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
674
                        if (!wpa_dbus_dict_string_array_add_element(
 
675
                                    &iter_array, "WPA-NONE"))
 
676
                                goto error;
 
677
                }
 
678
 
 
679
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
680
                                                    &iter_dict_entry,
 
681
                                                    &iter_dict_val,
 
682
                                                    &iter_array))
 
683
                        goto error;
 
684
        }
 
685
 
 
686
        /***** WPA protocol */
 
687
        if (res < 0) {
 
688
                if (!strict) {
 
689
                        const char *args[] = { "RSN", "WPA" };
 
690
                        if (!wpa_dbus_dict_append_string_array(
 
691
                                    &iter_dict, "proto", args,
 
692
                                    sizeof(args) / sizeof(char*)))
 
693
                                goto error;
 
694
                }
 
695
        } else {
 
696
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
 
697
                                                      &iter_dict_entry,
 
698
                                                      &iter_dict_val,
 
699
                                                      &iter_array))
 
700
                        goto error;
 
701
 
 
702
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 
703
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
704
                        if (!wpa_dbus_dict_string_array_add_element(
 
705
                                    &iter_array, "RSN"))
 
706
                                goto error;
 
707
                }
 
708
 
 
709
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
710
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
 
711
                        if (!wpa_dbus_dict_string_array_add_element(
 
712
                                    &iter_array, "WPA"))
 
713
                                goto error;
 
714
                }
 
715
 
 
716
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
717
                                                    &iter_dict_entry,
 
718
                                                    &iter_dict_val,
 
719
                                                    &iter_array))
 
720
                        goto error;
 
721
        }
 
722
 
 
723
        /***** auth alg */
 
724
        if (res < 0) {
 
725
                if (!strict) {
 
726
                        const char *args[] = { "OPEN", "SHARED", "LEAP" };
 
727
                        if (!wpa_dbus_dict_append_string_array(
 
728
                                    &iter_dict, "auth_alg", args,
 
729
                                    sizeof(args) / sizeof(char*)))
 
730
                                goto error;
 
731
                }
 
732
        } else {
 
733
                if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
 
734
                                                      &iter_dict_entry,
 
735
                                                      &iter_dict_val,
 
736
                                                      &iter_array))
 
737
                        goto error;
 
738
 
 
739
                if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
 
740
                        if (!wpa_dbus_dict_string_array_add_element(
 
741
                                    &iter_array, "OPEN"))
 
742
                                goto error;
 
743
                }
 
744
 
 
745
                if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
 
746
                        if (!wpa_dbus_dict_string_array_add_element(
 
747
                                    &iter_array, "SHARED"))
 
748
                                goto error;
 
749
                }
 
750
 
 
751
                if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
 
752
                        if (!wpa_dbus_dict_string_array_add_element(
 
753
                                    &iter_array, "LEAP"))
 
754
                                goto error;
 
755
                }
 
756
 
 
757
                if (!wpa_dbus_dict_end_string_array(&iter_dict,
 
758
                                                    &iter_dict_entry,
 
759
                                                    &iter_dict_val,
 
760
                                                    &iter_array))
 
761
                        goto error;
 
762
        }
 
763
 
 
764
        if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
 
765
                goto error;
 
766
 
 
767
        return reply;
 
768
 
 
769
error:
 
770
        if (reply)
 
771
                dbus_message_unref(reply);
 
772
        return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
 
773
                                      "an internal error occurred returning "
 
774
                                      "interface capabilities.");
 
775
}
 
776
 
 
777
 
 
778
/**
 
779
 * wpas_dbus_iface_add_network - Add a new configured network
 
780
 * @message: Pointer to incoming dbus message
 
781
 * @wpa_s: wpa_supplicant structure for a network interface
 
782
 * Returns: A dbus message containing the object path of the new network
 
783
 *
 
784
 * Handler function for "addNetwork" method call of a network interface.
 
785
 */
 
786
DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
 
787
                                          struct wpa_supplicant *wpa_s)
 
788
{
 
789
        DBusMessage *reply = NULL;
 
790
        struct wpa_ssid *ssid;
 
791
        char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
 
792
 
 
793
        ssid = wpa_config_add_network(wpa_s->conf);
 
794
        if (ssid == NULL) {
 
795
                reply = dbus_message_new_error(message,
 
796
                                               WPAS_ERROR_ADD_NETWORK_ERROR,
 
797
                                               "wpa_supplicant could not add "
 
798
                                               "a network on this interface.");
 
799
                goto out;
 
800
        }
 
801
        wpas_notify_network_added(wpa_s, ssid);
 
802
        ssid->disabled = 1;
 
803
        wpa_config_set_network_defaults(ssid);
 
804
 
 
805
        /* Construct the object path for this network. */
 
806
        os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
 
807
                    "%s/" WPAS_DBUS_NETWORKS_PART "/%d",
 
808
                    wpa_s->dbus_path, ssid->id);
 
809
 
 
810
        reply = dbus_message_new_method_return(message);
 
811
        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
 
812
                                 &path, DBUS_TYPE_INVALID);
 
813
 
 
814
out:
 
815
        return reply;
 
816
}
 
817
 
 
818
 
 
819
/**
 
820
 * wpas_dbus_iface_remove_network - Remove a configured network
 
821
 * @message: Pointer to incoming dbus message
 
822
 * @wpa_s: wpa_supplicant structure for a network interface
 
823
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
824
 *          failure (0)
 
825
 *
 
826
 * Handler function for "removeNetwork" method call of a network interface.
 
827
 */
 
828
DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
 
829
                                             struct wpa_supplicant *wpa_s)
 
830
{
 
831
        DBusMessage *reply = NULL;
 
832
        const char *op;
 
833
        char *iface = NULL, *net_id = NULL;
 
834
        int id;
 
835
        struct wpa_ssid *ssid;
 
836
 
 
837
        if (!dbus_message_get_args(message, NULL,
 
838
                                   DBUS_TYPE_OBJECT_PATH, &op,
 
839
                                   DBUS_TYPE_INVALID)) {
 
840
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
841
                goto out;
 
842
        }
 
843
 
 
844
        /* Extract the network ID */
 
845
        iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
 
846
        if (iface == NULL) {
 
847
                reply = wpas_dbus_new_invalid_network_error(message);
 
848
                goto out;
 
849
        }
 
850
 
 
851
        /* Ensure the network is actually a child of this interface */
 
852
        if (os_strcmp(iface, wpa_s->dbus_path) != 0) {
 
853
                reply = wpas_dbus_new_invalid_network_error(message);
 
854
                goto out;
 
855
        }
 
856
 
 
857
        id = strtoul(net_id, NULL, 10);
 
858
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
859
        if (ssid == NULL) {
 
860
                reply = wpas_dbus_new_invalid_network_error(message);
 
861
                goto out;
 
862
        }
 
863
 
 
864
        wpas_notify_network_removed(wpa_s, ssid);
 
865
 
 
866
        if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
 
867
                reply = dbus_message_new_error(message,
 
868
                                               WPAS_ERROR_REMOVE_NETWORK_ERROR,
 
869
                                               "error removing the specified "
 
870
                                               "on this interface.");
 
871
                goto out;
 
872
        }
 
873
 
 
874
        if (ssid == wpa_s->current_ssid)
 
875
                wpa_supplicant_deauthenticate(wpa_s,
 
876
                                              WLAN_REASON_DEAUTH_LEAVING);
 
877
        reply = wpas_dbus_new_success_reply(message);
 
878
 
 
879
out:
 
880
        os_free(iface);
 
881
        os_free(net_id);
 
882
        return reply;
 
883
}
 
884
 
 
885
 
 
886
static const char *dont_quote[] = {
 
887
        "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
 
888
        "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
 
889
        "bssid", NULL
 
890
};
 
891
 
 
892
 
 
893
static dbus_bool_t should_quote_opt(const char *key)
 
894
{
 
895
        int i = 0;
 
896
        while (dont_quote[i] != NULL) {
 
897
                if (strcmp(key, dont_quote[i]) == 0)
 
898
                        return FALSE;
 
899
                i++;
 
900
        }
 
901
        return TRUE;
 
902
}
 
903
 
 
904
 
 
905
/**
 
906
 * wpas_dbus_iface_set_network - Set options for a configured network
 
907
 * @message: Pointer to incoming dbus message
 
908
 * @wpa_s: wpa_supplicant structure for a network interface
 
909
 * @ssid: wpa_ssid structure for a configured network
 
910
 * Returns: a dbus message containing a UINT32 indicating success (1) or
 
911
 *          failure (0)
 
912
 *
 
913
 * Handler function for "set" method call of a configured network.
 
914
 */
 
915
DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
 
916
                                          struct wpa_supplicant *wpa_s,
 
917
                                          struct wpa_ssid *ssid)
 
918
{
 
919
        DBusMessage *reply = NULL;
 
920
        struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
 
921
        DBusMessageIter iter, iter_dict;
 
922
 
 
923
        dbus_message_iter_init(message, &iter);
 
924
 
 
925
        if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
 
926
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
927
                goto out;
 
928
        }
 
929
 
 
930
        while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
931
                char *value = NULL;
 
932
                size_t size = 50;
 
933
                int ret;
 
934
 
 
935
                if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
 
936
                        reply = wpas_dbus_new_invalid_opts_error(message,
 
937
                                                                 NULL);
 
938
                        goto out;
 
939
                }
 
940
 
 
941
                /* Type conversions, since wpa_supplicant wants strings */
 
942
                if (entry.type == DBUS_TYPE_ARRAY &&
 
943
                    entry.array_type == DBUS_TYPE_BYTE) {
 
944
                        if (entry.array_len <= 0)
 
945
                                goto error;
 
946
 
 
947
                        size = entry.array_len * 2 + 1;
 
948
                        value = os_zalloc(size);
 
949
                        if (value == NULL)
 
950
                                goto error;
 
951
                        ret = wpa_snprintf_hex(value, size,
 
952
                                               (u8 *) entry.bytearray_value,
 
953
                                               entry.array_len);
 
954
                        if (ret <= 0)
 
955
                                goto error;
 
956
                } else if (entry.type == DBUS_TYPE_STRING) {
 
957
                        if (should_quote_opt(entry.key)) {
 
958
                                size = os_strlen(entry.str_value);
 
959
                                /* Zero-length option check */
 
960
                                if (size <= 0)
 
961
                                        goto error;
 
962
                                size += 3;  /* For quotes and terminator */
 
963
                                value = os_zalloc(size);
 
964
                                if (value == NULL)
 
965
                                        goto error;
 
966
                                ret = os_snprintf(value, size, "\"%s\"",
 
967
                                                  entry.str_value);
 
968
                                if (ret < 0 || (size_t) ret != (size - 1))
 
969
                                        goto error;
 
970
                        } else {
 
971
                                value = os_strdup(entry.str_value);
 
972
                                if (value == NULL)
 
973
                                        goto error;
 
974
                        }
 
975
                } else if (entry.type == DBUS_TYPE_UINT32) {
 
976
                        value = os_zalloc(size);
 
977
                        if (value == NULL)
 
978
                                goto error;
 
979
                        ret = os_snprintf(value, size, "%u",
 
980
                                          entry.uint32_value);
 
981
                        if (ret <= 0)
 
982
                                goto error;
 
983
                } else if (entry.type == DBUS_TYPE_INT32) {
 
984
                        value = os_zalloc(size);
 
985
                        if (value == NULL)
 
986
                                goto error;
 
987
                        ret = os_snprintf(value, size, "%d",
 
988
                                          entry.int32_value);
 
989
                        if (ret <= 0)
 
990
                                goto error;
 
991
                } else
 
992
                        goto error;
 
993
 
 
994
                if (wpa_config_set(ssid, entry.key, value, 0) < 0)
 
995
                        goto error;
 
996
 
 
997
                if ((os_strcmp(entry.key, "psk") == 0 &&
 
998
                     value[0] == '"' && ssid->ssid_len) ||
 
999
                    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
 
1000
                        wpa_config_update_psk(ssid);
 
1001
                else if (os_strcmp(entry.key, "priority") == 0)
 
1002
                        wpa_config_update_prio_list(wpa_s->conf);
 
1003
 
 
1004
                os_free(value);
 
1005
                wpa_dbus_dict_entry_clear(&entry);
 
1006
                continue;
 
1007
 
 
1008
        error:
 
1009
                os_free(value);
 
1010
                reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
 
1011
                wpa_dbus_dict_entry_clear(&entry);
 
1012
                break;
 
1013
        }
 
1014
 
 
1015
        if (!reply)
 
1016
                reply = wpas_dbus_new_success_reply(message);
 
1017
 
 
1018
out:
 
1019
        return reply;
 
1020
}
 
1021
 
 
1022
 
 
1023
/**
 
1024
 * wpas_dbus_iface_enable_network - Mark a configured network as enabled
 
1025
 * @message: Pointer to incoming dbus message
 
1026
 * @wpa_s: wpa_supplicant structure for a network interface
 
1027
 * @ssid: wpa_ssid structure for a configured network
 
1028
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1029
 *          failure (0)
 
1030
 *
 
1031
 * Handler function for "enable" method call of a configured network.
 
1032
 */
 
1033
DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
 
1034
                                             struct wpa_supplicant *wpa_s,
 
1035
                                             struct wpa_ssid *ssid)
 
1036
{
 
1037
        wpa_supplicant_enable_network(wpa_s, ssid);
 
1038
        return wpas_dbus_new_success_reply(message);
 
1039
}
 
1040
 
 
1041
 
 
1042
/**
 
1043
 * wpas_dbus_iface_disable_network - Mark a configured network as disabled
 
1044
 * @message: Pointer to incoming dbus message
 
1045
 * @wpa_s: wpa_supplicant structure for a network interface
 
1046
 * @ssid: wpa_ssid structure for a configured network
 
1047
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1048
 *          failure (0)
 
1049
 *
 
1050
 * Handler function for "disable" method call of a configured network.
 
1051
 */
 
1052
DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
 
1053
                                              struct wpa_supplicant *wpa_s,
 
1054
                                              struct wpa_ssid *ssid)
 
1055
{
 
1056
        wpa_supplicant_disable_network(wpa_s, ssid);
 
1057
        return wpas_dbus_new_success_reply(message);
 
1058
}
 
1059
 
 
1060
 
 
1061
/**
 
1062
 * wpas_dbus_iface_select_network - Attempt association with a configured network
 
1063
 * @message: Pointer to incoming dbus message
 
1064
 * @wpa_s: wpa_supplicant structure for a network interface
 
1065
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1066
 *          failure (0)
 
1067
 *
 
1068
 * Handler function for "selectNetwork" method call of network interface.
 
1069
 */
 
1070
DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
 
1071
                                             struct wpa_supplicant *wpa_s)
 
1072
{
 
1073
        DBusMessage *reply = NULL;
 
1074
        const char *op;
 
1075
        struct wpa_ssid *ssid;
 
1076
        char *iface_obj_path = NULL;
 
1077
        char *network = NULL;
 
1078
 
 
1079
        if (os_strlen(dbus_message_get_signature(message)) == 0) {
 
1080
                /* Any network */
 
1081
                ssid = NULL;
 
1082
        } else {
 
1083
                int nid;
 
1084
 
 
1085
                if (!dbus_message_get_args(message, NULL,
 
1086
                                           DBUS_TYPE_OBJECT_PATH, &op,
 
1087
                                           DBUS_TYPE_INVALID)) {
 
1088
                        reply = wpas_dbus_new_invalid_opts_error(message,
 
1089
                                                                 NULL);
 
1090
                        goto out;
 
1091
                }
 
1092
 
 
1093
                /* Extract the network number */
 
1094
                iface_obj_path = wpas_dbus_decompose_object_path(op,
 
1095
                                                                 &network,
 
1096
                                                                 NULL);
 
1097
                if (iface_obj_path == NULL) {
 
1098
                        reply = wpas_dbus_new_invalid_iface_error(message);
 
1099
                        goto out;
 
1100
                }
 
1101
                /* Ensure the object path really points to this interface */
 
1102
                if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) {
 
1103
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1104
                        goto out;
 
1105
                }
 
1106
 
 
1107
                nid = strtoul(network, NULL, 10);
 
1108
                if (errno == EINVAL) {
 
1109
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1110
                        goto out;
 
1111
                }
 
1112
 
 
1113
                ssid = wpa_config_get_network(wpa_s->conf, nid);
 
1114
                if (ssid == NULL) {
 
1115
                        reply = wpas_dbus_new_invalid_network_error(message);
 
1116
                        goto out;
 
1117
                }
 
1118
        }
 
1119
 
 
1120
        /* Finally, associate with the network */
 
1121
        wpa_supplicant_select_network(wpa_s, ssid);
 
1122
 
 
1123
        reply = wpas_dbus_new_success_reply(message);
 
1124
 
 
1125
out:
 
1126
        os_free(iface_obj_path);
 
1127
        os_free(network);
 
1128
        return reply;
 
1129
}
 
1130
 
 
1131
 
 
1132
/**
 
1133
 * wpas_dbus_iface_disconnect - Terminate the current connection
 
1134
 * @message: Pointer to incoming dbus message
 
1135
 * @wpa_s: wpa_supplicant structure for a network interface
 
1136
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1137
 *          failure (0)
 
1138
 *
 
1139
 * Handler function for "disconnect" method call of network interface.
 
1140
 */
 
1141
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
 
1142
                                         struct wpa_supplicant *wpa_s)
 
1143
{
 
1144
        wpa_s->disconnected = 1;
 
1145
        wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
 
1146
 
 
1147
        return wpas_dbus_new_success_reply(message);
 
1148
}
 
1149
 
 
1150
 
 
1151
/**
 
1152
 * wpas_dbus_iface_set_ap_scan - Control roaming mode
 
1153
 * @message: Pointer to incoming dbus message
 
1154
 * @wpa_s: wpa_supplicant structure for a network interface
 
1155
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1156
 *          failure (0)
 
1157
 *
 
1158
 * Handler function for "setAPScan" method call.
 
1159
 */
 
1160
DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
 
1161
                                          struct wpa_supplicant *wpa_s)
 
1162
{
 
1163
        DBusMessage *reply = NULL;
 
1164
        dbus_uint32_t ap_scan = 1;
 
1165
 
 
1166
        if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
 
1167
                                   DBUS_TYPE_INVALID)) {
 
1168
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
1169
                goto out;
 
1170
        }
 
1171
 
 
1172
        if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
 
1173
                reply = wpas_dbus_new_invalid_opts_error(message, NULL);
 
1174
                goto out;
 
1175
        }
 
1176
 
 
1177
        reply = wpas_dbus_new_success_reply(message);
 
1178
 
 
1179
out:
 
1180
        return reply;
 
1181
}
 
1182
 
 
1183
 
 
1184
/**
 
1185
 * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
 
1186
 * @message: Pointer to incoming dbus message
 
1187
 * @wpa_s: wpa_supplicant structure for a network interface
 
1188
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1189
 *          failure (0)
 
1190
 *
 
1191
 * Handler function for "setSmartcardModules" method call.
 
1192
 */
 
1193
DBusMessage * wpas_dbus_iface_set_smartcard_modules(
 
1194
        DBusMessage *message, struct wpa_supplicant *wpa_s)
 
1195
{
 
1196
        DBusMessageIter iter, iter_dict;
 
1197
        char *opensc_engine_path = NULL;
 
1198
        char *pkcs11_engine_path = NULL;
 
1199
        char *pkcs11_module_path = NULL;
 
1200
        struct wpa_dbus_dict_entry entry;
 
1201
 
 
1202
        if (!dbus_message_iter_init(message, &iter))
 
1203
                goto error;
 
1204
 
 
1205
        if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
 
1206
                goto error;
 
1207
 
 
1208
        while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
1209
                if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
 
1210
                        goto error;
 
1211
                if (!strcmp(entry.key, "opensc_engine_path") &&
 
1212
                    (entry.type == DBUS_TYPE_STRING)) {
 
1213
                        opensc_engine_path = os_strdup(entry.str_value);
 
1214
                        if (opensc_engine_path == NULL)
 
1215
                                goto error;
 
1216
                } else if (!strcmp(entry.key, "pkcs11_engine_path") &&
 
1217
                           (entry.type == DBUS_TYPE_STRING)) {
 
1218
                        pkcs11_engine_path = os_strdup(entry.str_value);
 
1219
                        if (pkcs11_engine_path == NULL)
 
1220
                                goto error;
 
1221
                } else if (!strcmp(entry.key, "pkcs11_module_path") &&
 
1222
                                 (entry.type == DBUS_TYPE_STRING)) {
 
1223
                        pkcs11_module_path = os_strdup(entry.str_value);
 
1224
                        if (pkcs11_module_path == NULL)
 
1225
                                goto error;
 
1226
                } else {
 
1227
                        wpa_dbus_dict_entry_clear(&entry);
 
1228
                        goto error;
 
1229
                }
 
1230
                wpa_dbus_dict_entry_clear(&entry);
 
1231
        }
 
1232
 
 
1233
        os_free(wpa_s->conf->opensc_engine_path);
 
1234
        wpa_s->conf->opensc_engine_path = opensc_engine_path;
 
1235
        os_free(wpa_s->conf->pkcs11_engine_path);
 
1236
        wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
 
1237
        os_free(wpa_s->conf->pkcs11_module_path);
 
1238
        wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
 
1239
 
 
1240
        wpa_sm_set_eapol(wpa_s->wpa, NULL);
 
1241
        eapol_sm_deinit(wpa_s->eapol);
 
1242
        wpa_s->eapol = NULL;
 
1243
        wpa_supplicant_init_eapol(wpa_s);
 
1244
        wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
 
1245
 
 
1246
        return wpas_dbus_new_success_reply(message);
 
1247
 
 
1248
error:
 
1249
        os_free(opensc_engine_path);
 
1250
        os_free(pkcs11_engine_path);
 
1251
        os_free(pkcs11_module_path);
 
1252
        return wpas_dbus_new_invalid_opts_error(message, NULL);
 
1253
}
 
1254
 
 
1255
 
 
1256
/**
 
1257
 * wpas_dbus_iface_get_state - Get interface state
 
1258
 * @message: Pointer to incoming dbus message
 
1259
 * @wpa_s: wpa_supplicant structure for a network interface
 
1260
 * Returns: A dbus message containing a STRING representing the current
 
1261
 *          interface state
 
1262
 *
 
1263
 * Handler function for "state" method call.
 
1264
 */
 
1265
DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
 
1266
                                        struct wpa_supplicant *wpa_s)
 
1267
{
 
1268
        DBusMessage *reply = NULL;
 
1269
        const char *str_state;
 
1270
 
 
1271
        reply = dbus_message_new_method_return(message);
 
1272
        if (reply != NULL) {
 
1273
                str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
 
1274
                dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
 
1275
                                         DBUS_TYPE_INVALID);
 
1276
        }
 
1277
 
 
1278
        return reply;
 
1279
}
 
1280
 
 
1281
 
 
1282
/**
 
1283
 * wpas_dbus_iface_get_scanning - Get interface scanning state
 
1284
 * @message: Pointer to incoming dbus message
 
1285
 * @wpa_s: wpa_supplicant structure for a network interface
 
1286
 * Returns: A dbus message containing whether the interface is scanning
 
1287
 *
 
1288
 * Handler function for "scanning" method call.
 
1289
 */
 
1290
DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
 
1291
                                           struct wpa_supplicant *wpa_s)
 
1292
{
 
1293
        DBusMessage *reply = NULL;
 
1294
        dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
 
1295
 
 
1296
        reply = dbus_message_new_method_return(message);
 
1297
        if (reply != NULL) {
 
1298
                dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
 
1299
                                         DBUS_TYPE_INVALID);
 
1300
        } else {
 
1301
                wpa_printf(MSG_ERROR, "dbus: Not enough memory to return "
 
1302
                           "scanning state");
 
1303
        }
 
1304
 
 
1305
        return reply;
 
1306
}
 
1307
 
 
1308
 
 
1309
/**
 
1310
 * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
 
1311
 * @message: Pointer to incoming dbus message
 
1312
 * @wpa_s: %wpa_supplicant data structure
 
1313
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1314
 *          failure (0)
 
1315
 *
 
1316
 * Asks wpa_supplicant to internally store a one or more binary blobs.
 
1317
 */
 
1318
DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
 
1319
                                        struct wpa_supplicant *wpa_s)
 
1320
{
 
1321
        DBusMessage *reply = NULL;
 
1322
        struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
 
1323
        DBusMessageIter iter, iter_dict;
 
1324
 
 
1325
        dbus_message_iter_init(message, &iter);
 
1326
 
 
1327
        if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
 
1328
                return wpas_dbus_new_invalid_opts_error(message, NULL);
 
1329
 
 
1330
        while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
 
1331
                struct wpa_config_blob *blob;
 
1332
 
 
1333
                if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
 
1334
                        reply = wpas_dbus_new_invalid_opts_error(message,
 
1335
                                                                 NULL);
 
1336
                        break;
 
1337
                }
 
1338
 
 
1339
                if (entry.type != DBUS_TYPE_ARRAY ||
 
1340
                    entry.array_type != DBUS_TYPE_BYTE) {
 
1341
                        reply = wpas_dbus_new_invalid_opts_error(
 
1342
                                message, "Byte array expected.");
 
1343
                        break;
 
1344
                }
 
1345
 
 
1346
                if ((entry.array_len <= 0) || (entry.array_len > 65536) ||
 
1347
                    !strlen(entry.key)) {
 
1348
                        reply = wpas_dbus_new_invalid_opts_error(
 
1349
                                message, "Invalid array size.");
 
1350
                        break;
 
1351
                }
 
1352
 
 
1353
                blob = os_zalloc(sizeof(*blob));
 
1354
                if (blob == NULL) {
 
1355
                        reply = dbus_message_new_error(
 
1356
                                message, WPAS_ERROR_ADD_ERROR,
 
1357
                                "Not enough memory to add blob.");
 
1358
                        break;
 
1359
                }
 
1360
                blob->data = os_zalloc(entry.array_len);
 
1361
                if (blob->data == NULL) {
 
1362
                        reply = dbus_message_new_error(
 
1363
                                message, WPAS_ERROR_ADD_ERROR,
 
1364
                                "Not enough memory to add blob data.");
 
1365
                        os_free(blob);
 
1366
                        break;
 
1367
                }
 
1368
 
 
1369
                blob->name = os_strdup(entry.key);
 
1370
                blob->len = entry.array_len;
 
1371
                os_memcpy(blob->data, (u8 *) entry.bytearray_value,
 
1372
                                entry.array_len);
 
1373
                if (blob->name == NULL || blob->data == NULL) {
 
1374
                        wpa_config_free_blob(blob);
 
1375
                        reply = dbus_message_new_error(
 
1376
                                message, WPAS_ERROR_ADD_ERROR,
 
1377
                                "Error adding blob.");
 
1378
                        break;
 
1379
                }
 
1380
 
 
1381
                /* Success */
 
1382
                if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
 
1383
                        wpas_notify_blob_removed(wpa_s, blob->name);
 
1384
                wpa_config_set_blob(wpa_s->conf, blob);
 
1385
                wpas_notify_blob_added(wpa_s, blob->name);
 
1386
 
 
1387
                wpa_dbus_dict_entry_clear(&entry);
 
1388
        }
 
1389
        wpa_dbus_dict_entry_clear(&entry);
 
1390
 
 
1391
        return reply ? reply : wpas_dbus_new_success_reply(message);
 
1392
}
 
1393
 
 
1394
 
 
1395
/**
 
1396
 * wpas_dbus_iface_remove_blob - Remove named binary blobs
 
1397
 * @message: Pointer to incoming dbus message
 
1398
 * @wpa_s: %wpa_supplicant data structure
 
1399
 * Returns: A dbus message containing a UINT32 indicating success (1) or
 
1400
 *          failure (0)
 
1401
 *
 
1402
 * Asks wpa_supplicant to remove one or more previously stored binary blobs.
 
1403
 */
 
1404
DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
 
1405
                                           struct wpa_supplicant *wpa_s)
 
1406
{
 
1407
        DBusMessageIter iter, array;
 
1408
        char *err_msg = NULL;
 
1409
 
 
1410
        dbus_message_iter_init(message, &iter);
 
1411
 
 
1412
        if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
 
1413
            (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
 
1414
                return wpas_dbus_new_invalid_opts_error(message, NULL);
 
1415
 
 
1416
        dbus_message_iter_recurse(&iter, &array);
 
1417
        while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
 
1418
                const char *name;
 
1419
 
 
1420
                dbus_message_iter_get_basic(&array, &name);
 
1421
                if (!os_strlen(name))
 
1422
                        err_msg = "Invalid blob name.";
 
1423
 
 
1424
                if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
 
1425
                        err_msg = "Error removing blob.";
 
1426
                else
 
1427
                        wpas_notify_blob_removed(wpa_s, name);
 
1428
                dbus_message_iter_next(&array);
 
1429
        }
 
1430
 
 
1431
        if (err_msg)
 
1432
                return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR,
 
1433
                                              err_msg);
 
1434
 
 
1435
        return wpas_dbus_new_success_reply(message);
 
1436
}