~ubuntu-branches/ubuntu/maverick/wpasupplicant/maverick

« back to all changes in this revision

Viewing changes to radius_client.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* 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:
1
1
/*
2
 
 * Host AP (software wireless LAN access point) user space daemon for
3
 
 * Host AP kernel driver / RADIUS client / modified for eapol_test
4
 
 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
 
2
 * hostapd / RADIUS client
 
3
 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5
4
 *
6
5
 * This program is free software; you can redistribute it and/or modify
7
6
 * it under the terms of the GNU General Public License version 2 as
8
 
 * published by the Free Software Foundation. See README and COPYING for
9
 
 * more details.
 
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.
10
13
 */
11
14
 
12
 
#include <stdlib.h>
13
 
#include <stdio.h>
14
 
#include <unistd.h>
15
 
#include <netinet/in.h>
16
 
#include <string.h>
17
 
#include <time.h>
18
 
#include <sys/types.h>
19
 
#include <sys/socket.h>
20
 
#include <arpa/inet.h>
 
15
#include "includes.h"
21
16
 
22
 
#include "common.h"
23
 
#include "wpa.h"
24
 
#include "config_ssid.h"
25
 
#include "wpa_supplicant.h"
26
 
#include "wpa_supplicant_i.h"
 
17
#include "hostapd.h"
27
18
#include "radius.h"
28
19
#include "radius_client.h"
29
20
#include "eloop.h"
30
 
#include "l2_packet.h"
31
 
 
32
 
#include "wpa_supplicant.h"
33
 
#define hostapd_logger(h, a, m, l, t...) wpa_printf(MSG_DEBUG, t)
34
 
#define HOSTAPD_DEBUG(l, a...) wpa_printf(MSG_DEBUG, a)
35
 
#define HOSTAPD_DEBUG_COND(l) 1
36
21
 
37
22
/* Defaults for RADIUS retransmit values (exponential backoff) */
38
 
#define RADIUS_CLIENT_FIRST_WAIT 1 /* seconds */
 
23
#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */
39
24
#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
40
25
#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
41
26
                                      * before entry is removed from retransmit
47
32
                                      * many failed retry attempts */
48
33
 
49
34
 
 
35
struct radius_rx_handler {
 
36
        RadiusRxResult (*handler)(struct radius_msg *msg,
 
37
                                  struct radius_msg *req,
 
38
                                  u8 *shared_secret, size_t shared_secret_len,
 
39
                                  void *data);
 
40
        void *data;
 
41
};
 
42
 
 
43
 
 
44
/* RADIUS message retransmit list */
 
45
struct radius_msg_list {
 
46
        u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages
 
47
                            * for the same STA. */
 
48
        struct radius_msg *msg;
 
49
        RadiusType msg_type;
 
50
        os_time_t first_try;
 
51
        os_time_t next_try;
 
52
        int attempts;
 
53
        int next_wait;
 
54
        struct os_time last_attempt;
 
55
 
 
56
        u8 *shared_secret;
 
57
        size_t shared_secret_len;
 
58
 
 
59
        /* TODO: server config with failover to backup server(s) */
 
60
 
 
61
        struct radius_msg_list *next;
 
62
};
 
63
 
 
64
 
 
65
struct radius_client_data {
 
66
        void *ctx;
 
67
        struct hostapd_radius_servers *conf;
 
68
 
 
69
        int auth_serv_sock; /* socket for authentication RADIUS messages */
 
70
        int acct_serv_sock; /* socket for accounting RADIUS messages */
 
71
        int auth_serv_sock6;
 
72
        int acct_serv_sock6;
 
73
        int auth_sock; /* currently used socket */
 
74
        int acct_sock; /* currently used socket */
 
75
 
 
76
        struct radius_rx_handler *auth_handlers;
 
77
        size_t num_auth_handlers;
 
78
        struct radius_rx_handler *acct_handlers;
 
79
        size_t num_acct_handlers;
 
80
 
 
81
        struct radius_msg_list *msgs;
 
82
        size_t num_msgs;
 
83
 
 
84
        u8 next_radius_identifier;
 
85
};
 
86
 
50
87
 
51
88
static int
52
 
radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
 
89
radius_change_server(struct radius_client_data *radius,
 
90
                     struct hostapd_radius_server *nserv,
53
91
                     struct hostapd_radius_server *oserv,
54
 
                     int sock, int auth);
 
92
                     int sock, int sock6, int auth);
 
93
static int radius_client_init_acct(struct radius_client_data *radius);
 
94
static int radius_client_init_auth(struct radius_client_data *radius);
55
95
 
56
96
 
57
97
static void radius_client_msg_free(struct radius_msg_list *req)
62
102
}
63
103
 
64
104
 
65
 
int radius_client_register(struct wpa_supplicant *wpa_s, RadiusType msg_type,
66
 
                           RadiusRxResult (*handler)(struct wpa_supplicant *wpa_s,
67
 
                                                     struct radius_msg *msg,
 
105
int radius_client_register(struct radius_client_data *radius,
 
106
                           RadiusType msg_type,
 
107
                           RadiusRxResult (*handler)(struct radius_msg *msg,
68
108
                                                     struct radius_msg *req,
69
109
                                                     u8 *shared_secret,
70
110
                                                     size_t shared_secret_len,
75
115
        size_t *num;
76
116
 
77
117
        if (msg_type == RADIUS_ACCT) {
78
 
                handlers = &wpa_s->radius->acct_handlers;
79
 
                num = &wpa_s->radius->num_acct_handlers;
 
118
                handlers = &radius->acct_handlers;
 
119
                num = &radius->num_acct_handlers;
80
120
        } else {
81
 
                handlers = &wpa_s->radius->auth_handlers;
82
 
                num = &wpa_s->radius->num_auth_handlers;
 
121
                handlers = &radius->auth_handlers;
 
122
                num = &radius->num_auth_handlers;
83
123
        }
84
124
 
85
125
        newh = (struct radius_rx_handler *)
97
137
}
98
138
 
99
139
 
100
 
static int radius_client_retransmit(struct wpa_supplicant *wpa_s,
101
 
                                    struct radius_msg_list *entry, time_t now)
102
 
{
 
140
static void radius_client_handle_send_error(struct radius_client_data *radius,
 
141
                                            int s, RadiusType msg_type)
 
142
{
 
143
#ifndef CONFIG_NATIVE_WINDOWS
 
144
        int _errno = errno;
 
145
        perror("send[RADIUS]");
 
146
        if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL) {
 
147
                hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
148
                               HOSTAPD_LEVEL_INFO,
 
149
                               "Send failed - maybe interface status changed -"
 
150
                               " try to connect again");
 
151
                eloop_unregister_read_sock(s);
 
152
                close(s);
 
153
                if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM)
 
154
                        radius_client_init_acct(radius);
 
155
                else
 
156
                        radius_client_init_auth(radius);
 
157
        }
 
158
#endif /* CONFIG_NATIVE_WINDOWS */
 
159
}
 
160
 
 
161
 
 
162
static int radius_client_retransmit(struct radius_client_data *radius,
 
163
                                    struct radius_msg_list *entry,
 
164
                                    os_time_t now)
 
165
{
 
166
        struct hostapd_radius_servers *conf = radius->conf;
103
167
        int s;
104
168
 
105
169
        if (entry->msg_type == RADIUS_ACCT ||
106
 
            entry->msg_type == RADIUS_ACCT_INTERIM)
107
 
                s = wpa_s->radius->acct_serv_sock;
108
 
        else
109
 
                s = wpa_s->radius->auth_serv_sock;
 
170
            entry->msg_type == RADIUS_ACCT_INTERIM) {
 
171
                s = radius->acct_sock;
 
172
                if (entry->attempts == 0)
 
173
                        conf->acct_server->requests++;
 
174
                else {
 
175
                        conf->acct_server->timeouts++;
 
176
                        conf->acct_server->retransmissions++;
 
177
                }
 
178
        } else {
 
179
                s = radius->auth_sock;
 
180
                if (entry->attempts == 0)
 
181
                        conf->auth_server->requests++;
 
182
                else {
 
183
                        conf->auth_server->timeouts++;
 
184
                        conf->auth_server->retransmissions++;
 
185
                }
 
186
        }
110
187
 
111
188
        /* retransmit; remove entry if too many attempts */
112
189
        entry->attempts++;
113
 
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
114
 
                      "\n", entry->msg->hdr->identifier);
 
