Coverage Report

Created: 2025-04-24 06:18

/src/hostap/src/radius/radius_client.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * RADIUS client
3
 * Copyright (c) 2002-2024, Jouni Malinen <j@w1.fi>
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "includes.h"
10
#include <fcntl.h>
11
#include <net/if.h>
12
13
#include "common.h"
14
#include "eloop.h"
15
#include "crypto/tls.h"
16
#include "radius.h"
17
#include "radius_client.h"
18
19
/* Defaults for RADIUS retransmit values (exponential backoff) */
20
21
/**
22
 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds
23
 */
24
0
#define RADIUS_CLIENT_FIRST_WAIT 3
25
26
/**
27
 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds
28
 */
29
0
#define RADIUS_CLIENT_MAX_WAIT 120
30
31
/**
32
 * RADIUS_CLIENT_MAX_FAILOVER - RADIUS client maximum retries
33
 *
34
 * Maximum number of server failovers before the entry is removed from
35
 * retransmit list.
36
 */
37
0
#define RADIUS_CLIENT_MAX_FAILOVER 3
38
39
/**
40
 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages
41
 *
42
 * Maximum number of entries in retransmit list (oldest entries will be
43
 * removed, if this limit is exceeded).
44
 */
45
0
#define RADIUS_CLIENT_MAX_ENTRIES 30
46
47
/**
48
 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point
49
 *
50
 * The number of failed retry attempts after which the RADIUS server will be
51
 * changed (if one of more backup servers are configured).
52
 */
53
0
#define RADIUS_CLIENT_NUM_FAILOVER 4
54
55
56
/**
57
 * struct radius_rx_handler - RADIUS client RX handler
58
 *
59
 * This data structure is used internally inside the RADIUS client module to
60
 * store registered RX handlers. These handlers are registered by calls to
61
 * radius_client_register() and unregistered when the RADIUS client is
62
 * deinitialized with a call to radius_client_deinit().
63
 */
64
struct radius_rx_handler {
65
  /**
66
   * handler - Received RADIUS message handler
67
   */
68
  RadiusRxResult (*handler)(struct radius_msg *msg,
69
          struct radius_msg *req,
70
          const u8 *shared_secret,
71
          size_t shared_secret_len,
72
          void *data);
73
74
  /**
75
   * data - Context data for the handler
76
   */
77
  void *data;
78
};
79
80
81
/**
82
 * struct radius_msg_list - RADIUS client message retransmit list
83
 *
84
 * This data structure is used internally inside the RADIUS client module to
85
 * store pending RADIUS requests that may still need to be retransmitted.
86
 */
87
struct radius_msg_list {
88
  /**
89
   * addr - STA/client address
90
   *
91
   * This is used to find RADIUS messages for the same STA.
92
   */
93
  u8 addr[ETH_ALEN];
94
95
  /**
96
   * msg - RADIUS message
97
   */
98
  struct radius_msg *msg;
99
100
  /**
101
   * msg_type - Message type
102
   */
103
  RadiusType msg_type;
104
105
  /**
106
   * first_try - Time of the first transmission attempt
107
   */
108
  os_time_t first_try;
109
110
  /**
111
   * next_try - Time for the next transmission attempt
112
   */
113
  os_time_t next_try;
114
115
  /**
116
   * attempts - Number of transmission attempts for one server
117
   */
118
  int attempts;
119
120
  /**
121
   * accu_attempts - Number of accumulated attempts
122
   */
123
  int accu_attempts;
124
125
  /**
126
   * next_wait - Next retransmission wait time in seconds
127
   */
128
  int next_wait;
129
130
  /**
131
   * last_attempt - Time of the last transmission attempt
132
   */
133
  struct os_reltime last_attempt;
134
135
  /**
136
   * shared_secret - Shared secret with the target RADIUS server
137
   */
138
  const u8 *shared_secret;
139
140
  /**
141
   * shared_secret_len - shared_secret length in octets
142
   */
143
  size_t shared_secret_len;
144
145
  /* TODO: server config with failover to backup server(s) */
146
147
  /**
148
   * next - Next message in the list
149
   */
150
  struct radius_msg_list *next;
151
};
152
153
154
/**
155
 * struct radius_client_data - Internal RADIUS client data
156
 *
157
 * This data structure is used internally inside the RADIUS client module.
158
 * External users allocate this by calling radius_client_init() and free it by
159
 * calling radius_client_deinit(). The pointer to this opaque data is used in
160
 * calls to other functions as an identifier for the RADIUS client instance.
161
 */
162
struct radius_client_data {
163
  /**
164
   * ctx - Context pointer for hostapd_logger() callbacks
165
   */
166
  void *ctx;
167
168
  /**
169
   * conf - RADIUS client configuration (list of RADIUS servers to use)
170
   */
171
  struct hostapd_radius_servers *conf;
172
173
  /**
174
   * auth_sock - Currently used socket for RADIUS authentication server
175
   */
176
  int auth_sock;
177
178
  /**
179
   * auth_tls - Whether current authentication connection uses TLS
180
   */
181
  bool auth_tls;
182
183
  /**
184
   * auth_tls_ready - Whether authentication TLS is ready
185
   */
186
  bool auth_tls_ready;
187
188
  /**
189
   * acct_sock - Currently used socket for RADIUS accounting server
190
   */
191
  int acct_sock;
192
193
  /**
194
   * acct_tls - Whether current accounting connection uses TLS
195
   */
196
  bool acct_tls;
197
198
  /**
199
   * acct_tls_ready - Whether accounting TLS is ready
200
   */
201
  bool acct_tls_ready;
202
203
  /**
204
   * auth_handlers - Authentication message handlers
205
   */
206
  struct radius_rx_handler *auth_handlers;
207
208
  /**
209
   * num_auth_handlers - Number of handlers in auth_handlers
210
   */
211
  size_t num_auth_handlers;
212
213
  /**
214
   * acct_handlers - Accounting message handlers
215
   */
216
  struct radius_rx_handler *acct_handlers;
217
218
  /**
219
   * num_acct_handlers - Number of handlers in acct_handlers
220
   */
221
  size_t num_acct_handlers;
222
223
  /**
224
   * msgs - Pending outgoing RADIUS messages
225
   */
226
  struct radius_msg_list *msgs;
227
228
  /**
229
   * num_msgs - Number of pending messages in the msgs list
230
   */
231
  size_t num_msgs;
232
233
  /**
234
   * next_radius_identifier - Next RADIUS message identifier to use
235
   */
236
  u8 next_radius_identifier;
237
238
  /**
239
   * interim_error_cb - Interim accounting error callback
240
   */
241
  void (*interim_error_cb)(const u8 *addr, void *ctx);
242
243
  /**
244
   * interim_error_cb_ctx - interim_error_cb() context data
245
   */
246
  void *interim_error_cb_ctx;
247
248
#ifdef CONFIG_RADIUS_TLS
249
  void *tls_ctx;
250
  struct tls_connection *auth_tls_conn;
251
  struct tls_connection *acct_tls_conn;
252
#endif /* CONFIG_RADIUS_TLS */
253
};
254
255
256
static int
257
radius_change_server(struct radius_client_data *radius,
258
         struct hostapd_radius_server *nserv,
259
         struct hostapd_radius_server *oserv,
260
         int auth);
261
static int radius_client_init_acct(struct radius_client_data *radius);
262
static int radius_client_init_auth(struct radius_client_data *radius);
263
static void radius_client_auth_failover(struct radius_client_data *radius);
264
static void radius_client_acct_failover(struct radius_client_data *radius);
265
266
267
static void radius_client_msg_free(struct radius_msg_list *req)
268
0
{
269
0
  radius_msg_free(req->msg);
270
0
  os_free(req);
271
0
}
272
273
274
/**
275
 * radius_client_register - Register a RADIUS client RX handler
276
 * @radius: RADIUS client context from radius_client_init()
277
 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
278
 * @handler: Handler for received RADIUS messages
279
 * @data: Context pointer for handler callbacks
280
 * Returns: 0 on success, -1 on failure
281
 *
282
 * This function is used to register a handler for processing received RADIUS
283
 * authentication and accounting messages. The handler() callback function will
284
 * be called whenever a RADIUS message is received from the active server.
285
 *
286
 * There can be multiple registered RADIUS message handlers. The handlers will
287
 * be called in order until one of them indicates that it has processed or
288
 * queued the message.
289
 */
290
int radius_client_register(struct radius_client_data *radius,
291
         RadiusType msg_type,
292
         RadiusRxResult (*handler)(struct radius_msg *msg,
293
                 struct radius_msg *req,
294
                 const u8 *shared_secret,
295
                 size_t shared_secret_len,
296
                 void *data),
297
         void *data)
298
0
{
299
0
  struct radius_rx_handler **handlers, *newh;
300
0
  size_t *num;
301
302
0
  if (msg_type == RADIUS_ACCT) {
303
0
    handlers = &radius->acct_handlers;
304
0
    num = &radius->num_acct_handlers;
305
0
  } else {
306
0
    handlers = &radius->auth_handlers;
307
0
    num = &radius->num_auth_handlers;
308
0
  }
309
310
0
  newh = os_realloc_array(*handlers, *num + 1,
311
0
        sizeof(struct radius_rx_handler));
312
0
  if (newh == NULL)
313
0
    return -1;
314
315
0
  newh[*num].handler = handler;
316
0
  newh[*num].data = data;
317
0
  (*num)++;
318
0
  *handlers = newh;
319
320
0
  return 0;
321
0
}
322
323
324
/**
325
 * radius_client_set_interim_erro_cb - Register an interim acct error callback
326
 * @radius: RADIUS client context from radius_client_init()
327
 * @addr: Station address from the failed message
328
 * @cb: Handler for interim accounting errors
329
 * @ctx: Context pointer for handler callbacks
330
 *
331
 * This function is used to register a handler for processing failed
332
 * transmission attempts of interim accounting update messages.
333
 */
334
void radius_client_set_interim_error_cb(struct radius_client_data *radius,
335
          void (*cb)(const u8 *addr, void *ctx),
336
          void *ctx)
