~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to src/drivers/driver_privsep.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * WPA Supplicant - privilege separated driver interface
 
3
 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
 
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 <sys/un.h>
 
17
 
 
18
#include "common.h"
 
19
#include "driver.h"
 
20
#include "eloop.h"
 
21
#include "privsep_commands.h"
 
22
 
 
23
 
 
24
struct wpa_driver_privsep_data {
 
25
        void *ctx;
 
26
        u8 own_addr[ETH_ALEN];
 
27
        int priv_socket;
 
28
        char *own_socket_path;
 
29
        int cmd_socket;
 
30
        char *own_cmd_path;
 
31
        struct sockaddr_un priv_addr;
 
32
        char ifname[16];
 
33
};
 
34
 
 
35
 
 
36
static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd)
 
37
{
 
38
        int res;
 
39
 
 
40
        res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0,
 
41
                     (struct sockaddr *) &drv->priv_addr,
 
42
                     sizeof(drv->priv_addr));
 
43
        if (res < 0)
 
44
                perror("sendto");
 
45
        return res < 0 ? -1 : 0;
 
46
}
 
47
 
 
48
 
 
49
static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd,
 
50
                        const void *data, size_t data_len,
 
51
                        void *reply, size_t *reply_len)
 
52
{
 
53
        struct msghdr msg;
 
54
        struct iovec io[2];
 
55
 
 
56
        io[0].iov_base = &cmd;
 
57
        io[0].iov_len = sizeof(cmd);
 
58
        io[1].iov_base = (u8 *) data;
 
59
        io[1].iov_len = data_len;
 
60
 
 
61
        os_memset(&msg, 0, sizeof(msg));
 
62
        msg.msg_iov = io;
 
63
        msg.msg_iovlen = data ? 2 : 1;
 
64
        msg.msg_name = &drv->priv_addr;
 
65
        msg.msg_namelen = sizeof(drv->priv_addr);
 
66
 
 
67
        if (sendmsg(drv->cmd_socket, &msg, 0) < 0) {
 
68
                perror("sendmsg(cmd_socket)");
 
69
                return -1;
 
70
        }
 
71
 
 
72
        if (reply) {
 
73
                fd_set rfds;
 
74
                struct timeval tv;
 
75
                int res;
 
76
 
 
77
                FD_ZERO(&rfds);
 
78
                FD_SET(drv->cmd_socket, &rfds);
 
79
                tv.tv_sec = 5;
 
80
                tv.tv_usec = 0;
 
81
                res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv);
 
82
                if (res < 0 && errno != EINTR) {
 
83
                        perror("select");
 
84
                        return -1;
 
85
                }
 
86
 
 
87
                if (FD_ISSET(drv->cmd_socket, &rfds)) {
 
88
                        res = recv(drv->cmd_socket, reply, *reply_len, 0);
 
89
                        if (res < 0) {
 
90
                                perror("recv");
 
91
                                return -1;
 
92
                        }
 
93
                        *reply_len = res;
 
94
                } else {
 
95
                        wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting "
 
96
                                   "for reply (cmd=%d)", cmd);
 
97
                        return -1;
 
98
                }
 
99
        }
 
100
 
 
101
        return 0;
 
102
}
 
103
 
 
104
                             
 
105
static int wpa_driver_privsep_set_wpa(void *priv, int enabled)
 
106
{
 
107
        struct wpa_driver_privsep_data *drv = priv;
 
108
        wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
 
109
        return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_WPA, &enabled,
 
110
                            sizeof(enabled), NULL, NULL);
 
111
}
 
112
 
 
113
 
 
114
static int wpa_driver_privsep_scan(void *priv, const u8 *ssid, size_t ssid_len)
 
115
{
 
116
        struct wpa_driver_privsep_data *drv = priv;
 
117
        wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv);
 
118
        return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len,
 
119
                            NULL, NULL);
 
120
}
 
121
 
 
122
 
 
123
static struct wpa_scan_results *
 