190
        hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
 
191
                       HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
 
192
                       entry->msg->hdr->identifier);
115
193
 
 
194
        os_get_time(&entry->last_attempt);
116
195
        if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
117
 
                perror("send[RADIUS]");
 
196
                radius_client_handle_send_error(radius, s, entry->msg_type);
118
197
 
119
198
        entry->next_try = now + entry->next_wait;
120
199
        entry->next_wait *= 2;
132
211
 
133
212
static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
134
213
{
135
 
        struct wpa_supplicant *wpa_s = eloop_ctx;
136
 
        time_t now, first;
 
214
        struct radius_client_data *radius = eloop_ctx;
 
215
        struct hostapd_radius_servers *conf = radius->conf;
 
216
        struct os_time now;
 
217
        os_time_t first;
137
218
        struct radius_msg_list *entry, *prev, *tmp;
138
219
        int auth_failover = 0, acct_failover = 0;
 
220
        char abuf[50];
139
221
 
140
 
        entry = wpa_s->radius->msgs;
 
222
        entry = radius->msgs;
141
223
        if (!entry)
142
224
                return;
143
225
 
144
 
        time(&now);
 
226
        os_get_time(&now);
145
227
        first = 0;
146
228
 
147
229
        prev = NULL;
148
230
        while (entry) {
149
 
                if (now >= entry->next_try &&
150
 
                    radius_client_retransmit(wpa_s, entry, now)) {
 
231
                if (now.sec >= entry->next_try &&
 
232
                    radius_client_retransmit(radius, entry, now.sec)) {
151
233
                        if (prev)
152
234
                                prev->next = entry->next;
153
235
                        else
154
 
                                wpa_s->radius->msgs = entry->next;
 
236
                                radius->msgs = entry->next;
155
237
 
156
238
                        tmp = entry;
157
239
                        entry = entry->next;
158
240
                        radius_client_msg_free(tmp);
159
 
                        wpa_s->radius->num_msgs--;
 
241
                        radius->num_msgs--;
160
242
                        continue;
161
243
                }
162
244
 
175
257
                entry = entry->next;
176
258
        }
177
259
 
178
 
        if (wpa_s->radius->msgs) {
179
 
                if (first < now)
180
 
                        first = now;
181
 
                eloop_register_timeout(first - now, 0,
182
 
                                       radius_client_timer, wpa_s, NULL);
 
260
        if (radius->msgs) {
 
261
                if (first < now.sec)
 
262
                        first = now.sec;
 
263
                eloop_register_timeout(first - now.sec, 0,
 
264
                                       radius_client_timer, radius, NULL);
 
265
                hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
266
                               HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
 
267
                               "retransmit in %ld seconds",
 
268
                               (long int) (first - now.sec));
183
269
        }
184
270
 
185
 
        if (auth_failover && wpa_s->num_auth_servers > 1) {
 
271
        if (auth_failover && conf->num_auth_servers > 1) {
186
272
                struct hostapd_radius_server *next, *old;
187
 
                old = wpa_s->auth_server;
188
 
                hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
 
273
                old = conf->auth_server;
 
274
                hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
189
275
                               HOSTAPD_LEVEL_NOTICE,
190
276
                               "No response from Authentication server "
191
277
                               "%s:%d - failover",
192
 
                               inet_ntoa(old->addr), old->port);
 
278
                               hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
 
279
                               old->port);
 
280
 
 
281
                for (entry = radius->msgs; entry; entry = entry->next) {
 
282
                        if (entry->msg_type == RADIUS_AUTH)
 
283
                                old->timeouts++;
 
284
                }
193
285
 
194
286
                next = old + 1;
195
 
                if (next > &(wpa_s->auth_servers
196
 
                             [wpa_s->num_auth_servers - 1]))
197
 
                        next = wpa_s->auth_servers;
198
 
                wpa_s->auth_server = next;
199
 
                radius_change_server(wpa_s, next, old,
200
 
                                     wpa_s->radius->auth_serv_sock, 1);
 
287
                if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
 
288
                        next = conf->auth_servers;
 
289
                conf->auth_server = next;
 
290
                radius_change_server(radius, next, old,
 
291
                                     radius->auth_serv_sock,
 
292
                                     radius->auth_serv_sock6, 1);
201
293
        }
202
294
 
203
 
        if (acct_failover && wpa_s->num_acct_servers > 1) {
 
295
        if (acct_failover && conf->num_acct_servers > 1) {
204
296
                struct hostapd_radius_server *next, *old;
205
 
                old = wpa_s->acct_server;
206
 
                hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
 
297
                old = conf->acct_server;
 
298
                hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
207
299
                               HOSTAPD_LEVEL_NOTICE,
208
300
                               "No response from Accounting server "
209
301
                               "%s:%d - failover",
210
 
                               inet_ntoa(old->addr), old->port);
 
302
                               hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
 
303
                               old->port);
 
304
 
 
305
                for (entry = radius->msgs; entry; entry = entry->next) {
 
306
                        if (entry->msg_type == RADIUS_ACCT ||
 
307
                            entry->msg_type == RADIUS_ACCT_INTERIM)
 
308
                                old->timeouts++;
 
309
                }
 
310
 
211
311
                next = old + 1;
212
 
                if (next > &wpa_s->acct_servers
213
 
                    [wpa_s->num_acct_servers - 1])
214
 
                        next = wpa_s->acct_servers;
215
 
                wpa_s->acct_server = next;
216
 
                radius_change_server(wpa_s, next, old,
217
 
                                     wpa_s->radius->acct_serv_sock, 0);
218
 
        }
219
 
}
220
 
 
221
 
 
222
 