337
0
{
338
0
  radius->interim_error_cb = cb;
339
0
  radius->interim_error_cb_ctx = ctx;
340
0
}
341
342
343
/*
344
 * Returns >0 if message queue was flushed (i.e., the message that triggered
345
 * the error is not available anymore)
346
 */
347
static int radius_client_handle_send_error(struct radius_client_data *radius,
348
             int s, RadiusType msg_type)
349
0
{
350
0
#ifndef CONFIG_NATIVE_WINDOWS
351
0
  int _errno = errno;
352
0
  wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno));
353
0
  if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
354
0
      _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) {
355
0
    hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
356
0
             HOSTAPD_LEVEL_INFO,
357
0
             "Send failed - maybe interface status changed -"
358
0
             " try to connect again");
359
0
    if (msg_type == RADIUS_ACCT ||
360
0
        msg_type == RADIUS_ACCT_INTERIM) {
361
0
      radius_client_init_acct(radius);
362
0
      return 0;
363
0
    } else {
364
0
      radius_client_init_auth(radius);
365
0
      return 1;
366
0
    }
367
0
  }
368
0
#endif /* CONFIG_NATIVE_WINDOWS */
369
370
0
  return 0;
371
0
}
372
373
374
static int radius_client_retransmit(struct radius_client_data *radius,
375
            struct radius_msg_list *entry,
376
            os_time_t now)
377
0
{
378
0
  struct hostapd_radius_servers *conf = radius->conf;
379
0
  int s;
380
0
  struct wpabuf *buf;
381
0
  size_t prev_num_msgs;
382
0
  u8 *acct_delay_time;
383
0
  size_t acct_delay_time_len;
384
0
  int num_servers;
385
#ifdef CONFIG_RADIUS_TLS
386
  struct wpabuf *out = NULL;
387
  struct tls_connection *conn = NULL;
388
  bool acct = false;
389
#endif /* CONFIG_RADIUS_TLS */
390
391
0
  if (entry->msg_type == RADIUS_ACCT ||
392
0
      entry->msg_type == RADIUS_ACCT_INTERIM) {
393
#ifdef CONFIG_RADIUS_TLS
394
    acct = true;
395
    if (radius->acct_tls)
396
      conn = radius->acct_tls_conn;
397
#endif /* CONFIG_RADIUS_TLS */
398
0
    num_servers = conf->num_acct_servers;
399
0
    if (radius->acct_sock < 0)
400
0
      radius_client_init_acct(radius);
401
0
    if (radius->acct_sock < 0 && conf->num_acct_servers > 1) {
402
0
      prev_num_msgs = radius->num_msgs;
403
0
      radius_client_acct_failover(radius);
404
0
      if (prev_num_msgs != radius->num_msgs)
405
0
        return 0;
406
0
    }
407
0
    s = radius->acct_sock;
408
0
    if (entry->attempts == 0)
409
0
      conf->acct_server->requests++;
410
0
    else {
411
0
      conf->acct_server->timeouts++;
412
0
      conf->acct_server->retransmissions++;
413
0
    }
414
0
  } else {
415
#ifdef CONFIG_RADIUS_TLS
416
    if (radius->auth_tls)
417
      conn = radius->auth_tls_conn;
418
#endif /* CONFIG_RADIUS_TLS */
419
0
    num_servers = conf->num_auth_servers;
420
0
    if (radius->auth_sock < 0)
421
0
      radius_client_init_auth(radius);
422
0
    if (radius->auth_sock < 0 && conf->num_auth_servers > 1) {
423
0
      prev_num_msgs = radius->num_msgs;
424
0
      radius_client_auth_failover(radius);
425
0
      if (prev_num_msgs != radius->num_msgs)
426
0
        return 0;
427
0
    }
428
0
    s = radius->auth_sock;
429
0
    if (entry->attempts == 0)
430
0
      conf->auth_server->requests++;
431
0
    else {
432
0
      conf->auth_server->timeouts++;
433
0
      conf->auth_server->retransmissions++;
434
0
    }
435
0
  }
436
437
0
  if (entry->msg_type == RADIUS_ACCT_INTERIM) {
438
0
    wpa_printf(MSG_DEBUG,
439
0
         "RADIUS: Failed to transmit interim accounting update to "
440
0
         MACSTR " - drop message and request a new update",
441
0
         MAC2STR(entry->addr));
442
0
    if (radius->interim_error_cb)
443
0
      radius->interim_error_cb(entry->addr,
444
0
             radius->interim_error_cb_ctx);
445
0
    return 1;
446
0
  }
447
448
0
  if (s < 0) {
449
0
    wpa_printf(MSG_INFO,
450
0
         "RADIUS: No valid socket for retransmission");
451
0
    return 1;
452
0
  }
453
454
#ifdef CONFIG_RADIUS_TLS
455
  if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
456
      (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
457
    wpa_printf(MSG_DEBUG,
458
         "RADIUS: TLS connection not yet ready for TX");
459
    goto not_ready;
460
  }
461
#endif /* CONFIG_RADIUS_TLS */
462
463
0
  if (entry->msg_type == RADIUS_ACCT &&
464
0
      radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
465
0
            &acct_delay_time, &acct_delay_time_len,
466
0
            NULL) == 0 &&
467
0
      acct_delay_time_len == 4) {
468
0
    struct radius_hdr *hdr;
469
0
    u32 delay_time;
470
471
    /*
472
     * Need to assign a new identifier since attribute contents
473
     * changes.
474
     */
475
0
    hdr = radius_msg_get_hdr(entry->msg);
476
0
    hdr->identifier = radius_client_get_id(radius);
477
478
    /* Update Acct-Delay-Time to show wait time in queue */
479
0
    delay_time = now - entry->first_try;
480
0
    WPA_PUT_BE32(acct_delay_time, delay_time);
481
482
0
    wpa_printf(MSG_DEBUG,
483
0
         "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
484
0
         delay_time);
485
0
    if (radius_msg_finish_acct(entry->msg, entry->shared_secret,
486
0
             entry->shared_secret_len) < 0) {
487
0
      wpa_printf(MSG_INFO, "Failed to build RADIUS message");
488
0
      return -1;
489
0
    }
490
0
    if (radius->conf->msg_dumps)
491
0
      radius_msg_dump(entry->msg);
492
0
  }
493
494
  /* retransmit; remove entry if too many attempts */
495
0
  if (entry->accu_attempts >= RADIUS_CLIENT_MAX_FAILOVER *
496
0
      RADIUS_CLIENT_NUM_FAILOVER * num_servers) {
497
0
    wpa_printf(MSG_INFO,
498
0
         "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts");
499
0
    return 1;
500
0
  }
501
502
0
  entry->attempts++;
503
0
  entry->accu_attempts++;
504
0
  hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
505
0
           HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
506
0
           radius_msg_get_hdr(entry->msg)->identifier);
507
508
0
  os_get_reltime(&entry->last_attempt);
509
0
  buf = radius_msg_get_buf(entry->msg);
510
#ifdef CONFIG_RADIUS_TLS
511
  if (conn) {
512
    out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
513
    if (!out) {
514
      wpa_printf(MSG_INFO,
515
           "RADIUS: Failed to encrypt RADIUS message (TLS)");
516
      return -1;
517
    }
518
    wpa_printf(MSG_DEBUG,
519
         "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
520
         wpabuf_len(buf), wpabuf_len(out));
521
    buf = out;
522
  }
523
#endif /* CONFIG_RADIUS_TLS */
524
525
0
  wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
526
0
       wpabuf_len(buf));
527
0
  if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
528
0
    if (radius_client_handle_send_error(radius, s, entry->msg_type)
529
0
        > 0) {
530
#ifdef CONFIG_RADIUS_TLS
531
      wpabuf_free(out);
532
#endif /* CONFIG_RADIUS_TLS */
533
0
      return 0;
534
0
    }
535
0
  }
536
#ifdef CONFIG_RADIUS_TLS
537
  wpabuf_free(out);
538
539
not_ready:
540
#endif /* CONFIG_RADIUS_TLS */
541
542
0
  entry->next_try = now + entry->next_wait;
543
0
  entry->next_wait *= 2;
544
0
  if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
545
0
    entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
546
547
0
  return 0;
548
0
}
549
550
551
static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
552
0
{
553
0
  struct radius_client_data *radius = eloop_ctx;
554
0
  struct os_reltime now;
555
0
  os_time_t first;
556
0
  struct radius_msg_list *entry, *prev, *tmp;
557
0
  int auth_failover = 0, acct_failover = 0;
558
0
  size_t prev_num_msgs;
559
0
  int s;
560
561
0
  entry = radius->msgs;
562
0
  if (!entry)
563
0
    return;
564
565
0
  os_get_reltime(&now);
566
567
0
  while (entry) {
568
0
    if (now.sec >= entry->next_try) {
569
0
      s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock :
570
0
        radius->acct_sock;
571
0
      if (entry->attempts >= RADIUS_CLIENT_NUM_FAILOVER ||
572
0
          (s < 0 && entry->attempts > 0)) {
573
0
        if (entry->msg_type == RADIUS_ACCT ||
574
0
            entry->msg_type == RADIUS_ACCT_INTERIM)
575
0
          acct_failover++;
576
0
        else
577
0
          auth_failover++;
578
0
      }
579
0
    }
580
0
    entry = entry->next;
581
0
  }
582
583
0
  if (auth_failover)
584
0
    radius_client_auth_failover(radius);
585
586
0
  if (acct_failover)
587
0
    radius_client_acct_failover(radius);
588
589
0
  entry = radius->msgs;
590
0
  first = 0;
591
592
0
  prev = NULL;
593
0
  while (entry) {
594
0
    prev_num_msgs = radius->num_msgs;
595
0
    if (now.sec >= entry->next_try &&
596
0
        radius_client_retransmit(radius, entry, now.sec)) {
597
0
      if (prev)
598
0
        prev->next = entry->next;
599
0
      else
600
0
        radius->msgs = entry->next;
601
602
0
      tmp = entry;
603
0
      entry = entry->next;
604
0
      radius_client_msg_free(tmp);
605
0
      radius->num_msgs--;
606
0
      continue;
607
0
    }
608
609
0
    if (prev_num_msgs != radius->num_msgs) {
610
0
      wpa_printf(MSG_DEBUG,
611
0
           "RADIUS: Message removed from queue - restart from beginning");
612
0
      entry = radius->msgs;
613
0
      prev = NULL;
614
0
      continue;
615
0
    }
616
617
0
    if (first == 0 || entry->next_try < first)
618
0
      first = entry->next_try;
619
620
0
    prev = entry;
621
0
    entry = entry->next;
622
0
  }
623
624
0
  if (radius->msgs) {
625
0
    if (first < now.sec)
626
0
      first = now.sec;
627
0
    eloop_cancel_timeout(radius_client_timer, radius, NULL);
628
0
    eloop_register_timeout(first - now.sec, 0,
629
0
               radius_client_timer, radius, NULL);
630
0
    hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
631
0
             HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
632
0
             "retransmit in %ld seconds",
633
0
             (long int) (first - now.sec));
634
0
  }
