~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid-updates

« back to all changes in this revision

Viewing changes to ctrl_iface_udp.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.1.5 upstream) (3 etch)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20061005080401-r8lqlix4390yos7b
Tags: 0.5.5-2
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include "ctrl_iface.h"
23
23
#include "wpa_ctrl.h"
24
24
 
 
25
 
 
26
#define COOKIE_LEN 8
 
27
 
25
28
/* Per-interface ctrl_iface */
26
29
 
27
30
/**
44
47
        struct wpa_supplicant *wpa_s;
45
48
        int sock;
46
49
        struct wpa_ctrl_dst *ctrl_dst;
 
50
        u8 cookie[COOKIE_LEN];
47
51
};
48
52
 
49
53
 
120
124
}
121
125
 
122
126
 
 
127
static char *
 
128
wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
 
129
                                     size_t *reply_len)
 
130
{
 
131
        char *reply;
 
132
        reply = malloc(7 + 2 * COOKIE_LEN + 1);
 
133
        if (reply == NULL) {
 
134
                *reply_len = 1;
 
135
                return NULL;
 
136
        }
 
137
 
 
138
        memcpy(reply, "COOKIE=", 7);
 
139
        wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
 
140
                         priv->cookie, COOKIE_LEN);
 
141
 
 
142
        *reply_len = 7 + 2 * COOKIE_LEN;
 
143
        return reply;
 
144
}
 
145
 
 
146
 
123
147
static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
124
148
                                              void *sock_ctx)
125
149
{
126
150
        struct wpa_supplicant *wpa_s = eloop_ctx;
127
151
        struct ctrl_iface_priv *priv = sock_ctx;
128
 
        char buf[256];
 
152
        char buf[256], *pos;
129
153
        int res;
130
154
        struct sockaddr_in from;
131
155
        socklen_t fromlen = sizeof(from);
132
156
        char *reply = NULL;
133
157
        size_t reply_len = 0;
134
158
        int new_attached = 0;
 
159
        u8 cookie[COOKIE_LEN];
135
160
 
136
161
        res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
137
162
                       (struct sockaddr *) &from, &fromlen);
139
164
                perror("recvfrom(ctrl_iface)");
140
165
                return;
141
166
        }
 
167
        if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
 
168
                /*
 
169
                 * The OS networking stack is expected to drop this kind of
 
170
                 * frames since the socket is bound to only localhost address.
 
171
                 * Just in case, drop the frame if it is coming from any other
 
172
                 * address.
 
173
                 */
 
174
                wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
 
175
                           "source %s", inet_ntoa(from.sin_addr));
 
176
                return;
 
177
        }
142
178
        buf[res] = '\0';
143
179
 
144
 
        if (strcmp(buf, "ATTACH") == 0) {
 
180
        if (strcmp(buf, "GET_COOKIE") == 0) {
 
181
                reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
 
182
                goto done;
 
183
        }
 
184
 
 
185
        /*
 
186
         * Require that the client includes a prefix with the 'cookie' value
 
187
         * fetched with GET_COOKIE command. This is used to verify that the
 
188
         * client has access to a bidirectional link over UDP in order to
 
189
         * avoid attacks using forged localhost IP address even if the OS does
 
190
         * not block such frames from remote destinations.
 
191
         */
 
192
        if (strncmp(buf, "COOKIE=", 7) != 0) {
 
193
                wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
 
194
                           "drop request");
 
195
                return;
 
196
        }
 
197
 
 
198
        if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
 
199
                wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
 
200
                           "request - drop request");
 
201
                return;
 
202
        }
 
203
 
 
204
        if (memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
 
205
                wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
 
206
                           "drop request");
 
207
                return;
 
208
        }
 
209
 
 
210
        pos = buf + 7 + 2 * COOKIE_LEN;
 
211
        while (*pos == ' ')
 
212
                pos++;
 
213
 
 
214
        if (strcmp(pos, "ATTACH") == 0) {
145
215
                if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
146
216
                        reply_len = 1;
147
217
                else {
148
218
                        new_attached = 1;
149
219
                        reply_len = 2;
150
220
                }
151
 
        } else if (strcmp(buf, "DETACH") == 0) {
 
221
        } else if (strcmp(pos, "DETACH") == 0) {
152
222
                if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
153
223
                        reply_len = 1;
154
224
                else
155
225
                        reply_len = 2;
156
 
        } else if (strncmp(buf, "LEVEL ", 6) == 0) {
 
226
        } else if (strncmp(pos, "LEVEL ", 6) == 0) {
157
227
                if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
158
 
                                                    buf + 6))
 