124
wpa_driver_privsep_get_scan_results2(void *priv)
 
125
{
 
126
        struct wpa_driver_privsep_data *drv = priv;
 
127
        int res, num;
 
128
        u8 *buf, *pos, *end;
 
129
        size_t reply_len = 60000;
 
130
        struct wpa_scan_results *results;
 
131
        struct wpa_scan_res *r;
 
132
 
 
133
        buf = os_malloc(reply_len);
 
134
        if (buf == NULL)
 
135
                return NULL;
 
136
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS,
 
137
                           NULL, 0, buf, &reply_len);
 
138
        if (res < 0) {
 
139
                os_free(buf);
 
140
                return NULL;
 
141
        }
 
142
 
 
143
        wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results",
 
144
                   (unsigned long) reply_len);
 
145
        if (reply_len < sizeof(int)) {
 
146
                wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu",
 
147
                           (unsigned long) reply_len);
 
148
                os_free(buf);
 
149
                return NULL;
 
150
        }
 
151
 
 
152
        pos = buf;
 
153
        end = buf + reply_len;
 
154
        os_memcpy(&num, pos, sizeof(int));
 
155
        if (num < 0 || num > 1000) {
 
156
                os_free(buf);
 
157
                return NULL;
 
158
        }
 
159
        pos += sizeof(int);
 
160
 
 
161
        results = os_zalloc(sizeof(*results));
 
162
        if (results == NULL) {
 
163
                os_free(buf);
 
164
                return NULL;
 
165
        }
 
166
 
 
167
        results->res = os_zalloc(num * sizeof(struct wpa_scan_res *));
 
168
        if (results->res == NULL) {
 
169
                os_free(results);
 
170
                os_free(buf);
 
171
                return NULL;
 
172
        }
 
173
 
 
174
        while (results->num < (size_t) num && pos + sizeof(int) < end) {
 
175
                int len;
 
176
                os_memcpy(&len, pos, sizeof(int));
 
177
                pos += sizeof(int);
 
178
                if (len < 0 || len > 10000 || pos + len > end)
 
179
                        break;
 
180
 
 
181
                r = os_malloc(len);
 
182
                if (r == NULL)
 
183
                        break;
 
184
                os_memcpy(r, pos, len);
 
185
                pos += len;
 
186
                if (sizeof(*r) + r->ie_len > (size_t) len) {
 
187
                        os_free(r);
 
188
                        break;
 
189
                }
 
190
 
 
191
                results->res[results->num++] = r;
 
192
        }
 
193
 
 
194
        os_free(buf);
 
195
        return results;
 
196
}
 
197
 
 
198
 
 
199
static int wpa_driver_privsep_set_key(void *priv, wpa_alg alg, const u8 *addr,
 
200
                                   int key_idx, int set_tx,
 
201
                                   const u8 *seq, size_t seq_len,
 
202
                                   const u8 *key, size_t key_len)
 
203
{
 
204
        struct wpa_driver_privsep_data *drv = priv;
 
205
        struct privsep_cmd_set_key cmd;
 
206
 
 
207
        wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
 
208
                   __func__, priv, alg, key_idx, set_tx);
 
209
 
 
210
        os_memset(&cmd, 0, sizeof(cmd));
 
211
        cmd.alg = alg;
 
212
        if (addr)
 
213
                os_memcpy(cmd.addr, addr, ETH_ALEN);
 
214
        else
 
215
                os_memset(cmd.addr, 0xff, ETH_ALEN);
 
216
        cmd.key_idx = key_idx;
 
217
        cmd.set_tx = set_tx;
 
218
        if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
 
219
                os_memcpy(cmd.seq, seq, seq_len);
 
220
                cmd.seq_len = seq_len;
 
221
        }
 
222
        if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
 
223
                os_memcpy(cmd.key, key, key_len);
 
224
                cmd.key_len = key_len;
 
225
        }
 
226
 
 
227
        return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
 
228
                            NULL, NULL);
 
229
}
 