635
0
}
636
637
638
static void radius_client_auth_failover(struct radius_client_data *radius)
639
0
{
640
0
  struct hostapd_radius_servers *conf = radius->conf;
641
0
  struct hostapd_radius_server *next, *old;
642
0
  struct radius_msg_list *entry;
643
0
  char abuf[50];
644
645
0
  old = conf->auth_server;
646
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
647
0
           HOSTAPD_LEVEL_NOTICE,
648
0
           "No response from Authentication server %s:%d - failover",
649
0
           hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
650
0
           old->port);
651
652
0
  for (entry = radius->msgs; entry; entry = entry->next) {
653
0
    if (entry->msg_type == RADIUS_AUTH)
654
0
      old->timeouts++;
655
0
  }
656
657
0
  next = old + 1;
658
0
  if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
659
0
    next = conf->auth_servers;
660
0
  conf->auth_server = next;
661
0
  radius_change_server(radius, next, old, 1);
662
0
}
663
664
665
static void radius_client_acct_failover(struct radius_client_data *radius)
666
0
{
667
0
  struct hostapd_radius_servers *conf = radius->conf;
668
0
  struct hostapd_radius_server *next, *old;
669
0
  struct radius_msg_list *entry;
670
0
  char abuf[50];
671
672
0
  old = conf->acct_server;
673
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
674
0
           HOSTAPD_LEVEL_NOTICE,
675
0
           "No response from Accounting server %s:%d - failover",
676
0
           hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
677
0
           old->port);
678
679
0
  for (entry = radius->msgs; entry; entry = entry->next) {
680
0
    if (entry->msg_type == RADIUS_ACCT ||
681
0
        entry->msg_type == RADIUS_ACCT_INTERIM)
682
0
      old->timeouts++;
683
0
  }
684
685
0
  next = old + 1;
686
0
  if (next > &conf->acct_servers[conf->num_acct_servers - 1])
687
0
    next = conf->acct_servers;
688
0
  conf->acct_server = next;
689
0
  radius_change_server(radius, next, old, 0);
690
0
}
691
692
693
static void radius_client_update_timeout(struct radius_client_data *radius)
694
0
{
695
0
  struct os_reltime now;
696
0
  os_time_t first;
697
0
  struct radius_msg_list *entry;
698
699
0
  eloop_cancel_timeout(radius_client_timer, radius, NULL);
700
701
0
  if (radius->msgs == NULL) {
702
0
    return;
703
0
  }
704
705
0
  first = 0;
706
0
  for (entry = radius->msgs; entry; entry = entry->next) {
707
0
    if (first == 0 || entry->next_try < first)
708
0
      first = entry->next_try;
709
0
  }
710
711
0
  os_get_reltime(&now);
712
0
  if (first < now.sec)
713
0
    first = now.sec;
714
0
  eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
715
0
             NULL);
716
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
717
0
           HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
718
0
           " %ld seconds", (long int) (first - now.sec));
719
0
}
720
721
722
static void radius_client_list_add(struct radius_client_data *radius,
723
           struct radius_msg *msg,
724
           RadiusType msg_type,
725
           const u8 *shared_secret,
726
           size_t shared_secret_len, const u8 *addr)
727
0
{
728
0
  struct radius_msg_list *entry, *prev;
729
730
0
  if (eloop_terminated()) {
731
    /* No point in adding entries to retransmit queue since event
732
     * loop has already been terminated. */
733
0
    radius_msg_free(msg);
734
0
    return;
735
0
  }
736
737
0
  entry = os_zalloc(sizeof(*entry));
738
0
  if (entry == NULL) {
739
0
    wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list");
740
0
    radius_msg_free(msg);
741
0
    return;
742
0
  }
743
744
0
  if (addr)
745
0
    os_memcpy(entry->addr, addr, ETH_ALEN);
746
0
  entry->msg = msg;
747
0
  entry->msg_type = msg_type;
748
0
  entry->shared_secret = shared_secret;
749
0
  entry->shared_secret_len = shared_secret_len;
750
0
  os_get_reltime(&entry->last_attempt);
751
0
  entry->first_try = entry->last_attempt.sec;
752
0
  entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
753
0
  entry->attempts = 1;
754
0
  entry->accu_attempts = 1;
755
0
  entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
756
0
  if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
757
0
    entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
758
0
  entry->next = radius->msgs;
759
0
  radius->msgs = entry;
760
0
  radius_client_update_timeout(radius);
761
762
0
  if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
763
0
    wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits");
764
0
    prev = NULL;
765
0
    while (entry->next) {
766
0
      prev = entry;
767
0
      entry = entry->next;
768
0
    }
769
0
    if (prev) {
770
0
      prev->next = NULL;
771
0
      radius_client_msg_free(entry);
772
0
    }
773
0
  } else
774
0
    radius->num_msgs++;
775
0
}
776
777
778
static int radius_client_disable_pmtu_discovery(int s)
779
0
{
780
0
  int r = -1;
781
0
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
782
  /* Turn off Path MTU discovery on IPv4/UDP sockets. */
783
0
  int action = IP_PMTUDISC_DONT;
784
0
  r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action,
785
0
           sizeof(action));
786
0
  if (r == -1)
787
0
    wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s",
788
0
         strerror(errno));
789
0
#endif
790
0
  return r;
791
0
}
792
793
794
static void radius_close_auth_socket(struct radius_client_data *radius)
795
0
{
796
0
  if (radius->auth_sock >= 0) {
797
#ifdef CONFIG_RADIUS_TLS
798
    if (radius->conf->auth_server->tls)
799
      eloop_unregister_sock(radius->auth_sock,
800
                EVENT_TYPE_WRITE);
801
#endif /* CONFIG_RADIUS_TLS */
802
0
    eloop_unregister_read_sock(radius->auth_sock);
803
0
    close(radius->auth_sock);
804
0
    radius->auth_sock = -1;
805
0
  }
806
0
}
807
808
809
static void radius_close_acct_socket(struct radius_client_data *radius)
810
0
{
811
0
  if (radius->acct_sock >= 0) {
812
#ifdef CONFIG_RADIUS_TLS
813
    if (radius->conf->acct_server->tls)
814
      eloop_unregister_sock(radius->acct_sock,
815
                EVENT_TYPE_WRITE);
816
#endif /* CONFIG_RADIUS_TLS */
817
0
    eloop_unregister_read_sock(radius->acct_sock);
818
0
    close(radius->acct_sock);
819
0
    radius->acct_sock = -1;
820
0
  }
821
0
}
822
823
824
/**
825
 * radius_client_send - Send a RADIUS request
826
 * @radius: RADIUS client context from radius_client_init()
827
 * @msg: RADIUS message to be sent
828
 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
829
 * @addr: MAC address of the device related to this message or %NULL
830
 * Returns: 0 on success, -1 on failure
831
 *
832
 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
833
 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
834
 * between accounting and interim accounting messages is that the interim
835
 * message will not be retransmitted. Instead, a callback is used to indicate
836
 * that the transmission failed for the specific station @addr so that a new
837
 * interim accounting update message can be generated with up-to-date session
838
 * data instead of trying to resend old information.
839
 *
840
 * The message is added on the retransmission queue and will be retransmitted
841
 * automatically until a response is received or maximum number of retries
842
 * (RADIUS_CLIENT_MAX_FAILOVER * RADIUS_CLIENT_NUM_FAILOVER) is reached. No
843
 * such retries are used with RADIUS_ACCT_INTERIM, i.e., such a pending message
844
 * is removed from the queue automatically on transmission failure.
845
 *
846
 * The related device MAC address can be used to identify pending messages that
847
 * can be removed with radius_client_flush_auth().
848
 */
849
int radius_client_send(struct radius_client_data *radius,
850
           struct radius_msg *msg, RadiusType msg_type,
851
           const u8 *addr)