static void radius_client_list_add(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
 
312
                if (next > &conf->acct_servers[conf->num_acct_servers - 1])
 
313
                        next = conf->acct_servers;
 
314
                conf->acct_server = next;
 
315
                radius_change_server(radius, next, old,
 
316
                                     radius->acct_serv_sock,
 
317
                                     radius->acct_serv_sock6, 0);
 
318
        }
 
319
}
 
320
 
 
321
 
 
322
static void radius_client_update_timeout(struct radius_client_data *radius)
 
323
{
 
324
        struct os_time now;
 
325
        os_time_t first;
 
326
        struct radius_msg_list *entry;
 
327
 
 
328
        eloop_cancel_timeout(radius_client_timer, radius, NULL);
 
329
 
 
330
        if (radius->msgs == NULL) {
 
331
                return;
 
332
        }
 
333
 
 
334
        first = 0;
 
335
        for (entry = radius->msgs; entry; entry = entry->next) {
 
336
                if (first == 0 || entry->next_try < first)
 
337
                        first = entry->next_try;
 
338
        }
 
339
 
 
340
        os_get_time(&now);
 
341
        if (first < now.sec)
 
342
                first = now.sec;
 
343
        eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
 
344
                               NULL);
 
345
        hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
346
                       HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
 
347
                       " %ld seconds\n", (long int) (first - now.sec));
 
348
}
 
349
 
 
350
 
 
351
static void radius_client_list_add(struct radius_client_data *radius,
 
352
                                   struct radius_msg *msg,
223
353
                                   RadiusType msg_type, u8 *shared_secret,
224
 
                                   size_t shared_secret_len, u8 *addr)
 
354
                                   size_t shared_secret_len, const u8 *addr)
225
355
{
226
356
        struct radius_msg_list *entry, *prev;
227
357
 
233
363
                return;
234
364
        }
235
365
 
236
 
        entry = malloc(sizeof(*entry));
 
366
        entry = wpa_zalloc(sizeof(*entry));
237
367
        if (entry == NULL) {
238
368
                printf("Failed to add RADIUS packet into retransmit list\n");
239
369
                radius_msg_free(msg);
241
371
                return;
242
372
        }
243
373
 
244
 
        memset(entry, 0, sizeof(*entry));
245
374
        if (addr)
246
375
                memcpy(entry->addr, addr, ETH_ALEN);
247
376
        entry->msg = msg;
248
377
        entry->msg_type = msg_type;
249
378
        entry->shared_secret = shared_secret;
250
379
        entry->shared_secret_len = shared_secret_len;
251
 
        time(&entry->first_try);
 
380
        os_get_time(&entry->last_attempt);
 
381
        entry->first_try = entry->last_attempt.sec;
252
382
        entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
253
383
        entry->attempts = 1;
254
384
        entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
255
 
 
256
 
        if (!wpa_s->radius->msgs)
257
 
                eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
258
 
                                       radius_client_timer, wpa_s, NULL);
259
 
 
260
 
        entry->next = wpa_s->radius->msgs;
261
 
        wpa_s->radius->msgs = entry;
262
 
 
263
 
        if (wpa_s->radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
 
385
        entry->next = radius->msgs;
 
386
        radius->msgs = entry;
 
387
        radius_client_update_timeout(radius);
 
388
 
 
389
        if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
264
390
                printf("Removing the oldest un-ACKed RADIUS packet due to "
265
391
                       "retransmit list limits.\n");
266
392
                prev = NULL;
273
399
                        radius_client_msg_free(entry);
274
400
                }
275
401
        } else
276
 
                wpa_s->radius->num_msgs++;
 
402
                radius->num_msgs++;
277
403
}
278
404
 
279
405
 
280
 
static void radius_client_list_del(struct wpa_supplicant *wpa_s,
281
 
                                   RadiusType msg_type, u8 *addr)
 
406
static void radius_client_list_del(struct radius_client_data *radius,
 
407
                                   RadiusType msg_type, const u8 *addr)
282
408
{
283
409
        struct radius_msg_list *entry, *prev, *tmp;
284
410
 
285
411
        if (addr == NULL)
286
412
                return;
287
413
 
288
 
        entry = wpa_s->radius->msgs;
 
414
        entry = radius->msgs;
289
415
        prev = NULL;
290
416
        while (entry) {
291
417
                if (entry->msg_type == msg_type &&
293
419
                        if (prev)
294
420
                                prev->next = entry->next;
295
421
                        else
296
 
                                wpa_s->radius->msgs = entry->next;
 
422
                                radius->msgs = entry->next;
297
423
                        tmp = entry;
298
424
                        entry = entry->next;
299
 
                        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
300
 
                                      "Removing matching RADIUS message for "
301
 
                                      MACSTR "\n", MAC2STR(addr));
 
425
                        hostapd_logger(radius->ctx, addr,
 
426
                                       HOSTAPD_MODULE_RADIUS,
 
427
                                       HOSTAPD_LEVEL_DEBUG,
 
428
                                       "Removing matching RADIUS message");
302
429
                        radius_client_msg_free(tmp);
303
 
                        wpa_s->radius->num_msgs--;
 
430
                        radius->num_msgs--;
304
431
                        continue;
305
432
                }
306
433
                prev = entry;
309
436
}
310
437
 
311
438
 
312
 
int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
313
 
                       RadiusType msg_type, u8 *addr)
 
439
int radius_client_send(struct radius_client_data *radius,
 
440
                       struct radius_msg *msg, RadiusType msg_type,
 
441
                       const u8 *addr)
314
442
{
 
443
        struct hostapd_radius_servers *conf = radius->conf;
315
444
        u8 *shared_secret;
316
445
        size_t shared_secret_len;
317
446
        char *name;
319
448
 
320
449
        if (msg_type == RADIUS_ACCT_INTERIM) {
321
450
                /* Remove any pending interim acct update for the same STA. */
322
 
                radius_client_list_del(wpa_s, msg_type, addr);
 
451
                radius_client_list_del(radius, msg_type, addr);
323
452
        }
324
453
 
325
454
        if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
326
 
                shared_secret = wpa_s->acct_server->shared_secret;
327
 
                shared_secret_len = wpa_s->acct_server->shared_secret_len;
 
455
                shared_secret = conf->acct_server->shared_secret;
 
456
                shared_secret_len = conf->acct_server->shared_secret_len;
328
457
                radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
329
458
                name = "accounting";
330
 
                s = wpa_s->radius->acct_serv_sock;
 
459
                s = radius->acct_sock;
 
460
                conf->acct_server->requests++;
331
461
        } else {
332
 
                shared_secret = wpa_s->auth_server->shared_secret;
333
 
                shared_secret_len = wpa_s->auth_server->shared_secret_len;
 
462
                shared_secret = conf->auth_server->shared_secret;
 
463
                shared_secret_len = conf->auth_server->shared_secret_len;
334
464
                radius_msg_finish(msg, shared_secret, shared_secret_len);
335
465
                name = "authentication";
336
 
                s = wpa_s->radius->auth_serv_sock;
 
466
                s = radius->auth_sock;
 
467
                conf->auth_server->requests++;
337
468
        }