230
 
 
231
 
 
232
static int wpa_driver_privsep_associate(
 
233
        void *priv, struct wpa_driver_associate_params *params)
 
234
{
 
235
        struct wpa_driver_privsep_data *drv = priv;
 
236
        struct privsep_cmd_associate *data;
 
237
        int res;
 
238
        size_t buflen;
 
239
 
 
240
        wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
 
241
                   "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
 
242
                   __func__, priv, params->freq, params->pairwise_suite,
 
243
                   params->group_suite, params->key_mgmt_suite,
 
244
                   params->auth_alg, params->mode);
 
245
 
 
246
        buflen = sizeof(*data) + params->wpa_ie_len;
 
247
        data = os_zalloc(buflen);
 
248
        if (data == NULL)
 
249
                return -1;
 
250
 
 
251
        if (params->bssid)
 
252
                os_memcpy(data->bssid, params->bssid, ETH_ALEN);
 
253
        os_memcpy(data->ssid, params->ssid, params->ssid_len);
 
254
        data->ssid_len = params->ssid_len;
 
255
        data->freq = params->freq;
 
256
        data->pairwise_suite = params->pairwise_suite;
 
257
        data->group_suite = params->group_suite;
 
258
        data->key_mgmt_suite = params->key_mgmt_suite;
 
259
        data->auth_alg = params->auth_alg;
 
260
        data->mode = params->mode;
 
261
        data->wpa_ie_len = params->wpa_ie_len;
 
262
        if (params->wpa_ie)
 
263
                os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len);
 
264
        /* TODO: add support for other assoc parameters */
 
265
 
 
266
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen,
 
267
                           NULL, NULL);
 
268
        os_free(data);
 
269
 
 
270
        return res;
 
271
}
 
272
 
 
273
 
 
274
static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid)
 
275
{
 
276
        struct wpa_driver_privsep_data *drv = priv;
 
277
        int res;
 
278
        size_t len = ETH_ALEN;
 
279
 
 
280
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len);
 
281
        if (res < 0 || len != ETH_ALEN)
 
282
                return -1;
 
283
        return 0;
 
284
}
 
285
 
 
286
 
 
287
static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid)
 
288
{
 
289
        struct wpa_driver_privsep_data *drv = priv;
 
290
        int res, ssid_len;
 
291
        u8 reply[sizeof(int) + 32];
 
292
        size_t len = sizeof(reply);
 
293
 
 
294
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len);
 
295
        if (res < 0 || len < sizeof(int))
 
296
                return -1;
 
297
        os_memcpy(&ssid_len, reply, sizeof(int));
 
298
        if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) {
 
299
                wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply");
 
300
                return -1;
 
301
        }
 
302
        os_memcpy(ssid, &reply[sizeof(int)], ssid_len);
 
303
        return ssid_len;
 
304
}
 
305
 
 
306
 
 
307
static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr,
 
308
                                          int reason_code)
 
309
{
 
310
        //struct wpa_driver_privsep_data *drv = priv;
 
311
        wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
 
312
                   __func__, MAC2STR(addr), reason_code);
 
313
        wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
 
314
        return 0;
 
315
}
 
316
 
 
317
 
 
318
static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr,
 
319
                                        int reason_code)
 
320
{
 
321
        //struct wpa_driver_privsep_data *drv = priv;
 
322
        wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d",
 
323
                   __func__, MAC2STR(addr), reason_code);
 
324
        wpa_printf(MSG_DEBUG, "%s - TODO", __func__);
 
325
        return 0;
 
326
}
 
327
 
 
328
 
 
329
static void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event,
 
330
                                           u8 *buf, size_t len)
 