852
0
{
853
0
  struct hostapd_radius_servers *conf = radius->conf;
854
0
  const u8 *shared_secret;
855
0
  size_t shared_secret_len;
856
0
  char *name;
857
0
  int s, res;
858
0
  struct wpabuf *buf;
859
#ifdef CONFIG_RADIUS_TLS
860
  struct wpabuf *out = NULL;
861
  struct tls_connection *conn = NULL;
862
  bool acct = false;
863
#endif /* CONFIG_RADIUS_TLS */
864
865
0
  if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
866
#ifdef CONFIG_RADIUS_TLS
867
    acct = true;
868
    if (radius->acct_tls)
869
      conn = radius->acct_tls_conn;
870
#endif /* CONFIG_RADIUS_TLS */
871
0
    if (conf->acct_server && radius->acct_sock < 0)
872
0
      radius_client_init_acct(radius);
873
874
0
    if (conf->acct_server == NULL || radius->acct_sock < 0 ||
875
0
        conf->acct_server->shared_secret == NULL) {
876
0
      hostapd_logger(radius->ctx, NULL,
877
0
               HOSTAPD_MODULE_RADIUS,
878
0
               HOSTAPD_LEVEL_INFO,
879
0
               "No accounting server configured");
880
0
      return -1;
881
0
    }
882
0
    shared_secret = conf->acct_server->shared_secret;
883
0
    shared_secret_len = conf->acct_server->shared_secret_len;
884
0
    if (radius_msg_finish_acct(msg, shared_secret,
885
0
             shared_secret_len) < 0) {
886
0
      hostapd_logger(radius->ctx, NULL,
887
0
               HOSTAPD_MODULE_RADIUS,
888
0
               HOSTAPD_LEVEL_INFO,
889
0
               "Failed to build RADIUS accounting message");
890
0
      return -1;
891
0
    }
892
0
    name = "accounting";
893
0
    s = radius->acct_sock;
894
0
    conf->acct_server->requests++;
895
0
  } else {
896
#ifdef CONFIG_RADIUS_TLS
897
    if (radius->auth_tls)
898
      conn = radius->auth_tls_conn;
899
#endif /* CONFIG_RADIUS_TLS */
900
0
    if (conf->auth_server && radius->auth_sock < 0)
901
0
      radius_client_init_auth(radius);
902
903
0
    if (conf->auth_server == NULL || radius->auth_sock < 0 ||
904
0
        conf->auth_server->shared_secret == NULL) {
905
0
      hostapd_logger(radius->ctx, NULL,
906
0
               HOSTAPD_MODULE_RADIUS,
907
0
               HOSTAPD_LEVEL_INFO,
908
0
               "No authentication server configured");
909
0
      return -1;
910
0
    }
911
0
    shared_secret = conf->auth_server->shared_secret;
912
0
    shared_secret_len = conf->auth_server->shared_secret_len;
913
0
    if (radius_msg_finish(msg, shared_secret, shared_secret_len) <
914
0
        0) {
915
0
      hostapd_logger(radius->ctx, NULL,
916
0
               HOSTAPD_MODULE_RADIUS,
917
0
               HOSTAPD_LEVEL_INFO,
918
0
               "Failed to build RADIUS authentication message");
919
0
      return -1;
920
0
    }
921
0
    name = "authentication";
922
0
    s = radius->auth_sock;
923
0
    conf->auth_server->requests++;
924
0
  }
925
926
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
927
0
           HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
928
0
           "server", name);
929
0
  if (conf->msg_dumps)
930
0
    radius_msg_dump(msg);
931
932
#ifdef CONFIG_RADIUS_TLS
933
  if ((acct && radius->acct_tls && !radius->acct_tls_ready) ||
934
      (!acct && radius->auth_tls && !radius->auth_tls_ready)) {
935
    wpa_printf(MSG_DEBUG,
936
         "RADIUS: TLS connection not yet ready for TX");
937
    goto skip_send;
938
  }
939
#endif /* CONFIG_RADIUS_TLS */
940
941
0
  buf = radius_msg_get_buf(msg);
942
#ifdef CONFIG_RADIUS_TLS
943
  if (conn) {
944
    out = tls_connection_encrypt(radius->tls_ctx, conn, buf);
945
    if (!out) {
946
      wpa_printf(MSG_INFO,
947
           "RADIUS: Failed to encrypt RADIUS message (TLS)");
948
      return -1;
949
    }
950
    wpa_printf(MSG_DEBUG,
951
         "RADIUS: TLS encryption of %zu bytes of plaintext to %zu bytes of ciphertext",
952
         wpabuf_len(buf), wpabuf_len(out));
953
    buf = out;
954
  }
955
#endif /* CONFIG_RADIUS_TLS */
956
0
  wpa_printf(MSG_DEBUG, "RADIUS: Send %zu bytes to the server",
957
0
       wpabuf_len(buf));
958
0
  res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
959
#ifdef CONFIG_RADIUS_TLS
960
  wpabuf_free(out);
961
#endif /* CONFIG_RADIUS_TLS */
962
0
  if (res < 0)
963
0
    radius_client_handle_send_error(radius, s, msg_type);
964
965
#ifdef CONFIG_RADIUS_TLS
966
skip_send:
967
#endif /* CONFIG_RADIUS_TLS */
968
0
  radius_client_list_add(radius, msg, msg_type, shared_secret,
969
0
             shared_secret_len, addr);
970
971
0
  return 0;
972
0
}
973
974
975
#ifdef CONFIG_RADIUS_TLS
976
977
static void radius_client_close_tcp(struct radius_client_data *radius,
978
            int sock, RadiusType msg_type)
979
{
980
  wpa_printf(MSG_DEBUG, "RADIUS: Closing TCP connection (sock %d)",
981
       sock);
982
  if (msg_type == RADIUS_ACCT) {
983
    radius->acct_tls_ready = false;
984
    radius_close_acct_socket(radius);
985
  } else {
986
    radius->auth_tls_ready = false;
987
    radius_close_auth_socket(radius);
988
  }
989
}
990
991
992
static void
993
radius_client_process_tls_handshake(struct radius_client_data *radius,
994
            int sock, RadiusType msg_type,
995
            u8 *buf, size_t len)
996
{
997
  struct wpabuf *in, *out = NULL, *appl;
998
  struct tls_connection *conn;
999
  int res;
1000
  bool ready = false;
1001
1002
  wpa_printf(MSG_DEBUG,
1003
       "RADIUS: Process %zu bytes of received TLS handshake message",
1004
       len);
1005
1006
  if (msg_type == RADIUS_ACCT)
1007
    conn = radius->acct_tls_conn;
1008
  else
1009
    conn = radius->auth_tls_conn;
1010
1011
  in = wpabuf_alloc_copy(buf, len);
1012
  if (!in)
1013
    return;
1014
1015
  appl = NULL;
1016
  out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1017
  wpabuf_free(in);
1018
  if (!out) {
1019
    wpa_printf(MSG_DEBUG,
1020
         "RADIUS: Could not generate TLS handshake data");
1021
    goto fail;
1022
  }
1023
1024
  if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1025
    wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1026
    goto fail;
1027
  }
1028
1029
  if (tls_connection_established(radius->tls_ctx, conn)) {
1030
    wpa_printf(MSG_DEBUG,
1031
         "RADIUS: TLS connection established (sock=%d)",
1032
         sock);
1033
    if (msg_type == RADIUS_ACCT)
1034
      radius->acct_tls_ready = true;
1035
    else
1036
      radius->auth_tls_ready = true;
1037
    ready = true;
1038
  }
1039
1040
  wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1041
       wpabuf_len(out));
1042
  res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1043
  if (res < 0) {
1044
    wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1045
    goto fail;
1046
  }
1047
  if ((size_t) res != wpabuf_len(out)) {
1048
    wpa_printf(MSG_INFO,
1049
         "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1050
         res);
1051
    goto fail;
1052
  }
1053
  wpabuf_free(out);
1054
1055
  if (ready) {
1056
    struct radius_msg_list *entry, *prev, *tmp;
1057
    struct os_reltime now;
1058
1059
    /* Send all pending message of matching type since the TLS
1060
     * tunnel has now been established. */
1061
1062
    os_get_reltime(&now);
1063
1064
    entry = radius->msgs;
1065
    prev = NULL;
1066
    while (entry) {
1067
      if (entry->msg_type != msg_type) {
1068
        prev = entry;
1069
        entry = entry->next;
1070
        continue;
1071
      }
1072
1073
      if (radius_client_retransmit(radius, entry, now.sec)) {
1074
        if (prev)
1075
          prev->next = entry->next;
1076
        else
1077
          radius->msgs = entry->next;
1078
1079
        tmp = entry;
1080
        entry = entry->next;
1081
        radius_client_msg_free(tmp);
1082
        radius->num_msgs--;
1083
        continue;
1084
      }
1085
1086
      prev = entry;
1087
      entry = entry->next;
1088
    }
1089
  }
1090
1091
  return;
1092
1093
fail:
1094
  wpabuf_free(out);
1095
  tls_connection_deinit(radius->tls_ctx, conn);
1096
  if (msg_type == RADIUS_ACCT)
1097
    radius->acct_tls_conn = NULL;
1098
  else
1099
    radius->auth_tls_conn = NULL;
1100
  radius_client_close_tcp(radius, sock, msg_type);