338
469
 
339
 
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
340
 
                      "Sending RADIUS message to %s server\n", name);
341
 
        if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
 
470
        hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
471
                       HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
 
472
                       "server", name);
 
473
        if (conf->msg_dumps)
342
474
                radius_msg_dump(msg);
343
475
 
344
476
        res = send(s, msg->buf, msg->buf_used, 0);
345
477
        if (res < 0)
346
 
                perror("send[RADIUS]");
 
478
                radius_client_handle_send_error(radius, s, msg_type);
347
479
 
348
 
        radius_client_list_add(wpa_s, msg, msg_type, shared_secret,
 
480
        radius_client_list_add(radius, msg, msg_type, shared_secret,
349
481
                               shared_secret_len, addr);
350
482
 
351
483
        return res;
354
486
 
355
487
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
356
488
{
357
 
        struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx;
 
489
        struct radius_client_data *radius = eloop_ctx;
 
490
        struct hostapd_radius_servers *conf = radius->conf;
358
491
        RadiusType msg_type = (RadiusType) sock_ctx;
359
 
        int len, i;
 
492
        int len, roundtrip;
360
493
        unsigned char buf[3000];
361
494
        struct radius_msg *msg;
362
495
        struct radius_rx_handler *handlers;
363
 
        size_t num_handlers;
 
496
        size_t num_handlers, i;
364
497
        struct radius_msg_list *req, *prev_req;
365
 
 
366
 
        len = recv(sock, buf, sizeof(buf), 0);
 
498
        struct os_time now;
 
499
        struct hostapd_radius_server *rconf;
 
500
        int invalid_authenticator = 0;
 
501
 
 
502
        if (msg_type == RADIUS_ACCT) {
 
503
                handlers = radius->acct_handlers;
 
504
                num_handlers = radius->num_acct_handlers;
 
505
                rconf = conf->acct_server;
 
506
        } else {
 
507
                handlers = radius->auth_handlers;
 
508
                num_handlers = radius->num_auth_handlers;
 
509
                rconf = conf->auth_server;
 
510
        }
 
511
 
 
512
        len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
367
513
        if (len < 0) {
368
514
                perror("recv[RADIUS]");
369
515
                return;
370
516
        }
371
 
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
372
 
                      "Received %d bytes from RADIUS server\n", len);
 
517
        hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
518
                       HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
 
519
                       "server", len);
373
520
        if (len == sizeof(buf)) {
374
521
                printf("Possibly too long UDP frame for our buffer - "
375
522
                       "dropping it\n");
379
526
        msg = radius_msg_parse(buf, len);
380
527
        if (msg == NULL) {
381
528
                printf("Parsing incoming RADIUS frame failed\n");
 
529
                rconf->malformed_responses++;
382
530
                return;
383
531
        }
384
532
 
385
 
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
386
 
                      "Received RADIUS message\n");
387
 
        if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
 
533
        hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
534
                       HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
 
535
        if (conf->msg_dumps)
388
536
                radius_msg_dump(msg);
389
537
 
390
 
        if (msg_type == RADIUS_ACCT) {
391
 
                handlers = wpa_s->radius->acct_handlers;
392
 
                num_handlers = wpa_s->radius->num_acct_handlers;
393
 
        } else {
394
 
                handlers = wpa_s->radius->auth_handlers;
395
 
                num_handlers = wpa_s->radius->num_auth_handlers;
 
538
        switch (msg->hdr->code) {
 
539
        case RADIUS_CODE_ACCESS_ACCEPT:
 
540
                rconf->access_accepts++;
 
541
                break;
 
542
        case RADIUS_CODE_ACCESS_REJECT:
 
543
                rconf->access_rejects++;
 
544
                break;
 
545
        case RADIUS_CODE_ACCESS_CHALLENGE:
 
546
                rconf->access_challenges++;
 
547
                break;
 
548
        case RADIUS_CODE_ACCOUNTING_RESPONSE:
 
549
                rconf->responses++;
 
550
                break;
396
551
        }
397
552
 
398
553
        prev_req = NULL;
399
 
        req = wpa_s->radius->msgs;
 
554
        req = radius->msgs;
400
555
        while (req) {
401
556
                /* TODO: also match by src addr:port of the packet when using
402
557
                 * alternative RADIUS servers (?) */
411
566
        }
412
567
 
413
568
        if (req == NULL) {
414
 
                HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
415
 
                              "No matching RADIUS request found (type=%d "
416
 
                              "id=%d) - dropping packet\n",
417
 
                              msg_type, msg->hdr->identifier);
 
569
                hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
570
                               HOSTAPD_LEVEL_DEBUG,
 
571
                               "No matching RADIUS request found (type=%d "
 
572
                               "id=%d) - dropping packet",
 
573
                               msg_type, msg->hdr->identifier);
418
574
                goto fail;
419
575
        }
420
576
 
 
577
        os_get_time(&now);
 
578
        roundtrip = (now.sec - req->last_attempt.sec) * 100 +
 
579
                (now.usec - req->last_attempt.usec) / 10000;
 
580
        hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
 
581
                       HOSTAPD_LEVEL_DEBUG,
 
582
                       "Received RADIUS packet matched with a pending "
 
583
                       "request, round trip time %d.%02d sec",
 
584
                       roundtrip / 100, roundtrip % 100);
 
585
        rconf->round_trip_time = roundtrip;
 
586
 
421
587
        /* Remove ACKed RADIUS packet from retransmit list */
422
588
        if (prev_req)
423
589
                prev_req->next = req->next;
424
590
        else
425
 
                wpa_s->radius->msgs = req->next;
426
 
        wpa_s->radius->num_msgs--;
 
591
                radius->msgs = req->next;
 
592
        radius->num_msgs--;
427
593
 
428
594
        for (i = 0; i < num_handlers; i++) {
429
595
                RadiusRxResult res;
430
 
                res = handlers[i].handler(wpa_s, msg, req->msg,
431
 
                                          req->shared_secret,
 
596
                res = handlers[i].handler(msg, req->msg, req->shared_secret,
432
597
                                          req->shared_secret_len,
433
598
                                          handlers[i].data);
434
599
                switch (res) {
439
604
                case RADIUS_RX_QUEUED:
440
605
                        radius_client_msg_free(req);
441
606
                        return;
 
607
                case RADIUS_RX_INVALID_AUTHENTICATOR:
 
608
                        invalid_authenticator++;
 
609
                        /* continue */
442
610
                case RADIUS_RX_UNKNOWN:
443
611
                        /* continue with next handler */
444
612
                        break;
445
613
                }
446
614
        }
447
615
 
448
 
        printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping "
449
 
               "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier);
 
616
        if (invalid_authenticator)
 
617
                rconf->bad_authenticators++;
 
618
        else
 
619
                rconf->unknown_types++;
 
620
        hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
 
621
                       HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
 
622
                       "(type=%d code=%d id=%d)%s - dropping packet",
 
623
                       msg_type, msg->hdr->code, msg->hdr->identifier,
 
624
                       invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
 
625
                       "");