331
{
 
332
        union wpa_event_data data;
 
333
        int inc_data = 0;
 
334
        u8 *pos, *end;
 
335
        int ie_len;
 
336
 
 
337
        os_memset(&data, 0, sizeof(data));
 
338
 
 
339
        pos = buf;
 
340
        end = buf + len;
 
341
 
 
342
        if (end - pos < (int) sizeof(int))
 
343
                return;
 
344
        os_memcpy(&ie_len, pos, sizeof(int));
 
345
        pos += sizeof(int);
 
346
        if (ie_len < 0 || ie_len > end - pos)
 
347
                return;
 
348
        if (ie_len) {
 
349
                data.assoc_info.req_ies = pos;
 
350
                data.assoc_info.req_ies_len = ie_len;
 
351
                pos += ie_len;
 
352
                inc_data = 1;
 
353
        }
 
354
 
 
355
        wpa_supplicant_event(ctx, event, inc_data ? &data : NULL);
 
356
}
 
357
 
 
358
 
 
359
static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf,
 
360
                                                      size_t len)
 
361
{
 
362
        union wpa_event_data data;
 
363
        int ievent;
 
364
 
 
365
        if (len < sizeof(int) ||
 
366
            len - sizeof(int) > sizeof(data.interface_status.ifname))
 
367
                return;
 
368
 
 
369
        os_memcpy(&ievent, buf, sizeof(int));
 
370
 
 
371
        os_memset(&data, 0, sizeof(data));
 
372
        data.interface_status.ievent = ievent;
 
373
        os_memcpy(data.interface_status.ifname, buf + sizeof(int),
 
374
                  len - sizeof(int));
 
375
        wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data);
 
376
}
 
377
 
 
378
 
 
379
static void wpa_driver_privsep_event_michael_mic_failure(
 
380
        void *ctx, u8 *buf, size_t len)
 
381
{
 
382
        union wpa_event_data data;
 
383
 
 
384
        if (len != sizeof(int))
 
385
                return;
 
386
 
 
387
        os_memset(&data, 0, sizeof(data));
 
388
        os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int));
 
389
        wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
 
390
}
 
391
 
 
392
 
 
393
static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf,
 
394
                                                     size_t len)
 
395
{
 
396
        union wpa_event_data data;
 
397
 
 
398
        if (len != sizeof(struct pmkid_candidate))
 
399
                return;
 
400
 
 
401
        os_memset(&data, 0, sizeof(data));
 
402
        os_memcpy(&data.pmkid_candidate, buf, len);
 
403
        wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data);
 
404
}
 
405
 
 
406
 
 
407
static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len)
 
408
{
 
409
        union wpa_event_data data;
 
410
 
 
411
        if (len != ETH_ALEN)
 
412
                return;
 
413
 
 
414
        os_memset(&data, 0, sizeof(data));
 
415
        os_memcpy(data.stkstart.peer, buf, ETH_ALEN);
 
416
        wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
 
417
}
 
418
 
 
419
 
 
420
static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf,
 
421
                                                 size_t len)
 
422
{
 
423
        union wpa_event_data data;
 
424
 
 
425
        if (len < sizeof(int) + ETH_ALEN)
 
426
                return;
 
427
 
 
428
        os_memset(&data, 0, sizeof(data));
 
429
        os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int));
 
430
        os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN);
 
431
        data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN;
 
432
        data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN;
 
433
        wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data);
 
434
}
 
435
 
 
436
 
 
437
static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len)
 
438
{
 
439
        if (len < ETH_ALEN)
 
440
                return;
 
441
 
 
442
        wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN);
 
443
}
 
444
 
 
445
 
 
446
static void wpa_driver_privsep_receive(int sock, void *eloop_ctx,
 
447
                                       void *sock_ctx)
 
448
{
 
449
        struct wpa_driver_privsep_data *drv = eloop_ctx;
 
450
        u8 *buf, *event_buf;
 
451
        size_t event_len;
 
452
        int res, event;
 
453
        enum privsep_event e;
 
454
        struct sockaddr_un from;
 
455
        socklen_t fromlen = sizeof(from);
 
456
        const size_t buflen = 2000;
 
457
 
 
458
        buf = os_malloc(buflen);
 
459
        if (buf == NULL)
 
460
                return;
 
461
        res = recvfrom(sock, buf, buflen, 0,
 
462
                       (struct sockaddr *) &from, &fromlen);
 
463
        if (res < 0) {
 
464
                perror("recvfrom(priv_socket)");
 
465
                os_free(buf);
 
466
                return;
 
467
        }
 
468
 
 
469
        wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res);
 