1101
}
1102
1103
#endif /* CONFIG_RADIUS_TLS */
1104
1105
1106
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
1107
0
{
1108
0
  struct radius_client_data *radius = eloop_ctx;
1109
0
  struct hostapd_radius_servers *conf = radius->conf;
1110
0
  RadiusType msg_type = (uintptr_t) sock_ctx;
1111
0
  int len, roundtrip;
1112
0
  unsigned char buf[RADIUS_MAX_MSG_LEN];
1113
0
  struct msghdr msghdr = {0};
1114
0
  struct iovec iov;
1115
0
  struct radius_msg *msg;
1116
0
  struct radius_hdr *hdr;
1117
0
  struct radius_rx_handler *handlers;
1118
0
  size_t num_handlers, i;
1119
0
  struct radius_msg_list *req, *prev_req, *r;
1120
0
  struct os_reltime now;
1121
0
  struct hostapd_radius_server *rconf;
1122
0
  int invalid_authenticator = 0;
1123
#ifdef CONFIG_RADIUS_TLS
1124
  struct tls_connection *conn = NULL;
1125
  bool tls, tls_ready;
1126
#endif /* CONFIG_RADIUS_TLS */
1127
1128
0
  if (msg_type == RADIUS_ACCT) {
1129
#ifdef CONFIG_RADIUS_TLS
1130
    if (radius->acct_tls)
1131
      conn = radius->acct_tls_conn;
1132
    tls = radius->acct_tls;
1133
    tls_ready = radius->acct_tls_ready;
1134
#endif /* CONFIG_RADIUS_TLS */
1135
0
    handlers = radius->acct_handlers;
1136
0
    num_handlers = radius->num_acct_handlers;
1137
0
    rconf = conf->acct_server;
1138
0
  } else {
1139
#ifdef CONFIG_RADIUS_TLS
1140
    if (radius->auth_tls)
1141
      conn = radius->auth_tls_conn;
1142
    tls = radius->auth_tls;
1143
    tls_ready = radius->auth_tls_ready;
1144
#endif /* CONFIG_RADIUS_TLS */
1145
0
    handlers = radius->auth_handlers;
1146
0
    num_handlers = radius->num_auth_handlers;
1147
0
    rconf = conf->auth_server;
1148
0
  }
1149
1150
0
  iov.iov_base = buf;
1151
0
  iov.iov_len = RADIUS_MAX_MSG_LEN;
1152
0
  msghdr.msg_iov = &iov;
1153
0
  msghdr.msg_iovlen = 1;
1154
0
  msghdr.msg_flags = 0;
1155
0
  len = recvmsg(sock, &msghdr, MSG_DONTWAIT);
1156
0
  if (len < 0) {
1157
0
    wpa_printf(MSG_INFO, "recvmsg[RADIUS]: %s", strerror(errno));
1158
0
    return;
1159
0
  }
1160
#ifdef CONFIG_RADIUS_TLS
1161
  if (tls && len == 0) {
1162
    wpa_printf(MSG_DEBUG, "RADIUS: No TCP data available");
1163
    goto close_tcp;
1164
  }
1165
1166
  if (tls && !tls_ready) {
1167
    radius_client_process_tls_handshake(radius, sock, msg_type,
1168
                buf, len);
1169
    return;
1170
  }
1171
1172
  if (conn) {
1173
    struct wpabuf *out, *in;
1174
1175
    in = wpabuf_alloc_copy(buf, len);
1176
    if (!in)
1177
      return;
1178
    wpa_printf(MSG_DEBUG,
1179
         "RADIUS: Process %d bytes of encrypted TLS data",
1180
         len);
1181
    out = tls_connection_decrypt(radius->tls_ctx, conn, in);
1182
    wpabuf_free(in);
1183
    if (!out) {
1184
      wpa_printf(MSG_INFO,
1185
           "RADIUS: Failed to decrypt TLS data");
1186
      goto close_tcp;
1187
    }
1188
    if (wpabuf_len(out) == 0) {
1189
      wpa_printf(MSG_DEBUG,
1190
           "RADIUS: Full message not yet received - continue waiting for additional TLS data");
1191
      wpabuf_free(out);
1192
      return;
1193
    }
1194
    if (wpabuf_len(out) > RADIUS_MAX_MSG_LEN) {
1195
      wpa_printf(MSG_INFO,
1196
           "RADIUS: Too long RADIUS message from TLS: %zu",
1197
           wpabuf_len(out));
1198
      wpabuf_free(out);
1199
      goto close_tcp;
1200
    }
1201
    os_memcpy(buf, wpabuf_head(out), wpabuf_len(out));
1202
    len = wpabuf_len(out);
1203
    wpabuf_free(out);
1204
  }
1205
#endif /* CONFIG_RADIUS_TLS */
1206
1207
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1208
0
           HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
1209
0
           "server", len);
1210
1211
0
  if (msghdr.msg_flags & MSG_TRUNC) {
1212
0
    wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it");
1213
0
    return;
1214
0
  }
1215
1216
0
  msg = radius_msg_parse(buf, len);
1217
0
  if (msg == NULL) {
1218
0
    wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed");
1219
0
    rconf->malformed_responses++;
1220
0
    return;
1221
0
  }
1222
0
  hdr = radius_msg_get_hdr(msg);
1223
1224
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1225
0
           HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
1226
0
  if (conf->msg_dumps)
1227
0
    radius_msg_dump(msg);
1228
1229
0
  switch (hdr->code) {
1230
0
  case RADIUS_CODE_ACCESS_ACCEPT:
1231
0
    rconf->access_accepts++;
1232
0
    break;
1233
0
  case RADIUS_CODE_ACCESS_REJECT:
1234
0
    rconf->access_rejects++;
1235
0
    break;
1236
0
  case RADIUS_CODE_ACCESS_CHALLENGE:
1237
0
    rconf->access_challenges++;
1238
0
    break;
1239
0
  case RADIUS_CODE_ACCOUNTING_RESPONSE:
1240
0
    rconf->responses++;
1241
0
    break;
1242
0
  }
1243
1244
0
  req = radius->msgs;
1245
0
  while (req) {
1246
    /* TODO: also match by src addr:port of the packet when using
1247
     * alternative RADIUS servers (?) */
1248
0
    if ((req->msg_type == msg_type ||
1249
0
         (req->msg_type == RADIUS_ACCT_INTERIM &&
1250
0
          msg_type == RADIUS_ACCT)) &&
1251
0
        radius_msg_get_hdr(req->msg)->identifier ==
1252
0
        hdr->identifier)
1253
0
      break;
1254
1255
0
    req = req->next;
1256
0
  }
1257
1258
0
  if (req == NULL) {
1259
0
    hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1260
0
             HOSTAPD_LEVEL_DEBUG,
1261
0
             "No matching RADIUS request found (type=%d "
1262
0
             "id=%d) - dropping packet",
1263
0
             msg_type, hdr->identifier);
1264
0
    goto fail;
1265
0
  }
1266
1267
0
  os_get_reltime(&now);
1268
0
  roundtrip = (now.sec - req->last_attempt.sec) * 100 +
1269
0
    (now.usec - req->last_attempt.usec) / 10000;
1270
0
  hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1271
0
           HOSTAPD_LEVEL_DEBUG,
1272
0
           "Received RADIUS packet matched with a pending "
1273
0
           "request, round trip time %d.%02d sec",
1274
0
           roundtrip / 100, roundtrip % 100);
1275
0
  rconf->round_trip_time = roundtrip;
1276
1277
0
  for (i = 0; i < num_handlers; i++) {
1278
0
    RadiusRxResult res;
1279
0
    res = handlers[i].handler(msg, req->msg, req->shared_secret,
1280
0
            req->shared_secret_len,
1281
0
            handlers[i].data);
1282
0
    switch (res) {
1283
0
    case RADIUS_RX_PROCESSED:
1284
0
      radius_msg_free(msg);
1285
      /* fall through */
1286
0
    case RADIUS_RX_QUEUED:
1287
      /* Remove ACKed RADIUS packet from retransmit list */
1288
0
      prev_req = NULL;
1289
0
      for (r = radius->msgs; r; r = r->next) {
1290
0
        if (r == req)
1291
0
          break;
1292
0
        prev_req = r;
1293
0
      }
1294
0
      if (prev_req)
1295
0
        prev_req->next = req->next;
1296
0
      else
1297
0
        radius->msgs = req->next;
1298
0
      radius->num_msgs--;
1299
1300
0
      radius_client_msg_free(req);
1301
0
      return;
1302
0
    case RADIUS_RX_INVALID_AUTHENTICATOR:
1303
0
      invalid_authenticator++;
1304
      /* fall through */
1305
0
    case RADIUS_RX_UNKNOWN:
1306
      /* continue with next handler */
1307
0
      break;
1308
0
    }
1309
0
  }
1310
1311
0
  if (invalid_authenticator)
1312
0
    rconf->bad_authenticators++;
1313
0
  else
1314
0
    rconf->unknown_types++;
1315
0
  hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
1316
0
           HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
1317
0
           "(type=%d code=%d id=%d)%s - dropping packet",
1318
0
           msg_type, hdr->code, hdr->identifier,
1319
0
           invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
1320
0
           "");
1321
1322
0
 fail:
1323
0
  radius_msg_free(msg);
1324
0
  return;
1325
1326
#ifdef CONFIG_RADIUS_TLS
1327
close_tcp:
1328
  radius_client_close_tcp(radius, sock, msg_type);
1329
#endif /* CONFIG_RADIUS_TLS */
1330
0
}
1331
1332
1333
#ifdef CONFIG_RADIUS_TLS
1334
static void radius_client_write_ready(int sock, void *eloop_ctx, void *sock_ctx)
1335
{
1336
  struct radius_client_data *radius = eloop_ctx;
1337
  RadiusType msg_type = (uintptr_t) sock_ctx;
1338
  struct tls_connection *conn = NULL;
1339
  struct wpabuf *in, *out = NULL, *appl;
1340
  int res = -1;
1341
  struct tls_connection_params params;
1342
  struct hostapd_radius_server *server;
1343
1344
  wpa_printf(MSG_DEBUG, "RADIUS: TCP connection established - start TLS handshake (sock=%d)",
1345
       sock);
1346
1347
  if (msg_type == RADIUS_ACCT) {
1348
    eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1349
    eloop_register_read_sock(sock, radius_client_receive, radius,
1350
           (void *) RADIUS_ACCT);
1351
    if (radius->acct_tls_conn) {
1352
      wpa_printf(MSG_DEBUG,
1353
           "RADIUS: Deinit previously used TLS connection");
1354
      tls_connection_deinit(radius->tls_ctx,
1355
                radius->acct_tls_conn);
1356
      radius->acct_tls_conn = NULL;
1357
    }
1358
    server = radius->conf->acct_server;
1359
  } else {
1360
    eloop_unregister_sock(sock, EVENT_TYPE_WRITE);
1361
    eloop_register_read_sock(sock, radius_client_receive, radius,
1362
           (void *) RADIUS_AUTH);
1363
    if (radius->auth_tls_conn) {
1364
      wpa_printf(MSG_DEBUG,
1365
           "RADIUS: Deinit previously used TLS connection");
1366
      tls_connection_deinit(radius->tls_ctx,
1367
                radius->auth_tls_conn);
1368
      radius->auth_tls_conn = NULL;
1369
    }
1370
    server = radius->conf->auth_server;
1371
  }
1372
1373
  if (!server)
1374
    goto fail;
1375
1376
  conn = tls_connection_init(radius->tls_ctx);
1377
  if (!conn) {
1378
    wpa_printf(MSG_INFO,
1379
         "RADIUS: Failed to initiate TLS connection");
1380
    goto fail;
1381
  }
1382
1383
  os_memset(&params, 0, sizeof(params));
1384
  params.ca_cert = server->ca_cert;
1385
  params.client_cert = server->client_cert;
1386
  params.private_key = server->private_key;
1387
  params.private_key_passwd = server->private_key_passwd;
1388
  params.flags = TLS_CONN_DISABLE_TLSv1_0 | TLS_CONN_DISABLE_TLSv1_1;
1389
  if (tls_connection_set_params(radius->tls_ctx, conn, &params)) {
1390
    wpa_printf(MSG_INFO,
1391
         "RADIUS: Failed to set TLS connection parameters");
1392
    goto fail;
1393
  }
1394
1395
  in = NULL;
1396
  appl = NULL;
1397
  out = tls_connection_handshake(radius->tls_ctx, conn, in, &appl);
1398
  if (!out) {
1399
    wpa_printf(MSG_DEBUG,
1400
         "RADIUS: Could not generate TLS handshake data");
1401
    goto fail;
1402
  }
1403
1404
  if (tls_connection_get_failed(radius->tls_ctx, conn)) {
1405
    wpa_printf(MSG_INFO, "RADIUS: TLS handshake failed");
1406
    goto fail;
1407
  }
1408
1409
  wpa_printf(MSG_DEBUG, "RADIUS: Sending %zu bytes of TLS handshake",
1410
       wpabuf_len(out));
1411
  res = send(sock, wpabuf_head(out), wpabuf_len(out), 0);
1412
  if (res < 0) {
1413
    wpa_printf(MSG_INFO, "RADIUS: send: %s", strerror(errno));
1414
    goto fail;
1415
  }
1416
  if ((size_t) res != wpabuf_len(out)) {
1417
    wpa_printf(MSG_INFO,
1418
         "RADIUS: Could not send all data for TLS handshake: only %d bytes sent",
1419
         res);
1420
    goto fail;
1421
  }
1422
  wpabuf_free(out);
1423
1424
  if (msg_type == RADIUS_ACCT)
1425
    radius->acct_tls_conn = conn;
1426
  else
1427
    radius->auth_tls_conn = conn;
1428
  return;
1429
1430
fail:
1431
  wpa_printf(MSG_INFO, "RADIUS: Failed to perform TLS handshake");
1432
  tls_connection_deinit(radius->tls_ctx, conn);
1433
  wpabuf_free(out);
1434
  radius_client_close_tcp(radius, sock, msg_type);
1435
}
1436
#endif /* CONFIG_RADIUS_TLS */
1437
1438
1439
/**
1440
 * radius_client_get_id - Get an identifier for a new RADIUS message
1441
 * @radius: RADIUS client context from radius_client_init()
1442
 * Returns: Allocated identifier
1443
 *
1444
 * This function is used to fetch a unique (among pending requests) identifier
1445
 * for a new RADIUS message.
1446
 */