450
626
        radius_client_msg_free(req);
451
627
 
452
628
 fail:
455
631
}
456
632
 
457
633
 
458
 
u8 radius_client_get_id(struct wpa_supplicant *wpa_s)
 
634
u8 radius_client_get_id(struct radius_client_data *radius)
459
635
{
460
636
        struct radius_msg_list *entry, *prev, *remove;
461
 
        u8 id = wpa_s->radius->next_radius_identifier++;
 
637
        u8 id = radius->next_radius_identifier++;
462
638
 
463
639
        /* remove entries with matching id from retransmit list to avoid
464
640
         * using new reply from the RADIUS server with an old request */
465
 
        entry = wpa_s->radius->msgs;
 
641
        entry = radius->msgs;
466
642
        prev = NULL;
467
643
        while (entry) {
468
644
                if (entry->msg->hdr->identifier == id) {
469
 
                        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
470
 
                                      "Removing pending RADIUS message, since "
471
 
                                      "its id (%d) is reused\n", id);
 
645
                        hostapd_logger(radius->ctx, entry->addr,
 
646
                                       HOSTAPD_MODULE_RADIUS,
 
647
                                       HOSTAPD_LEVEL_DEBUG,
 
648
                                       "Removing pending RADIUS message, "
 
649
                                       "since its id (%d) is reused", id);
472
650
                        if (prev)
473
651
                                prev->next = entry->next;
474
652
                        else
475
 
                                wpa_s->radius->msgs = entry->next;
 
653
                                radius->msgs = entry->next;
476
654
                        remove = entry;
477
 
                } else
 
655
                } else {
478
656
                        remove = NULL;
479
 
                prev = entry;
 
657
                        prev = entry;
 
658
                }
480
659
                entry = entry->next;
481
660
 
482
661
                if (remove)
487
666
}
488
667
 
489
668
 
490
 
void radius_client_flush(struct wpa_supplicant *wpa_s)
 
669
void radius_client_flush(struct radius_client_data *radius, int only_auth)
491
670
{
492
 
        struct radius_msg_list *entry, *prev;
 
671
        struct radius_msg_list *entry, *prev, *tmp;
493
672
 
494
 
        if (!wpa_s->radius)
 
673
        if (!radius)
495
674
                return;
496
675
 
497
 
        eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
 
676
        prev = NULL;
 
677
        entry = radius->msgs;
498
678
 
499
 
        entry = wpa_s->radius->msgs;
500
 
        wpa_s->radius->msgs = NULL;
501
 
        wpa_s->radius->num_msgs = 0;
502
679
        while (entry) {
503
 
                prev = entry;
504
 
                entry = entry->next;
505
 
                radius_client_msg_free(prev);
 
680
                if (!only_auth || entry->msg_type == RADIUS_AUTH) {
 
681
                        if (prev)
 
682
                                prev->next = entry->next;
 
683
                        else
 
684
                                radius->msgs = entry->next;
 
685
 
 
686
                        tmp = entry;
 
687
                        entry = entry->next;
 
688
                        radius_client_msg_free(tmp);
 
689
                        radius->num_msgs--;
 
690
                } else {
 
691
                        prev = entry;
 
692
                        entry = entry->next;
 
693
                }
 
694
        }
 
695
 
 
696
        if (radius->msgs == NULL)
 
697
                eloop_cancel_timeout(radius_client_timer, radius, NULL);
 
698
}
 
699
 
 
700
 
 
701
void radius_client_update_acct_msgs(struct radius_client_data *radius,
 
702
                                    u8 *shared_secret,
 
703
                                    size_t shared_secret_len)
 
704
{
 
705
        struct radius_msg_list *entry;
 
706
 
 
707
        if (!radius)
 
708
                return;
 
709
 
 
710
        for (entry = radius->msgs; entry; entry = entry->next) {
 
711
                if (entry->msg_type == RADIUS_ACCT) {
 
712
                        entry->shared_secret = shared_secret;
 
713
                        entry->shared_secret_len = shared_secret_len;
 
714
                        radius_msg_finish_acct(entry->msg, shared_secret,
 
715
                                               shared_secret_len);
 
716
                }
506
717
        }
507
718
}
508
719
 
509
720
 
510
721
static int
511
 
radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
 
722
radius_change_server(struct radius_client_data *radius,
 
723
                     struct hostapd_radius_server *nserv,
512
724
                     struct hostapd_radius_server *oserv,
513
 
                     int sock, int auth)
 
725
                     int sock, int sock6, int auth)
514
726
{
515
727
        struct sockaddr_in serv;
 
728
#ifdef CONFIG_IPV6
 
729
        struct sockaddr_in6 serv6;
 
730
#endif /* CONFIG_IPV6 */
 
731
        struct sockaddr *addr;
 
732
        socklen_t addrlen;
 
733
        char abuf[50];
 
734
        int sel_sock;
 
735
        struct radius_msg_list *entry;
516
736
 
517
 
        hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO,
 
737
        hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 
738
                       HOSTAPD_LEVEL_INFO,
518
739
                       "%s server %s:%d",
519
740
                       auth ? "Authentication" : "Accounting",
520
 
                       inet_ntoa(nserv->addr), nserv->port);
 
741
                       hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
 
742
                       nserv->port);
521
743
 
522
744
        if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
523
745
            memcmp(nserv->shared_secret, oserv->shared_secret,
524
746
                   nserv->shared_secret_len) != 0) {
525
 
                /* Pending RADIUS packets used different shared
526
 
                 * secret, so they would need to be modified. Could
527
 
                 * update all message authenticators and
528
 
                 * User-Passwords, etc. and retry with new server. For
529
 
                 * now, just drop all pending packets. */
530
 
                radius_client_flush(wpa_s);
531
 
        } else {
532
 
                /* Reset retry counters for the new server */
533
 
                struct radius_msg_list *entry;
534
 
                entry = wpa_s->radius->msgs;
535
 
                while (entry) {
536
 
                        entry->next_try = entry->first_try +
537
 
                                RADIUS_CLIENT_FIRST_WAIT;
538
 
                        entry->attempts = 0;
539
 
                        entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
540
 
                        entry = entry->next;
541
 
                }
542
 
                if (wpa_s->radius->msgs) {
543
 
                        eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
544
 
                        eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
545
 
                                               radius_client_timer, wpa_s,
546
 
                                               NULL);
547
 
                }
548
 
        }
549
 
 
550
 
        memset(&serv, 0, sizeof(serv));
551
 
        serv.sin_family = AF_INET;
552
 
        serv.sin_addr.s_addr = nserv->addr.s_addr;
553
 
        serv.sin_port = htons(nserv->port);