470
 
 
471
        if (res < (int) sizeof(int)) {
 
472
                wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res);
 
473
                return;
 
474
        }
 
475
 
 
476
        os_memcpy(&event, buf, sizeof(int));
 
477
        event_buf = &buf[sizeof(int)];
 
478
        event_len = res - sizeof(int);
 
479
        wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%d)",
 
480
                   event, event_len);
 
481
 
 
482
        e = event;
 
483
        switch (e) {
 
484
        case PRIVSEP_EVENT_SCAN_RESULTS:
 
485
                wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL);
 
486
                break;
 
487
        case PRIVSEP_EVENT_ASSOC:
 
488
                wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC,
 
489
                                               event_buf, event_len);
 
490
                break;
 
491
        case PRIVSEP_EVENT_DISASSOC:
 
492
                wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
 
493
                break;
 
494
        case PRIVSEP_EVENT_ASSOCINFO:
 
495
                wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO,
 
496
                                               event_buf, event_len);
 
497
                break;
 
498
        case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE:
 
499
                wpa_driver_privsep_event_michael_mic_failure(
 
500
                        drv->ctx, event_buf, event_len);
 
501
                break;
 
502
        case PRIVSEP_EVENT_INTERFACE_STATUS:
 
503
                wpa_driver_privsep_event_interface_status(drv->ctx, event_buf,
 
504
                                                          event_len);
 
505
                break;
 
506
        case PRIVSEP_EVENT_PMKID_CANDIDATE:
 
507
                wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf,
 
508
                                                         event_len);
 
509
                break;
 
510
        case PRIVSEP_EVENT_STKSTART:
 
511
                wpa_driver_privsep_event_stkstart(drv->ctx, event_buf,
 
512
                                                  event_len);
 
513
                break;
 
514
        case PRIVSEP_EVENT_FT_RESPONSE:
 
515
                wpa_driver_privsep_event_ft_response(drv->ctx, event_buf,
 
516
                                                     event_len);
 
517
                break;
 
518
        case PRIVSEP_EVENT_RX_EAPOL:
 
519
                wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf,
 
520
                                                  event_len);
 
521
        }
 
522
 
 
523
        os_free(buf);
 
524
}
 
525
 
 
526
 
 
527
static void * wpa_driver_privsep_init(void *ctx, const char *ifname)
 
528
{
 
529
        struct wpa_driver_privsep_data *drv;
 
530
 
 
531
        drv = os_zalloc(sizeof(*drv));
 
532
        if (drv == NULL)
 
533
                return NULL;
 
534
        drv->ctx = ctx;
 
535
        drv->priv_socket = -1;
 
536
        drv->cmd_socket = -1;
 
537
        os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
 
538
 
 
539
        return drv;
 
540
}
 
541
 
 
542
 
 
543
static void wpa_driver_privsep_deinit(void *priv)
 
544
{
 
545
        struct wpa_driver_privsep_data *drv = priv;
 
546
 
 
547
        if (drv->priv_socket >= 0) {
 
548
                wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER);
 
549
                eloop_unregister_read_sock(drv->priv_socket);
 
550
                close(drv->priv_socket);
 
551
        }
 
552
 
 
553
        if (drv->own_socket_path) {
 
554
                unlink(drv->own_socket_path);
 
555
                os_free(drv->own_socket_path);
 
556
        }
 
557
 
 
558
        if (drv->cmd_socket >= 0) {
 
559
                eloop_unregister_read_sock(drv->cmd_socket);
 
560
                close(drv->cmd_socket);
 
561
        }
 
562
 
 
563
        if (drv->own_cmd_path) {
 
564
                unlink(drv->own_cmd_path);
 
565
                os_free(drv->own_cmd_path);
 
566
        }
 