228
                                                    pos + 6))
159
229
                        reply_len = 1;
160
230
                else
161
231
                        reply_len = 2;
162
232
        } else {
163
 
                reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
 
233
                reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
164
234
                                                          &reply_len);
165
235
        }
166
236
 
 
237
 done:
167
238
        if (reply) {
168
239
                sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
169
240
                       fromlen);
192
263
                return NULL;
193
264
        priv->wpa_s = wpa_s;
194
265
        priv->sock = -1;
 
266
        os_get_random(priv->cookie, COOKIE_LEN);
195
267
 
196
268
        if (wpa_s->conf->ctrl_interface == NULL)
197
269
                return priv;
219
291
fail:
220
292
        if (priv->sock >= 0)
221
293
                close(priv->sock);
 
294
        free(priv);
222
295
        return NULL;
223
296
}
224
297
 
315
388
 
316
389
struct ctrl_iface_global_priv {
317
390
        int sock;
 
391
        u8 cookie[COOKIE_LEN];
318
392
};
319
393
 
320
394
 
 
395
static char *
 
396
wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
 
397
                                 size_t *reply_len)
 
398
{
 
399
        char *reply;
 
400
        reply = malloc(7 + 2 * COOKIE_LEN + 1);
 
401
        if (reply == NULL) {
 
402
                *reply_len = 1;
 
403
                return NULL;
 
404
        }
 
405
 
 
406
        memcpy(reply, "COOKIE=", 7);
 
407
        wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
 
408
                         priv->cookie, COOKIE_LEN);
 
409
 
 
410
        *reply_len = 7 + 2 * COOKIE_LEN;
 
411
        return reply;
 
412
}
 
413
 
 
414
 
321
415
static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
322
416
                                                     void *sock_ctx)
323
417
{
324
418
        struct wpa_global *global = eloop_ctx;
325
 
        char buf[256];
 
419
        struct ctrl_iface_global_priv *priv = sock_ctx;
 
420
        char buf[256], *pos;
326
421
        int res;
327
422
        struct sockaddr_in from;
328
423
        socklen_t fromlen = sizeof(from);
329
424
        char *reply;
330
425
        size_t reply_len;
 
426
        u8 cookie[COOKIE_LEN];
331
427
 
332
428
        res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
333
429
                       (struct sockaddr *) &from, &fromlen);
335
431
                perror("recvfrom(ctrl_iface)");
336
432
                return;
337
433
        }
 
434
        if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
 
435
                /*
 
436
                 * The OS networking stack is expected to drop this kind of
 
437
                 * frames since the socket is bound to only localhost address.
 
438
                 * Just in case, drop the frame if it is coming from any other
 
439
                 * address.
 
440
                 */
 
441
                wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
 
442
                           "source %s", inet_ntoa(from.sin_addr));
 
443
                return;
 
444
        }
338
445
        buf[res] = '\0';
339
446
 
340
 
        reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
 
447
        if (strcmp(buf, "GET_COOKIE") == 0) {
 
448
                reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
 
449
                goto done;
 
450
        }
 
451
 
 
452
        if (strncmp(buf, "COOKIE=", 7) != 0) {
 
453
                wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
 
454
                           "drop request");
 
455
                return;
 
456
        }
 
457
 
 
458
        if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
 
459
                wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
 
460
                           "request - drop request");
 
461
                return;
 
462
        }
 
463
 
 
464
        if (memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
 
465
                wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
 
466
                           "drop request");
 
467
                return;
 
468
        }
 
469
 
 
470
        pos = buf + 7 + 2 * COOKIE_LEN;
 
471
        while (*pos == ' ')
 
472
                pos++;
 
473
 
 
474
        reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
341
475
                                                         &reply_len);
342
476
 
 
477
 done:
343
478
        if (reply) {
344
479
                sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
345
480
                       fromlen);
361
496
        if (priv == NULL)
362
497
                return NULL;
363
498
        priv->sock = -1;
 
499
        os_get_random(priv->cookie, COOKIE_LEN);
364
500
 
365
501
        if (global->params.ctrl_interface == NULL)
366
502
                return priv;
385
521
 
386
522
        eloop_register_read_sock(priv->sock,
387
523
                                 wpa_supplicant_global_ctrl_iface_receive,
388
 
                                 global, NULL);
 
524
                                 global, priv);
389
525
 
390
526
        return priv;
391
527