554
 
 
555
 
        if (connect(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
 
747
                /* Pending RADIUS packets used different shared secret, so
 
748
                 * they need to be modified. Update accounting message
 
749
                 * authenticators here. Authentication messages are removed
 
750
                 * since they would require more changes and the new RADIUS
 
751
                 * server may not be prepared to receive them anyway due to
 
752
                 * missing state information. Client will likely retry
 
753
                 * authentication, so this should not be an issue. */
 
754
                if (auth)
 
755
                        radius_client_flush(radius, 1);
 
756
                else {
 
757
                        radius_client_update_acct_msgs(
 
758
                                radius, nserv->shared_secret,
 
759
                                nserv->shared_secret_len);
 
760
                }
 
761
        }
 
762
 
 
763
        /* Reset retry counters for the new server */
 
764
        for (entry = radius->msgs; entry; entry = entry->next) {
 
765
                if ((auth && entry->msg_type != RADIUS_AUTH) ||
 
766
                    (!auth && entry->msg_type != RADIUS_ACCT))
 
767
                        continue;
 
768
                entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
 
769
                entry->attempts = 0;
 
770
                entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
 
771
        }
 
772
 
 
773
        if (radius->msgs) {
 
774
                eloop_cancel_timeout(radius_client_timer, radius, NULL);
 
775
                eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
 
776
                                       radius_client_timer, radius, NULL);
 
777
        }
 
778
 
 
779
        switch (nserv->addr.af) {
 
780
        case AF_INET:
 
781
                memset(&serv, 0, sizeof(serv));
 
782
                serv.sin_family = AF_INET;
 
783
                serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
 
784
                serv.sin_port = htons(nserv->port);
 
785
                addr = (struct sockaddr *) &serv;
 
786
                addrlen = sizeof(serv);
 
787
                sel_sock = sock;
 
788
                break;
 
789
#ifdef CONFIG_IPV6
 
790
        case AF_INET6:
 
791
                memset(&serv6, 0, sizeof(serv6));
 
792
                serv6.sin6_family = AF_INET6;
 
793
                memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
 
794
                       sizeof(struct in6_addr));
 
795
                serv6.sin6_port = htons(nserv->port);
 
796
                addr = (struct sockaddr *) &serv6;
 
797
                addrlen = sizeof(serv6);
 
798
                sel_sock = sock6;
 
799
                break;
 
800
#endif /* CONFIG_IPV6 */
 
801
        default:
 
802
                return -1;
 
803
        }
 
804
 
 
805
        if (connect(sel_sock, addr, addrlen) < 0) {
556
806
                perror("connect[radius]");
557
807
                return -1;
558
808
        }
559
809
 
 
810
        if (auth)
 
811
                radius->auth_sock = sel_sock;
 
812
        else
 
813
                radius->acct_sock = sel_sock;
 
814
 
560
815
        return 0;
561
816
}
562
817
 
563
818
 
564
819
static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
565
820
{
566
 
        struct wpa_supplicant *wpa_s = eloop_ctx;
 
821
        struct radius_client_data *radius = eloop_ctx;
 
822
        struct hostapd_radius_servers *conf = radius->conf;
567
823
        struct hostapd_radius_server *oserv;
568
824
 
569
 
        if (wpa_s->radius->auth_serv_sock >= 0 && wpa_s->auth_servers &&
570
 
            wpa_s->auth_server != wpa_s->auth_servers) {
571
 
                oserv = wpa_s->auth_server;
572
 
                wpa_s->auth_server = wpa_s->auth_servers;
573
 
                radius_change_server(wpa_s, wpa_s->auth_server, oserv,
574
 
                                     wpa_s->radius->auth_serv_sock, 1);
575
 
        }
576
 
 
577
 
        if (wpa_s->radius->acct_serv_sock >= 0 && wpa_s->acct_servers &&
578
 
            wpa_s->acct_server != wpa_s->acct_servers) {
579
 
                oserv = wpa_s->acct_server;
580
 
                wpa_s->acct_server = wpa_s->acct_servers;
581
 
                radius_change_server(wpa_s, wpa_s->acct_server, oserv,
582
 
                                     wpa_s->radius->acct_serv_sock, 0);
583
 
        }
584
 
 
585
 
        if (wpa_s->radius_retry_primary_interval)
586
 
                eloop_register_timeout(wpa_s->
587
 
                                       radius_retry_primary_interval, 0,
588
 
                                       radius_retry_primary_timer, wpa_s, NULL);
589
 
}
590
 
 
591
 
 
592
 
static int radius_client_init_auth(struct wpa_supplicant *wpa_s)
593
 
{
594
 
        wpa_s->radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
595
 
        if (wpa_s->radius->auth_serv_sock < 0) {
596
 
                perror("socket[PF_INET,SOCK_DGRAM]");
597
 
                return -1;
598
 
        }
599
 
 
600
 
        radius_change_server(wpa_s, wpa_s->auth_server, NULL,
601
 
                             wpa_s->radius->auth_serv_sock, 1);
602
 
 
603
 
        if (eloop_register_read_sock(wpa_s->radius->auth_serv_sock,
604
 
                                     radius_client_receive, wpa_s,
605
 
                                     (void *) RADIUS_AUTH)) {
606
 
                printf("Could not register read socket for authentication "
607
 
                       "server\n");
608
 
                return -1;
609
 
        }
610
 
 
611
 
        return 0;
612
 
}
613
 
 
614
 
 
615
 
static int radius_client_init_acct(struct wpa_supplicant *wpa_s)
616
 
{
617
 
        wpa_s->radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
618
 
        if (wpa_s->radius->acct_serv_sock < 0) {
619
 
                perror("socket[PF_INET,SOCK_DGRAM]");
620
 
                return -1;
621
 
        }
622
 
 
623
 
        radius_change_server(wpa_s, wpa_s->acct_server, NULL,
624
 
                             wpa_s->radius->acct_serv_sock, 0);
625
 
 
626
 
        if (eloop_register_read_sock(wpa_s->radius->acct_serv_sock,
627
 
                                     radius_client_receive, wpa_s,
628
 
                                     (void *) RADIUS_ACCT)) {
629
 
                printf("Could not register read socket for accounting "
630
 
                       "server\n");
631
 
                return -1;
632
 
        }
633
 
 
634
 
        return 0;
635
 
}
636
 
 
637
 
 
638
 
int radius_client_init(struct wpa_supplicant *wpa_s)
639
 
{
640
 
        wpa_s->radius = malloc(sizeof(struct radius_client_data));
641
 
        if (wpa_s->radius == NULL)
642
 
                return -1;
643
 
 
644
 
        memset(wpa_s->radius, 0, sizeof(struct radius_client_data));
645
 
        wpa_s->radius->auth_serv_sock = wpa_s->radius->acct_serv_sock = -1;
646
 
 
647
 
        if (wpa_s->auth_server && radius_client_init_auth(wpa_s))
648
 
                return -1;
649
 
 
650
 
        if (wpa_s->acct_server && radius_client_init_acct(wpa_s))
651
 
                return -1;
652
 
 
653
 
        if (wpa_s->radius_retry_primary_interval)
654
 
                eloop_register_timeout(wpa_s->radius_retry_primary_interval, 0,
655
 
                                       radius_retry_primary_timer, wpa_s,
656
 
                                       NULL);
657
 
 
658
 
        return 0;
659
 
}
660
 
 
661
 
 
662
 