1447
u8 radius_client_get_id(struct radius_client_data *radius)
1448
0
{
1449
0
  struct radius_msg_list *entry, *prev, *_remove;
1450
0
  u8 id = radius->next_radius_identifier++;
1451
1452
  /* remove entries with matching id from retransmit list to avoid
1453
   * using new reply from the RADIUS server with an old request */
1454
0
  entry = radius->msgs;
1455
0
  prev = NULL;
1456
0
  while (entry) {
1457
0
    if (radius_msg_get_hdr(entry->msg)->identifier == id) {
1458
0
      hostapd_logger(radius->ctx, entry->addr,
1459
0
               HOSTAPD_MODULE_RADIUS,
1460
0
               HOSTAPD_LEVEL_DEBUG,
1461
0
               "Removing pending RADIUS message, "
1462
0
               "since its id (%d) is reused", id);
1463
0
      if (prev)
1464
0
        prev->next = entry->next;
1465
0
      else
1466
0
        radius->msgs = entry->next;
1467
0
      _remove = entry;
1468
0
    } else {
1469
0
      _remove = NULL;
1470
0
      prev = entry;
1471
0
    }
1472
0
    entry = entry->next;
1473
1474
0
    if (_remove)
1475
0
      radius_client_msg_free(_remove);
1476
0
  }
1477
1478
0
  return id;
1479
0
}
1480
1481
1482
/**
1483
 * radius_client_flush - Flush all pending RADIUS client messages
1484
 * @radius: RADIUS client context from radius_client_init()
1485
 * @only_auth: Whether only authentication messages are removed
1486
 */
1487
void radius_client_flush(struct radius_client_data *radius, int only_auth)
1488
0
{
1489
0
  struct radius_msg_list *entry, *prev, *tmp;
1490
1491
0
  if (!radius)
1492
0
    return;
1493
1494
0
  prev = NULL;
1495
0
  entry = radius->msgs;
1496
1497
0
  while (entry) {
1498
0
    if (!only_auth || entry->msg_type == RADIUS_AUTH) {
1499
0
      if (prev)
1500
0
        prev->next = entry->next;
1501
0
      else
1502
0
        radius->msgs = entry->next;
1503
1504
0
      tmp = entry;
1505
0
      entry = entry->next;
1506
0
      radius_client_msg_free(tmp);
1507
0
      radius->num_msgs--;
1508
0
    } else {
1509
0
      prev = entry;
1510
0
      entry = entry->next;
1511
0
    }
1512
0
  }
1513
1514
0
  if (radius->msgs == NULL)
1515
0
    eloop_cancel_timeout(radius_client_timer, radius, NULL);
1516
0
}
1517
1518
1519
static void radius_client_update_acct_msgs(struct radius_client_data *radius,
1520
             const u8 *shared_secret,
1521
             size_t shared_secret_len)
1522
0
{
1523
0
  struct radius_msg_list *entry;
1524
1525
0
  if (!radius)
1526
0
    return;
1527
1528
0
  for (entry = radius->msgs; entry; entry = entry->next) {
1529
0
    if (entry->msg_type == RADIUS_ACCT) {
1530
0
      entry->shared_secret = shared_secret;
1531
0
      entry->shared_secret_len = shared_secret_len;
1532
0
      if (radius_msg_finish_acct(entry->msg, shared_secret,
1533
0
               shared_secret_len) < 0)
1534
0
        wpa_printf(MSG_INFO,
1535
0
             "RADIUS: Failed to update accounting message");
1536
0
    }
1537
0
  }
1538
0
}
1539
1540
1541
static int
1542
radius_change_server(struct radius_client_data *radius,
1543
         struct hostapd_radius_server *nserv,
1544
         struct hostapd_radius_server *oserv,
1545
         int auth)
1546
0
{
1547
0
  struct sockaddr_in serv, claddr;
1548
0
#ifdef CONFIG_IPV6
1549
0
  struct sockaddr_in6 serv6, claddr6;
1550
0
#endif /* CONFIG_IPV6 */
1551
0
  struct sockaddr *addr, *cl_addr;
1552
0
  socklen_t addrlen, claddrlen;
1553
0
  char abuf[50];
1554
0
  int sel_sock;
1555
0
  struct radius_msg_list *entry;
1556
0
  struct hostapd_radius_servers *conf = radius->conf;
1557
0
  int type = SOCK_DGRAM;
1558
0
  bool tls = nserv->tls;
1559
1560
0
  if (tls) {
1561
#ifdef CONFIG_RADIUS_TLS
1562
    type = SOCK_STREAM;
1563
#else /* CONFIG_RADIUS_TLS */
1564
0
    wpa_printf(MSG_ERROR, "RADIUS: TLS not supported");
1565
0
    return -1;
1566
0
#endif /* CONFIG_RADIUS_TLS */
1567
0
  }
1568
1569
0
  hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
1570
0
           HOSTAPD_LEVEL_INFO,
1571
0
           "%s server %s:%d",
1572
0
           auth ? "Authentication" : "Accounting",
1573
0
           hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
1574
0
           nserv->port);
1575
1576
0
  if (oserv && oserv == nserv) {
1577
    /* Reconnect to same server, flush */
1578
0
    if (auth)
1579
0
      radius_client_flush(radius, 1);
1580
0
  }
1581
1582
0
  if (oserv && oserv != nserv &&
1583
0
      (nserv->shared_secret_len != oserv->shared_secret_len ||
1584
0
       os_memcmp(nserv->shared_secret, oserv->shared_secret,
1585
0
           nserv->shared_secret_len) != 0)) {
1586
    /* Pending RADIUS packets used different shared secret, so
1587
     * they need to be modified. Update accounting message
1588
     * authenticators here. Authentication messages are removed
1589
     * since they would require more changes and the new RADIUS
1590
     * server may not be prepared to receive them anyway due to
1591
     * missing state information. Client will likely retry
1592
     * authentication, so this should not be an issue. */
1593
0
    if (auth)
1594
0
      radius_client_flush(radius, 1);
1595
0
    else {
1596
0
      radius_client_update_acct_msgs(
1597
0
        radius, nserv->shared_secret,
1598
0
        nserv->shared_secret_len);
1599
0
    }
1600
0
  }
1601
1602
  /* Reset retry counters */
1603
0
  for (entry = radius->msgs; oserv && entry; entry = entry->next) {
1604
0
    if ((auth && entry->msg_type != RADIUS_AUTH) ||
1605
0
        (!auth && entry->msg_type != RADIUS_ACCT))
1606
0
      continue;
1607
0
    entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
1608
0
    entry->attempts = 0;
1609
0
    entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
1610
0
  }
1611
1612
0
  if (radius->msgs) {
1613
0
    eloop_cancel_timeout(radius_client_timer, radius, NULL);
1614
0
    eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
1615
0
               radius_client_timer, radius, NULL);
1616
0
  }
1617
1618
0
  switch (nserv->addr.af) {
1619
0
  case AF_INET:
1620
0
    os_memset(&serv, 0, sizeof(serv));
1621
0
    serv.sin_family = AF_INET;
1622
0
    serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
1623
0
    serv.sin_port = htons(nserv->port);
1624
0
    addr = (struct sockaddr *) &serv;
1625
0
    addrlen = sizeof(serv);
1626
0
    sel_sock = socket(PF_INET, type, 0);
1627
0
    if (sel_sock >= 0)
1628
0
      radius_client_disable_pmtu_discovery(sel_sock);
1629
0
    break;
1630
0
#ifdef CONFIG_IPV6
1631
0
  case AF_INET6:
1632
0
    os_memset(&serv6, 0, sizeof(serv6));
1633
0
    serv6.sin6_family = AF_INET6;
1634
0
    os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
1635
0
        sizeof(struct in6_addr));