567
 
 
568
        os_free(drv);
 
569
}
 
570
 
 
571
 
 
572
static int wpa_driver_privsep_set_param(void *priv, const char *param)
 
573
{
 
574
        struct wpa_driver_privsep_data *drv = priv;
 
575
        const char *pos;
 
576
        char *own_dir, *priv_dir;
 
577
        static unsigned int counter = 0;
 
578
        size_t len;
 
579
        struct sockaddr_un addr;
 
580
 
 
581
        wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
 
582
        if (param == NULL)
 
583
                pos = NULL;
 
584
        else
 
585
                pos = os_strstr(param, "own_dir=");
 
586
        if (pos) {
 
587
                char *end;
 
588
                own_dir = os_strdup(pos + 8);
 
589
                if (own_dir == NULL)
 
590
                        return -1;
 
591
                end = os_strchr(own_dir, ' ');
 
592
                if (end)
 
593
                        *end = '\0';
 
594
        } else {
 
595
                own_dir = os_strdup("/tmp");
 
596
                if (own_dir == NULL)
 
597
                        return -1;
 
598
        }
 
599
 
 
600
        if (param == NULL)
 
601
                pos = NULL;
 
602
        else
 
603
                pos = os_strstr(param, "priv_dir=");
 
604
        if (pos) {
 
605
                char *end;
 
606
                priv_dir = os_strdup(pos + 9);
 
607
                if (priv_dir == NULL) {
 
608
                        os_free(own_dir);
 
609
                        return -1;
 
610
                }
 
611
                end = os_strchr(priv_dir, ' ');
 
612
                if (end)
 
613
                        *end = '\0';
 
614
        } else {
 
615
                priv_dir = os_strdup("/var/run/wpa_priv");
 
616
                if (priv_dir == NULL) {
 
617
                        os_free(own_dir);
 
618
                        return -1;
 
619
                }
 
620
        }
 
621
 
 
622
        len = os_strlen(own_dir) + 50;
 
623
        drv->own_socket_path = os_malloc(len);
 
624
        if (drv->own_socket_path == NULL) {
 
625
                os_free(priv_dir);
 
626
                os_free(own_dir);
 
627
                return -1;
 
628
        }
 
629
        os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
 
630
                    own_dir, getpid(), counter++);
 
631
 
 
632
        len = os_strlen(own_dir) + 50;
 
633
        drv->own_cmd_path = os_malloc(len);
 
634
        if (drv->own_cmd_path == NULL) {
 
635
                os_free(drv->own_socket_path);
 
636
                drv->own_socket_path = NULL;
 
637
                os_free(priv_dir);
 
638
                os_free(own_dir);
 
639
                return -1;
 
640
        }
 
641
        os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
 
642
                    own_dir, getpid(), counter++);
 
643
 
 
644
        os_free(own_dir);
 
645
 
 
646
        drv->priv_addr.sun_family = AF_UNIX;
 
647
        os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
 
648
                    "%s/%s", priv_dir, drv->ifname);
 
649
        os_free(priv_dir);
 
650
 
 
651
        drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
 
652
        if (drv->priv_socket < 0) {
 
653
                perror("socket(PF_UNIX)");
 
654
                os_free(drv->own_socket_path);
 
655
                drv->own_socket_path = NULL;
 
656
                return -1;
 
657
        }
 
658
 
 
659
        os_memset(&addr, 0, sizeof(addr));
 
660
        addr.sun_family = AF_UNIX;
 
661
        os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
 
662
        if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
 
663
            0) {
 
664
                perror("bind(PF_UNIX)");
 
665
                close(drv->priv_socket);
 
666
                drv->priv_socket = -1;
 
667
                unlink(drv->own_socket_path);
 
668
                os_free(drv->own_socket_path);
 
669
                drv->own_socket_path = NULL;
 
670
                return -1;
 
671
        }
 
672
 
 
673
        eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
 
674
                                 drv, NULL);
 
675
 
 
676
        drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
 