void radius_client_deinit(struct wpa_supplicant *wpa_s)
663
 
{
664
 
        if (!wpa_s->radius)
 
825
        if (radius->auth_sock >= 0 && conf->auth_servers &&
 
826
            conf->auth_server != conf->auth_servers) {
 
827
                oserv = conf->auth_server;
 
828
                conf->auth_server = conf->auth_servers;
 
829
                radius_change_server(radius, conf->auth_server, oserv,
 
830
                                     radius->auth_serv_sock,
 
831
                                     radius->auth_serv_sock6, 1);
 
832
        }
 
833
 
 
834
        if (radius->acct_sock >= 0 && conf->acct_servers &&
 
835
            conf->acct_server != conf->acct_servers) {
 
836
                oserv = conf->acct_server;
 
837
                conf->acct_server = conf->acct_servers;
 
838
                radius_change_server(radius, conf->acct_server, oserv,
 
839
                                     radius->acct_serv_sock,
 
840
                                     radius->acct_serv_sock6, 0);
 
841
        }
 
842
 
 
843
        if (conf->retry_primary_interval)
 
844
                eloop_register_timeout(conf->retry_primary_interval, 0,
 
845
                                       radius_retry_primary_timer, radius,
 
846
                                       NULL);
 
847
}
 
848
 
 
849
 
 
850
static int radius_client_init_auth(struct radius_client_data *radius)
 
851
{
 
852
        struct hostapd_radius_servers *conf = radius->conf;
 
853
        int ok = 0;
 
854
 
 
855
        radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
 
856
        if (radius->auth_serv_sock < 0)
 
857
                perror("socket[PF_INET,SOCK_DGRAM]");
 
858
        else
 
859
                ok++;
 
860
 
 
861
#ifdef CONFIG_IPV6
 
862
        radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
 
863
        if (radius->auth_serv_sock6 < 0)
 
864
                perror("socket[PF_INET6,SOCK_DGRAM]");
 
865
        else
 
866
                ok++;
 
867
#endif /* CONFIG_IPV6 */
 
868
 
 
869
        if (ok == 0)
 
870
                return -1;
 
871
 
 
872
        radius_change_server(radius, conf->auth_server, NULL,
 
873
                             radius->auth_serv_sock, radius->auth_serv_sock6,
 
874
                             1);
 
875
 
 
876
        if (radius->auth_serv_sock >= 0 &&
 
877
            eloop_register_read_sock(radius->auth_serv_sock,
 
878
                                     radius_client_receive, radius,
 
879
                                     (void *) RADIUS_AUTH)) {
 
880
                printf("Could not register read socket for authentication "
 
881
                       "server\n");
 
882
                return -1;
 
883
        }
 
884
 
 
885
#ifdef CONFIG_IPV6
 
886
        if (radius->auth_serv_sock6 >= 0 &&
 
887
            eloop_register_read_sock(radius->auth_serv_sock6,
 
888
                                     radius_client_receive, radius,
 
889
                                     (void *) RADIUS_AUTH)) {
 
890
                printf("Could not register read socket for authentication "
 
891
                       "server\n");
 
892
                return -1;
 
893
        }
 
894
#endif /* CONFIG_IPV6 */
 
895
 
 
896
        return 0;
 
897
}
 
898
 
 
899
 
 
900
static int radius_client_init_acct(struct radius_client_data *radius)
 
901
{
 
902
        struct hostapd_radius_servers *conf = radius->conf;
 
903
        int ok = 0;
 
904
 
 
905
        radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
 
906
        if (radius->acct_serv_sock < 0)
 
907
                perror("socket[PF_INET,SOCK_DGRAM]");
 
908
        else
 
909
                ok++;
 
910
 
 
911
        radius_change_server(radius, conf->acct_server, NULL,
 
912
                             radius->acct_serv_sock, radius->acct_serv_sock6,
 
913
                             0);
 
914
 
 
915
        if (radius->acct_serv_sock >= 0 &&
 
916
            eloop_register_read_sock(radius->acct_serv_sock,
 
917
                                     radius_client_receive, radius,
 
918
                                     (void *) RADIUS_ACCT)) {
 
919
                printf("Could not register read socket for accounting "
 
920
                       "server\n");
 
921
                return -1;
 
922
        }
 
923
 
 
924
#ifdef CONFIG_IPV6
 
925
        if (radius->acct_serv_sock6 >= 0 &&
 
926
            eloop_register_read_sock(radius->acct_serv_sock6,
 
927
                                     radius_client_receive, radius,
 
928
                                     (void *) RADIUS_ACCT)) {
 
929
                printf("Could not register read socket for accounting "
 
930
                       "server\n");
 
931
                return -1;
 
932
        }
 
933
#endif /* CONFIG_IPV6 */
 
934
 
 
935
        return 0;
 
936
}
 
937
 
 
938
 
 
939
struct radius_client_data *
 
940
radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
 
941
{
 
942
        struct radius_client_data *radius;
 
943
 
 
944
        radius = wpa_zalloc(sizeof(struct radius_client_data));
 
945
        if (radius == NULL)
 
946
                return NULL;
 
947
 
 
948
        radius->ctx = ctx;
 
949
        radius->conf = conf;
 
950
        radius->auth_serv_sock = radius->acct_serv_sock =
 
951
                radius->auth_serv_sock6 = radius->acct_serv_sock6 =
 
952
                radius->auth_sock = radius->acct_sock = -1;
 
953
 
 
954
        if (conf->auth_server && radius_client_init_auth(radius)) {
 
955
                radius_client_deinit(radius);
 
956
                return NULL;
 
957
        }
 
958
 
 
959
        if (conf->acct_server && radius_client_init_acct(radius)) {
 
960
                radius_client_deinit(radius);
 
961
                return NULL;
 
962
        }
 
963
 
 
964
        if (conf->retry_primary_interval)
 
965
                eloop_register_timeout(conf->retry_primary_interval, 0,
 
966
                                       radius_retry_primary_timer, radius,
 
967
                                       NULL);
 
968
 
 
969
        return radius;
 
970
}
 
971
 
 
972
 
 
973
void radius_client_deinit(struct radius_client_data *radius)
 
974
{
 
975
        if (!radius)
665
976
                return;
666
977
 
667
 
        eloop_cancel_timeout(radius_retry_primary_timer, wpa_s, NULL);
668
 
 
669
 
        radius_client_flush(wpa_s);
670
 
        free(wpa_s->radius->auth_handlers);
671
 
        free(wpa_s->radius->acct_handlers);
672
 
        free(wpa_s->radius);
673
 
        wpa_s->radius = NULL;
 
978
        eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
 
979
 
 
980
        radius_client_flush(radius, 0);
 
981
        free(radius->auth_handlers);
 
982
        free(radius->acct_handlers);
 
983
        free(radius);
 
984
}
 
985
 
 
986
 
 
987
void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr)
 