1636
0
    serv6.sin6_port = htons(nserv->port);
1637
0
    addr = (struct sockaddr *) &serv6;
1638
0
    addrlen = sizeof(serv6);
1639
0
    sel_sock = socket(PF_INET6, type, 0);
1640
0
    break;
1641
0
#endif /* CONFIG_IPV6 */
1642
0
  default:
1643
0
    return -1;
1644
0
  }
1645
1646
0
  if (sel_sock < 0) {
1647
0
    wpa_printf(MSG_INFO,
1648
0
         "RADIUS: Failed to open server socket (af=%d auth=%d)",
1649
0
         nserv->addr.af, auth);
1650
0
    return -1;
1651
0
  }
1652
1653
#ifdef CONFIG_RADIUS_TLS
1654
  if (tls && fcntl(sel_sock, F_SETFL, O_NONBLOCK) != 0) {
1655
    wpa_printf(MSG_DEBUG, "RADIUS: fnctl(O_NONBLOCK) failed: %s",
1656
         strerror(errno));
1657
    close(sel_sock);
1658
    return -1;
1659
  }
1660
#endif /* CONFIG_RADIUS_TLS */
1661
1662
0
#ifdef __linux__
1663
0
  if (conf->force_client_dev && conf->force_client_dev[0]) {
1664
0
    if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
1665
0
             conf->force_client_dev,
1666
0
             os_strlen(conf->force_client_dev)) < 0) {
1667
0
      wpa_printf(MSG_ERROR,
1668
0
           "RADIUS: setsockopt[SO_BINDTODEVICE]: %s",
1669
0
           strerror(errno));
1670
      /* Probably not a critical error; continue on and hope
1671
       * for the best. */
1672
0
    } else {
1673
0
      wpa_printf(MSG_DEBUG,
1674
0
           "RADIUS: Bound client socket to device: %s",
1675
0
           conf->force_client_dev);
1676
0
    }
1677
0
  }
1678
0
#endif /* __linux__ */
1679
1680
0
  if (conf->force_client_addr) {
1681
0
    switch (conf->client_addr.af) {
1682
0
    case AF_INET:
1683
0
      os_memset(&claddr, 0, sizeof(claddr));
1684
0
      claddr.sin_family = AF_INET;
1685
0
      claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr;
1686
0
      claddr.sin_port = htons(0);
1687
0
      cl_addr = (struct sockaddr *) &claddr;
1688
0
      claddrlen = sizeof(claddr);
1689
0
      break;
1690
0
#ifdef CONFIG_IPV6
1691
0
    case AF_INET6:
1692
0
      os_memset(&claddr6, 0, sizeof(claddr6));
1693
0
      claddr6.sin6_family = AF_INET6;
1694
0
      os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6,
1695
0
          sizeof(struct in6_addr));
1696
0
      claddr6.sin6_port = htons(0);
1697
0
      cl_addr = (struct sockaddr *) &claddr6;
1698
0
      claddrlen = sizeof(claddr6);
1699
0
      break;
1700
0
#endif /* CONFIG_IPV6 */
1701
0
    default:
1702
0
      close(sel_sock);
1703
0
      return -1;
1704
0
    }
1705
1706
0
    if (bind(sel_sock, cl_addr, claddrlen) < 0) {
1707
0
      wpa_printf(MSG_INFO, "bind[radius]: %s",
1708
0
           strerror(errno));
1709
0
      close(sel_sock);
1710
0
      return -2;
1711
0
    }
1712
0
  }
1713
1714
0
  if (connect(sel_sock, addr, addrlen) < 0) {
1715
0
    if (nserv->tls && errno == EINPROGRESS) {
1716
0
      wpa_printf(MSG_DEBUG,
1717
0
           "RADIUS: TCP connection establishment in progress (sock %d)",
1718
0
           sel_sock);
1719
0
    } else {
1720
0
      wpa_printf(MSG_INFO, "connect[radius]: %s",
1721
0
           strerror(errno));
1722
0
      close(sel_sock);
1723
0
      return -2;
1724
0
    }
1725
0
  }
1726
1727
0
#ifndef CONFIG_NATIVE_WINDOWS
1728
0
  switch (nserv->addr.af) {
1729
0
  case AF_INET:
1730
0
    claddrlen = sizeof(claddr);
1731
0
    if (getsockname(sel_sock, (struct sockaddr *) &claddr,
1732
0
        &claddrlen) == 0) {
1733
0
      wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1734
0
           inet_ntoa(claddr.sin_addr),
1735
0
           ntohs(claddr.sin_port));
1736
0
    }
1737
0
    break;
1738
0
#ifdef CONFIG_IPV6
1739
0
  case AF_INET6: {
1740
0
    claddrlen = sizeof(claddr6);
1741
0
    if (getsockname(sel_sock, (struct sockaddr *) &claddr6,
1742
0
        &claddrlen) == 0) {
1743
0
      wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
1744
0
           inet_ntop(AF_INET6, &claddr6.sin6_addr,
1745
0
               abuf, sizeof(abuf)),
1746
0
           ntohs(claddr6.sin6_port));
1747
0
    }
1748
0
    break;
1749
0
  }
1750
0
#endif /* CONFIG_IPV6 */
1751
0
  }
1752
0
#endif /* CONFIG_NATIVE_WINDOWS */
1753
1754
0
  if (auth) {
1755
0
    radius_close_auth_socket(radius);
1756
0
    radius->auth_sock = sel_sock;
1757
0
  } else {
1758
0
    radius_close_acct_socket(radius);
1759
0
    radius->acct_sock = sel_sock;
1760
0
  }
1761
1762
0
  if (!tls)
1763
0
    eloop_register_read_sock(sel_sock, radius_client_receive,
1764
0
           radius,
1765
0
           auth ? (void *) RADIUS_AUTH :
1766
0
           (void *) RADIUS_ACCT);
1767
#ifdef CONFIG_RADIUS_TLS
1768
  if (tls)
1769
    eloop_register_sock(sel_sock, EVENT_TYPE_WRITE,
1770
            radius_client_write_ready, radius,
1771
            auth ? (void *) RADIUS_AUTH :
1772
            (void *) RADIUS_ACCT);
1773
#endif /* CONFIG_RADIUS_TLS */
1774
1775
0
  if (auth) {
1776
0
    radius->auth_tls = nserv->tls;
1777
0
    radius->auth_tls_ready = false;
1778
0
  } else {
1779
0
    radius->acct_tls = nserv->tls;
1780
0
    radius->acct_tls_ready = false;
1781
0
  }
1782
1783
0
  return 0;
1784
0
}
1785
1786
1787
static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
1788
0
{
1789
0
  struct radius_client_data *radius = eloop_ctx;
1790
0
  struct hostapd_radius_servers *conf = radius->conf;
1791
0
  struct hostapd_radius_server *oserv;
1792
1793
0
  if (radius->auth_sock >= 0 && conf->auth_servers &&
1794
0
      conf->auth_server != conf->auth_servers) {
1795
0
    oserv = conf->auth_server;
1796
0
    conf->auth_server = conf->auth_servers;
1797
0
    if (radius_change_server(radius, conf->auth_server, oserv,
1798
0
           1) < 0) {
1799
0
      conf->auth_server = oserv;
1800
0
      radius_change_server(radius, oserv, conf->auth_server,
1801
0
               1);
1802
0
    }
1803
0
  }
1804
1805
0
  if (radius->acct_sock >= 0 && conf->acct_servers &&
1806
0
      conf->acct_server != conf->acct_servers) {
1807
0
    oserv = conf->acct_server;
1808
0
    conf->acct_server = conf->acct_servers;
1809
0
    if (radius_change_server(radius, conf->acct_server, oserv,
1810
0
           0) < 0) {
1811
0
      conf->acct_server = oserv;
1812
0
      radius_change_server(radius, oserv, conf->acct_server,
1813
0
               0);
1814
0
    }
1815
0
  }
1816
1817
0
  if (conf->retry_primary_interval)
1818
0
    eloop_register_timeout(conf->retry_primary_interval, 0,
1819
0
               radius_retry_primary_timer, radius,
1820
0
               NULL);
1821
0
}
1822
1823
1824
static int radius_client_init_auth(struct radius_client_data *radius)
1825
0
{
1826
0
  radius_close_auth_socket(radius);
1827
0
  return radius_change_server(radius, radius->conf->auth_server, NULL, 1);
1828
0
}
1829
1830
1831
static int radius_client_init_acct(struct radius_client_data *radius)
1832
0
{
1833
0
  radius_close_acct_socket(radius);
1834
0
  return radius_change_server(radius, radius->conf->acct_server, NULL, 0);
1835
0
}
1836
1837
1838
#ifdef CONFIG_RADIUS_TLS
1839
static void radius_tls_event_cb(void *ctx, enum tls_event ev,
1840
        union tls_event_data *data)
1841
{
1842
  wpa_printf(MSG_DEBUG, "RADIUS: TLS event %d", ev);
1843
}
1844
#endif /* CONFIG_RADIUS_TLS */
1845
1846
1847
/**
1848
 * radius_client_init - Initialize RADIUS client
1849
 * @ctx: Callback context to be used in hostapd_logger() calls
1850
 * @conf: RADIUS client configuration (RADIUS servers)
1851
 * Returns: Pointer to private RADIUS client context or %NULL on failure
1852
 *
1853
 * The caller is responsible for keeping the configuration data available for
1854
 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
1855
 * called for the returned context pointer.
1856
 */