677
        if (drv->cmd_socket < 0) {
 
678
                perror("socket(PF_UNIX)");
 
679
                os_free(drv->own_cmd_path);
 
680
                drv->own_cmd_path = NULL;
 
681
                return -1;
 
682
        }
 
683
 
 
684
        os_memset(&addr, 0, sizeof(addr));
 
685
        addr.sun_family = AF_UNIX;
 
686
        os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
 
687
        if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
 
688
        {
 
689
                perror("bind(PF_UNIX)");
 
690
                close(drv->cmd_socket);
 
691
                drv->cmd_socket = -1;
 
692
                unlink(drv->own_cmd_path);
 
693
                os_free(drv->own_cmd_path);
 
694
                drv->own_cmd_path = NULL;
 
695
                return -1;
 
696
        }
 
697
 
 
698
        if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
 
699
                wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
 
700
                return -1;
 
701
        }
 
702
 
 
703
        return 0;
 
704
}
 
705
 
 
706
 
 
707
static int wpa_driver_privsep_get_capa(void *priv,
 
708
                                       struct wpa_driver_capa *capa)
 
709
{
 
710
        struct wpa_driver_privsep_data *drv = priv;
 
711
        int res;
 
712
        size_t len = sizeof(*capa);
 
713
 
 
714
        res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len);
 
715
        if (res < 0 || len != sizeof(*capa))
 
716
                return -1;
 
717
        return 0;
 
718
}
 
719
 
 
720
 
 
721
static const u8 * wpa_driver_privsep_get_mac_addr(void *priv)
 
722
{
 
723
        struct wpa_driver_privsep_data *drv = priv;
 
724
        wpa_printf(MSG_DEBUG, "%s", __func__);
 
725
        return drv->own_addr;
 
726
}
 
727
 
 
728
 
 
729
struct wpa_driver_ops wpa_driver_privsep_ops = {
 
730
        "privsep",
 
731
        "wpa_supplicant privilege separated driver",
 
732
        wpa_driver_privsep_get_bssid,
 
733
        wpa_driver_privsep_get_ssid,
 
734
        wpa_driver_privsep_set_wpa,
 
735
        wpa_driver_privsep_set_key,
 
736
        wpa_driver_privsep_init,
 
737
        wpa_driver_privsep_deinit,
 
738
        wpa_driver_privsep_set_param,
 
739
        NULL /* set_countermeasures */,
 
740
        NULL /* set_drop_unencrypted */,
 
741
        wpa_driver_privsep_scan,
 
742
        NULL /*  get_scan_results */,
 
743
        wpa_driver_privsep_deauthenticate,
 
744
        wpa_driver_privsep_disassociate,
 
745
        wpa_driver_privsep_associate,
 
746
        NULL /* set_auth_alg */,
 
747
        NULL /* add_pmkid */,
 
748
        NULL /* remove_pmkid */,
 
749
        NULL /* flush_pmkid */,
 
750
        wpa_driver_privsep_get_capa,
 
751
        NULL /* poll */,
 
752
        NULL /* get_ifname */,
 
753
        wpa_driver_privsep_get_mac_addr,
 
754
        NULL /* send_eapol */,
 
755
        NULL /* set_operstate */,
 
756
        NULL /* mlme_setprotection */,
 
757
        NULL /* get_hw_feature_data */,
 
758
        NULL /* set_channel */,
 
759
        NULL /* set_ssid */,
 
760
        NULL /* set_bssid */,
 
761
        NULL /* send_mlme */,
 
762
        NULL /* mlme_add_sta */,
 
763
        NULL /* mlme_remove_sta */,
 
764
        NULL /* update_ft_ies */,
 
765
        NULL /* send_ft_action */,
 
766
        wpa_driver_privsep_get_scan_results2
 
767
};
 
768
 
 
769
 
 
770
struct wpa_driver_ops *wpa_supplicant_drivers[] =
 
771
{
 
772
        &wpa_driver_privsep_ops,
 
773
        NULL
 
774
};