988
{
 
989
        struct radius_msg_list *entry, *prev, *tmp;
 
990
 
 
991
        prev = NULL;
 
992
        entry = radius->msgs;
 
993
        while (entry) {
 
994
                if (entry->msg_type == RADIUS_AUTH &&
 
995
                    memcmp(entry->addr, addr, ETH_ALEN) == 0) {
 
996
                        hostapd_logger(radius->ctx, addr,
 
997
                                       HOSTAPD_MODULE_RADIUS,
 
998
                                       HOSTAPD_LEVEL_DEBUG,
 
999
                                       "Removing pending RADIUS authentication"
 
1000
                                       " message for removed client");
 
1001
 
 
1002
                        if (prev)
 
1003
                                prev->next = entry->next;
 
1004
                        else
 
1005
                                radius->msgs = entry->next;
 
1006
 
 
1007
                        tmp = entry;
 
1008
                        entry = entry->next;
 
1009
                        radius_client_msg_free(tmp);
 
1010
                        radius->num_msgs--;
 
1011
                        continue;
 
1012
                }
 
1013
 
 
1014
                prev = entry;
 
1015
                entry = entry->next;
 
1016
        }
 
1017
}
 
1018
 
 
1019
 
 
1020
static int radius_client_dump_auth_server(char *buf, size_t buflen,
 
1021
                                          struct hostapd_radius_server *serv,
 
1022
                                          struct radius_client_data *cli)
 
1023
{
 
1024
        int pending = 0;
 
1025
        struct radius_msg_list *msg;
 
1026
        char abuf[50];
 
1027
 
 
1028
        if (cli) {
 
1029
                for (msg = cli->msgs; msg; msg = msg->next) {
 
1030
                        if (msg->msg_type == RADIUS_AUTH)
 
1031
                                pending++;
 
1032
                }
 
1033
        }
 
1034
 
 
1035
        return snprintf(buf, buflen,
 
1036
                        "radiusAuthServerIndex=%d\n"
 
1037
                        "radiusAuthServerAddress=%s\n"
 
1038
                        "radiusAuthClientServerPortNumber=%d\n"
 
1039
                        "radiusAuthClientRoundTripTime=%d\n"
 
1040
                        "radiusAuthClientAccessRequests=%u\n"
 
1041
                        "radiusAuthClientAccessRetransmissions=%u\n"
 
1042
                        "radiusAuthClientAccessAccepts=%u\n"
 
1043
                        "radiusAuthClientAccessRejects=%u\n"
 
1044
                        "radiusAuthClientAccessChallenges=%u\n"
 
1045
                        "radiusAuthClientMalformedAccessResponses=%u\n"
 
1046
                        "radiusAuthClientBadAuthenticators=%u\n"
 
1047
                        "radiusAuthClientPendingRequests=%u\n"
 
1048
                        "radiusAuthClientTimeouts=%u\n"
 
1049
                        "radiusAuthClientUnknownTypes=%u\n"
 
1050
                        "radiusAuthClientPacketsDropped=%u\n",
 
1051
                        serv->index,
 
1052
                        hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
 
1053
                        serv->port,
 
1054
                        serv->round_trip_time,
 
1055
                        serv->requests,
 
1056
                        serv->retransmissions,
 
1057
                        serv->access_accepts,
 
1058
                        serv->access_rejects,
 
1059
                        serv->access_challenges,
 
1060
                        serv->malformed_responses,
 
1061
                        serv->bad_authenticators,
 
1062
                        pending,
 
1063
                        serv->timeouts,
 
1064
                        serv->unknown_types,
 
1065
                        serv->packets_dropped);
 
1066
}
 
1067
 
 
1068
 
 
1069
static int radius_client_dump_acct_server(char *buf, size_t buflen,
 
1070
                                          struct hostapd_radius_server *serv,
 
1071
                                          struct radius_client_data *cli)
 
1072
{
 
1073
        int pending = 0;
 
1074
        struct radius_msg_list *msg;
 
1075
        char abuf[50];
 
1076
 
 
1077
        if (cli) {
 
1078
                for (msg = cli->msgs; msg; msg = msg->next) {
 
1079
                        if (msg->msg_type == RADIUS_ACCT ||
 
1080
                            msg->msg_type == RADIUS_ACCT_INTERIM)
 
1081
                                pending++;
 
1082
                }
 
1083
        }
 
1084
 
 
1085
        return snprintf(buf, buflen,
 
1086
                        "radiusAccServerIndex=%d\n"
 
1087
                        "radiusAccServerAddress=%s\n"
 
1088
                        "radiusAccClientServerPortNumber=%d\n"
 
1089
                        "radiusAccClientRoundTripTime=%d\n"
 
1090
                        "radiusAccClientRequests=%u\n"
 
1091
                        "radiusAccClientRetransmissions=%u\n"
 
1092
                        "radiusAccClientResponses=%u\n"
 
1093
                        "radiusAccClientMalformedResponses=%u\n"
 
1094
                        "radiusAccClientBadAuthenticators=%u\n"
 
1095
                        "radiusAccClientPendingRequests=%u\n"
 
1096
                        "radiusAccClientTimeouts=%u\n"
 
1097
                        "radiusAccClientUnknownTypes=%u\n"
 
1098
                        "radiusAccClientPacketsDropped=%u\n",
 
1099
                        serv->index,
 
1100
                        hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
 
1101
                        serv->port,
 
1102
                        serv->round_trip_time,
 
1103
                        serv->requests,
 
1104
                        serv->retransmissions,
 
1105
                        serv->responses,
 
1106
                        serv->malformed_responses,
 
1107
                        serv->bad_authenticators,
 
1108
                        pending,
 
1109
                        serv->timeouts,
 
1110
                        serv->unknown_types,
 
1111
                        serv->packets_dropped);
 
1112
}
 
1113
 
 
1114
 
 
1115
int radius_client_get_mib(struct radius_client_data *radius, char *buf,
 
1116
                          size_t buflen)
 
1117
{
 
1118
        struct hostapd_radius_servers *conf = radius->conf;
 
1119
        int i;
 
1120
        struct hostapd_radius_server *serv;
 
1121
        int count = 0;
 
1122
 
 
1123
        if (conf->auth_servers) {
 
1124
                for (i = 0; i < conf->num_auth_servers; i++) {
 
1125
                        serv = &conf->auth_servers[i];
 
1126
                        count += radius_client_dump_auth_server(
 
1127
                                buf + count, buflen - count, serv,
 
1128
                                serv == conf->auth_server ?
 
1129
                                radius : NULL);
 
1130
                }
 
1131
        }
 
1132
 
 
1133
        if (conf->acct_servers) {
 
1134
                for (i = 0; i < conf->num_acct_servers; i++) {
 
1135
                        serv = &conf->acct_servers[i];
 
1136
                        count += radius_client_dump_acct_server(
 
1137
                                buf + count, buflen - count, serv,
 
1138
                                serv == conf->acct_server ?
 
1139
                                radius : NULL);
 
1140
                }
 
1141
        }
 
1142
 
 
1143
        return count;
674
1144
}