1857
struct radius_client_data *
1858
radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
1859
0
{
1860
0
  struct radius_client_data *radius;
1861
1862
0
  radius = os_zalloc(sizeof(struct radius_client_data));
1863
0
  if (radius == NULL)
1864
0
    return NULL;
1865
1866
0
  radius->ctx = ctx;
1867
0
  radius->conf = conf;
1868
0
  radius->auth_sock = radius->acct_sock = -1;
1869
1870
0
  if (conf->auth_server && radius_client_init_auth(radius) == -1) {
1871
0
    radius_client_deinit(radius);
1872
0
    return NULL;
1873
0
  }
1874
1875
0
  if (conf->acct_server && radius_client_init_acct(radius) == -1) {
1876
0
    radius_client_deinit(radius);
1877
0
    return NULL;
1878
0
  }
1879
1880
0
  if (conf->retry_primary_interval)
1881
0
    eloop_register_timeout(conf->retry_primary_interval, 0,
1882
0
               radius_retry_primary_timer, radius,
1883
0
               NULL);
1884
1885
#ifdef CONFIG_RADIUS_TLS
1886
  if ((conf->auth_server && conf->auth_server->tls) ||
1887
      (conf->acct_server && conf->acct_server->tls)) {
1888
    struct tls_config tls_conf;
1889
1890
    os_memset(&tls_conf, 0, sizeof(tls_conf));
1891
    tls_conf.event_cb = radius_tls_event_cb;
1892
    radius->tls_ctx = tls_init(&tls_conf);
1893
    if (!radius->tls_ctx) {
1894
      radius_client_deinit(radius);
1895
      return NULL;
1896
    }
1897
  }
1898
#endif /* CONFIG_RADIUS_TLS */
1899
1900
1901
0
  return radius;
1902
0
}
1903
1904
1905
/**
1906
 * radius_client_deinit - Deinitialize RADIUS client
1907
 * @radius: RADIUS client context from radius_client_init()
1908
 */
1909
void radius_client_deinit(struct radius_client_data *radius)
1910
0
{
1911
0
  if (!radius)
1912
0
    return;
1913
1914
0
  radius_close_auth_socket(radius);
1915
0
  radius_close_acct_socket(radius);
1916
1917
0
  eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
1918
1919
0
  radius_client_flush(radius, 0);
1920
0
  os_free(radius->auth_handlers);
1921
0
  os_free(radius->acct_handlers);
1922
#ifdef CONFIG_RADIUS_TLS
1923
  if (radius->tls_ctx) {
1924
    tls_connection_deinit(radius->tls_ctx, radius->auth_tls_conn);
1925
    tls_connection_deinit(radius->tls_ctx, radius->acct_tls_conn);
1926
    tls_deinit(radius->tls_ctx);
1927
  }
1928
#endif /* CONFIG_RADIUS_TLS */
1929
0
  os_free(radius);
1930
0
}
1931
1932
1933
/**
1934
 * radius_client_flush_auth - Flush pending RADIUS messages for an address
1935
 * @radius: RADIUS client context from radius_client_init()
1936
 * @addr: MAC address of the related device
1937
 *
1938
 * This function can be used to remove pending RADIUS authentication messages
1939
 * that are related to a specific device. The addr parameter is matched with
1940
 * the one used in radius_client_send() call that was used to transmit the
1941
 * authentication request.
1942
 */
1943
void radius_client_flush_auth(struct radius_client_data *radius,
1944
            const u8 *addr)
1945
0
{
1946
0
  struct radius_msg_list *entry, *prev, *tmp;
1947
1948
0
  prev = NULL;
1949
0
  entry = radius->msgs;
1950
0
  while (entry) {
1951
0
    if (entry->msg_type == RADIUS_AUTH &&
1952
0
        ether_addr_equal(entry->addr, addr)) {
1953
0
      hostapd_logger(radius->ctx, addr,
1954
0
               HOSTAPD_MODULE_RADIUS,
1955
0
               HOSTAPD_LEVEL_DEBUG,
1956
0
               "Removing pending RADIUS authentication"
1957
0
               " message for removed client");
1958
1959
0
      if (prev)
1960
0
        prev->next = entry->next;
1961
0
      else
1962
0
        radius->msgs = entry->next;
1963
1964
0
      tmp = entry;
1965
0
      entry = entry->next;
1966
0
      radius_client_msg_free(tmp);
1967
0
      radius->num_msgs--;
1968
0
      continue;
1969
0
    }
1970
1971
0
    prev = entry;
1972
0
    entry = entry->next;
1973
0
  }
1974
0
}
1975
1976
1977
static int radius_client_dump_auth_server(char *buf, size_t buflen,
1978
            struct hostapd_radius_server *serv,
1979
            struct radius_client_data *cli)
1980
0
{
1981
0
  int pending = 0;
1982
0
  struct radius_msg_list *msg;
1983
0
  char abuf[50];
1984
1985
0
  if (cli) {
1986
0
    for (msg = cli->msgs; msg; msg = msg->next) {
1987
0
      if (msg->msg_type == RADIUS_AUTH)
1988
0
        pending++;
1989
0
    }
1990
0
  }
1991
1992
0
  return os_snprintf(buf, buflen,
1993
0
         "radiusAuthServerIndex=%d\n"
1994
0
         "radiusAuthServerAddress=%s\n"
1995
0
         "radiusAuthClientServerPortNumber=%d\n"
1996
0
         "radiusAuthClientRoundTripTime=%d\n"
1997
0
         "radiusAuthClientAccessRequests=%u\n"
1998
0
         "radiusAuthClientAccessRetransmissions=%u\n"
1999
0
         "radiusAuthClientAccessAccepts=%u\n"
2000
0
         "radiusAuthClientAccessRejects=%u\n"
2001
0
         "radiusAuthClientAccessChallenges=%u\n"
2002
0
         "radiusAuthClientMalformedAccessResponses=%u\n"
2003
0
         "radiusAuthClientBadAuthenticators=%u\n"
2004
0
         "radiusAuthClientPendingRequests=%u\n"
2005
0
         "radiusAuthClientTimeouts=%u\n"
2006
0
         "radiusAuthClientUnknownTypes=%u\n"
2007
0
         "radiusAuthClientPacketsDropped=%u\n",
2008
0
         serv->index,
2009
0
         hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
2010
0
         serv->port,
2011
0
         serv->round_trip_time,
2012
0
         serv->requests,
2013
0
         serv->retransmissions,
2014
0
         serv->access_accepts,
2015
0
         serv->access_rejects,
2016
0
         serv->access_challenges,
2017
0
         serv->malformed_responses,
2018
0
         serv->bad_authenticators,
2019
0
         pending,
2020
0
         serv->timeouts,
2021
0
         serv->unknown_types,
2022
0
         serv->packets_dropped);
2023
0
}
2024
2025
2026
static int radius_client_dump_acct_server(char *buf, size_t buflen,
2027
            struct hostapd_radius_server *serv,
2028
            struct radius_client_data *cli)
2029
0
{
2030
0
  int pending = 0;
2031
0
  struct radius_msg_list *msg;
2032
0
  char abuf[50];
2033
2034
0
  if (cli) {
2035
0
    for (msg = cli->msgs; msg; msg = msg->next) {
2036
0
      if (msg->msg_type == RADIUS_ACCT ||
2037
0
          msg->msg_type == RADIUS_ACCT_INTERIM)
2038
0
        pending++;
2039
0
    }
2040
0
  }
2041
2042
0
  return os_snprintf(buf, buflen,
2043
0
         "radiusAccServerIndex=%d\n"
2044
0
         "radiusAccServerAddress=%s\n"
2045
0
         "radiusAccClientServerPortNumber=%d\n"
2046
0
         "radiusAccClientRoundTripTime=%d\n"
2047
0
         "radiusAccClientRequests=%u\n"
2048
0
         "radiusAccClientRetransmissions=%u\n"
2049
0
         "radiusAccClientResponses=%u\n"
2050
0
         "radiusAccClientMalformedResponses=%u\n"
2051
0
         "radiusAccClientBadAuthenticators=%u\n"
2052
0
         "radiusAccClientPendingRequests=%u\n"
2053
0
         "radiusAccClientTimeouts=%u\n"
2054
0
         "radiusAccClientUnknownTypes=%u\n"
2055
0
         "radiusAccClientPacketsDropped=%u\n",
2056
0
         serv->index,
2057
0
         hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
2058
0
         serv->port,
2059
0
         serv->round_trip_time,
2060
0
         serv->requests,
2061
0
         serv->retransmissions,
2062
0
         serv->responses,
2063
0
         serv->malformed_responses,
2064
0
         serv->bad_authenticators,
2065
0
         pending,
2066
0
         serv->timeouts,
2067
0
         serv->unknown_types,
2068
0
         serv->packets_dropped);
2069
0
}
2070
2071
2072
/**
2073
 * radius_client_get_mib - Get RADIUS client MIB information
2074
 * @radius: RADIUS client context from radius_client_init()
2075
 * @buf: Buffer for returning MIB data in text format
2076
 * @buflen: Maximum buf length in octets
2077
 * Returns: Number of octets written into the buffer
2078
 */
2079
int radius_client_get_mib(struct radius_client_data *radius, char *buf,
2080
        size_t buflen)
2081
0
{
2082
0
  struct hostapd_radius_servers *conf;
2083
0
  int i;
2084
0
  struct hostapd_radius_server *serv;
2085
0
  int count = 0;
2086
2087
0
  if (!radius)
2088
0
    return 0;
2089
2090
0
  conf = radius->conf;
2091
2092
0
  if (conf->auth_servers) {
2093
0
    for (i = 0; i < conf->num_auth_servers; i++) {
2094
0
      serv = &conf->auth_servers[i];
2095
0
      count += radius_client_dump_auth_server(
2096
0
        buf + count, buflen - count, serv,
2097
0
        serv == conf->auth_server ?
2098
0
        radius : NULL);
2099
0
    }
2100
0
  }
2101
2102
0
  if (conf->acct_servers) {
2103
0
    for (i = 0; i < conf->num_acct_servers; i++) {
2104
0
      serv = &conf->acct_servers[i];
2105
0
      count += radius_client_dump_acct_server(
2106
0
        buf + count, buflen - count, serv,
2107
0
        serv == conf->acct_server ?
2108
0
        radius : NULL);
2109
0
    }
2110
0
  }
2111
2112
0
  return count;
2113
0
}
2114
2115
2116
void radius_client_reconfig(struct radius_client_data *radius,
2117
          struct hostapd_radius_servers *conf)
2118
0
{
2119
0
  if (radius)
2120
0
    radius->conf = conf;
2121
0
}