Coverage Report

Created: 2026-09-28 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/protocols/radius/base.c
Line
Count
Source
1
/*
2
 *   This library is free software; you can redistribute it and/or
3
 *   modify it under the terms of the GNU Lesser General Public
4
 *   License as published by the Free Software Foundation; either
5
 *   version 2.1 of the License, or (at your option) any later version.
6
 *
7
 *   This library is distributed in the hope that it will be useful,
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
 *   Lesser General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU Lesser General Public
13
 *   License along with this library; if not, write to the Free Software
14
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15
 */
16
17
/**
18
 * $Id: 67362bd5b8ce28d82d833f91f081c0f39b634983 $
19
 *
20
 * @file protocols/radius/base.c
21
 * @brief Functions to send/receive radius packets.
22
 *
23
 * @copyright 2000-2003,2006 The FreeRADIUS server project
24
 */
25
RCSID("$Id: 67362bd5b8ce28d82d833f91f081c0f39b634983 $")
26
27
#include <fcntl.h>
28
#include <ctype.h>
29
30
#include "attrs.h"
31
#include "radius.h"
32
33
#include <freeradius-devel/io/pair.h>
34
#include <freeradius-devel/util/md5.h>
35
#include <freeradius-devel/util/net.h>
36
#include <freeradius-devel/util/proto.h>
37
#include <freeradius-devel/util/udp.h>
38
#include <freeradius-devel/protocol/radius/freeradius.internal.h>
39
40
static uint32_t instance_count = 0;
41
static bool instantiated = false;
42
43
fr_dict_t const *dict_freeradius;
44
fr_dict_t const *dict_radius;
45
46
extern fr_dict_autoload_t libfreeradius_radius_dict[];
47
fr_dict_autoload_t libfreeradius_radius_dict[] = {
48
  { .out = &dict_freeradius, .proto = "freeradius" },
49
  { .out = &dict_radius, .proto = "radius" },
50
51
  DICT_AUTOLOAD_TERMINATOR
52
};
53
54
fr_dict_attr_t const *attr_packet_type;
55
fr_dict_attr_t const *attr_packet_authentication_vector;
56
fr_dict_attr_t const *attr_chap_challenge;
57
fr_dict_attr_t const *attr_chargeable_user_identity;
58
fr_dict_attr_t const *attr_eap_message;
59
fr_dict_attr_t const *attr_message_authenticator;
60
fr_dict_attr_t const *attr_state;
61
fr_dict_attr_t const *attr_vendor_specific;
62
fr_dict_attr_t const *attr_nas_filter_rule;
63
64
extern fr_dict_attr_autoload_t libfreeradius_radius_dict_attr[];
65
fr_dict_attr_autoload_t libfreeradius_radius_dict_attr[] = {
66
  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
67
  { .out = &attr_packet_authentication_vector, .name = "Packet-Authentication-Vector", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
68
  { .out = &attr_chap_challenge, .name = "CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
69
  { .out = &attr_chargeable_user_identity, .name = "Chargeable-User-Identity", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
70
71
  { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
72
  { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
73
  { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
74
  { .out = &attr_vendor_specific, .name = "Vendor-Specific", .type = FR_TYPE_VSA, .dict = &dict_radius },
75
  { .out = &attr_nas_filter_rule, .name = "NAS-Filter-Rule", .type = FR_TYPE_STRING, .dict = &dict_radius },
76
77
  DICT_AUTOLOAD_TERMINATOR
78
};
79
80
/*
81
 *  Some messages get printed out only in debugging mode.
82
 */
83
0
#define FR_DEBUG_STRERROR_PRINTF    if (fr_debug_lvl) fr_strerror_printf
84
0
#define FR_DEBUG_STRERROR_PRINTF_PUSH   if (fr_debug_lvl) fr_strerror_printf_push
85
86
fr_table_num_sorted_t const fr_radius_require_ma_table[] = {
87
  { L("auto"),    FR_RADIUS_REQUIRE_MA_AUTO   },
88
  { L("false"),   FR_RADIUS_REQUIRE_MA_NO     },
89
  { L("no"),    FR_RADIUS_REQUIRE_MA_NO     },
90
  { L("true"),    FR_RADIUS_REQUIRE_MA_YES    },
91
  { L("yes"),   FR_RADIUS_REQUIRE_MA_YES    },
92
};
93
size_t fr_radius_require_ma_table_len = NUM_ELEMENTS(fr_radius_require_ma_table);
94
95
fr_table_num_sorted_t const fr_radius_limit_proxy_state_table[] = {
96
  { L("auto"),    FR_RADIUS_LIMIT_PROXY_STATE_AUTO  },
97
  { L("false"),   FR_RADIUS_LIMIT_PROXY_STATE_NO    },
98
  { L("no"),    FR_RADIUS_LIMIT_PROXY_STATE_NO    },
99
  { L("true"),    FR_RADIUS_LIMIT_PROXY_STATE_YES   },
100
  { L("yes"),   FR_RADIUS_LIMIT_PROXY_STATE_YES   },
101
};
102
size_t fr_radius_limit_proxy_state_table_len = NUM_ELEMENTS(fr_radius_limit_proxy_state_table);
103
104
fr_table_num_sorted_t const fr_radius_request_name_table[] = {
105
  { L("acct"),    FR_RADIUS_CODE_ACCOUNTING_REQUEST },
106
  { L("auth"),    FR_RADIUS_CODE_ACCESS_REQUEST   },
107
  { L("auto"),    FR_RADIUS_CODE_UNDEFINED    },
108
  { L("challenge"), FR_RADIUS_CODE_ACCESS_CHALLENGE   },
109
  { L("coa"),   FR_RADIUS_CODE_COA_REQUEST    },
110
  { L("disconnect"),  FR_RADIUS_CODE_DISCONNECT_REQUEST },
111
  { L("status"),    FR_RADIUS_CODE_STATUS_SERVER    }
112
};
113
size_t fr_radius_request_name_table_len = NUM_ELEMENTS(fr_radius_request_name_table);
114
115
char const *fr_radius_packet_name[FR_RADIUS_CODE_MAX] = {
116
  "",         //!< 0
117
  "Access-Request",
118
  "Access-Accept",
119
  "Access-Reject",
120
  "Accounting-Request",
121
  "Accounting-Response",
122
  "Accounting-Status",
123
  "Password-Request",
124
  "Password-Accept",
125
  "Password-Reject",
126
  "Accounting-Message",     //!< 10
127
  "Access-Challenge",
128
  "Status-Server",
129
  "Status-Client",
130
  "14",
131
  "15",
132
  "16",
133
  "17",
134
  "18",
135
  "19",
136
  "20",         //!< 20
137
  "Resource-Free-Request",
138
  "Resource-Free-Response",
139
  "Resource-Query-Request",
140
  "Resource-Query-Response",
141
  "Alternate-Resource-Reclaim-Request",
142
  "NAS-Reboot-Request",
143
  "NAS-Reboot-Response",
144
  "28",
145
  "Next-Passcode",
146
  "New-Pin",        //!< 30
147
  "Terminate-Session",
148
  "Password-Expired",
149
  "Event-Request",
150
  "Event-Response",
151
  "35",
152
  "36",
153
  "37",
154
  "38",
155
  "39",
156
  "Disconnect-Request",     //!< 40
157
  "Disconnect-ACK",
158
  "Disconnect-NAK",
159
  "CoA-Request",
160
  "CoA-ACK",
161
  "CoA-NAK",
162
  "46",
163
  "47",
164
  "48",
165
  "49",
166
  "IP-Address-Allocate",      //!< 50
167
  "IP-Address-Release",
168
  "Protocol-Error",
169
};
170
171
172
/** If we get a reply, the request must come from one of a small
173
 * number of packet types.
174
 */
175
const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX] = {
176
  [FR_RADIUS_CODE_ACCESS_ACCEPT]    = FR_RADIUS_CODE_ACCESS_REQUEST,
177
  [FR_RADIUS_CODE_ACCESS_CHALLENGE] = FR_RADIUS_CODE_ACCESS_REQUEST,
178
  [FR_RADIUS_CODE_ACCESS_REJECT]    = FR_RADIUS_CODE_ACCESS_REQUEST,
179
180
  [FR_RADIUS_CODE_ACCOUNTING_RESPONSE]  = FR_RADIUS_CODE_ACCOUNTING_REQUEST,
181
182
  [FR_RADIUS_CODE_COA_ACK]    = FR_RADIUS_CODE_COA_REQUEST,
183
  [FR_RADIUS_CODE_COA_NAK]    = FR_RADIUS_CODE_COA_REQUEST,
184
185
  [FR_RADIUS_CODE_DISCONNECT_ACK]   = FR_RADIUS_CODE_DISCONNECT_REQUEST,
186
  [FR_RADIUS_CODE_DISCONNECT_NAK]   = FR_RADIUS_CODE_DISCONNECT_REQUEST,
187
188
  [FR_RADIUS_CODE_PROTOCOL_ERROR]   = FR_RADIUS_CODE_PROTOCOL_ERROR,  /* Any */
189
};
190
191
FR_DICT_ATTR_FLAG_FUNC(fr_radius_attr_flags_t, abinary)
192
FR_DICT_ATTR_FLAG_FUNC(fr_radius_attr_flags_t, concat)
193
194
static int dict_flag_encrypt(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)
195
440
{
196
440
  static fr_table_num_sorted_t const encrypted[] = {
197
440
    { L("Ascend-Secret"),  RADIUS_FLAG_ENCRYPT_ASCEND_SECRET },
198
440
    { L("Tunnel-Password"),  RADIUS_FLAG_ENCRYPT_TUNNEL_PASSWORD },
199
440
    { L("User-Password"),  RADIUS_FLAG_ENCRYPT_USER_PASSWORD}
200
440
  };
201
440
  static size_t encrypted_len = NUM_ELEMENTS(encrypted);
202
203
440
  fr_radius_attr_flags_encrypt_t encrypt;
204
440
  fr_radius_attr_flags_t *flags = fr_dict_attr_ext(*da_p, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
205
206
440
  encrypt = fr_table_value_by_str(encrypted, value, RADIUS_FLAG_ENCRYPT_INVALID);
207
440
  if (encrypt == RADIUS_FLAG_ENCRYPT_INVALID) {
208
0
    fr_strerror_printf("Unknown encryption type '%s'", value);
209
0
    return -1;
210
0
  }
211
212
440
  flags->encrypt = encrypt;
213
214
440
  return 0;
215
440
}
216
217
FR_DICT_ATTR_FLAG_FUNC(fr_radius_attr_flags_t, extended)
218
FR_DICT_ATTR_FLAG_FUNC(fr_radius_attr_flags_t, has_tag)
219
FR_DICT_ATTR_FLAG_FUNC(fr_radius_attr_flags_t, long_extended)
220
221
static fr_dict_flag_parser_t const radius_flags[] = {
222
  { L("abinary"),     { .func = dict_flag_abinary } },
223
  { L("concat"),      { .func = dict_flag_concat } },
224
  { L("encrypt"),     { .func = dict_flag_encrypt, .needs_value = true } },
225
  { L("extended"),    { .func = dict_flag_extended } },
226
  { L("has_tag"),     { .func = dict_flag_has_tag } },
227
  { L("long_extended"),   { .func = dict_flag_long_extended } }
228
};
229
230
int fr_radius_allow_reply(int code, bool allowed[static FR_RADIUS_CODE_MAX])
231
0
{
232
0
  int i;
233
234
0
  if ((code <= 0) || (code >= FR_RADIUS_CODE_MAX)) return -1;
235
236
0
  for (i = 1; i < FR_RADIUS_CODE_MAX; i++) {
237
0
    allowed[i] |= (allowed_replies[i] == (fr_radius_packet_code_t) code);
238
0
  }
239
240
0
  return 0;
241
0
}
242
243
/**  Do Ascend-Send / Recv-Secret calculation.
244
 *
245
 * The secret is hidden by xoring with a MD5 digest created from
246
 * the RADIUS shared secret and the authentication vector.
247
 * We put them into MD5 in the reverse order from that used when
248
 * encrypting passwords to RADIUS.
249
 */
250
ssize_t fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen,
251
        char const *secret, size_t secret_len, uint8_t const *vector)
252
149
{
253
149
  fr_md5_ctx_t    *md5_ctx;
254
149
  size_t      i;
255
149
  uint8_t     digest[MD5_DIGEST_LENGTH];
256
149
  fr_dbuff_t    work_dbuff = FR_DBUFF(dbuff);
257
258
149
  FR_DBUFF_EXTEND_LOWAT_OR_RETURN(&work_dbuff, sizeof(digest));
259
260
149
  md5_ctx = fr_md5_ctx_alloc_from_list();
261
149
  fr_md5_update(md5_ctx, vector, RADIUS_AUTH_VECTOR_LENGTH);
262
149
  fr_md5_update(md5_ctx, (uint8_t const *) secret, secret_len);
263
149
  fr_md5_final(digest, md5_ctx);
264
149
  fr_md5_ctx_free_from_list(&md5_ctx);
265
266
149
  if (inlen > sizeof(digest)) inlen = sizeof(digest);
267
1.36k
  for (i = 0; i < inlen; i++) digest[i] ^= in[i];
268
269
149
  fr_dbuff_in_memcpy(&work_dbuff, digest, sizeof(digest));
270
271
149
  return fr_dbuff_set(dbuff, &work_dbuff);
272
149
}
273
274
/** Basic validation of RADIUS packet header
275
 *
276
 * @note fr_strerror errors are only available if fr_debug_lvl > 0. This is to reduce CPU time
277
 *  consumed when discarding malformed packet.
278
 *
279
 * @param[in] sockfd we're reading from.
280
 * @param[out] src_ipaddr of the packet.
281
 * @param[out] src_port of the packet.
282
 * @param[out] code Pointer to where to write the packet code.
283
 * @return
284
 *  - -1 on failure.
285
 *  - 1 on decode error.
286
 *  - >= RADIUS_HEADER_LENGTH on success. This is the packet length as specified in the header.
287
 */
288
ssize_t fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code)
289
0
{
290
0
  ssize_t     data_len, packet_len;
291
0
  uint8_t     header[4];
292
293
0
  data_len = udp_recv_peek(sockfd, header, sizeof(header), UDP_FLAGS_PEEK, src_ipaddr, src_port);
294
0
  if (data_len < 0) {
295
0
    if ((errno == EAGAIN) || (errno == EINTR)) return 0;
296
0
    return -1;
297
0
  }
298
299
  /*
300
   *  Too little data is available, discard the packet.
301
   */
302
0
  if (data_len < 4) {
303
0
    char buffer[INET6_ADDRSTRLEN];
304
305
0
    FR_DEBUG_STRERROR_PRINTF("Expected at least 4 bytes of header data, got %zd bytes", data_len);
306
0
invalid:
307
0
    FR_DEBUG_STRERROR_PRINTF_PUSH("Invalid data from %s",
308
0
                inet_ntop(src_ipaddr->af, &src_ipaddr->addr, buffer, sizeof(buffer)));
309
0
    (void) udp_recv_discard(sockfd);
310
311
0
    return 0;
312
0
  }
313
314
  /*
315
   *  See how long the packet says it is.
316
   */
317
0
  packet_len = (header[2] * 256) + header[3];
318
319
  /*
320
   *  The length in the packet says it's less than
321
   *  a RADIUS header length: discard it.
322
   */
323
0
  if (packet_len < RADIUS_HEADER_LENGTH) {
324
0
    FR_DEBUG_STRERROR_PRINTF("Expected at least " STRINGIFY(RADIUS_HEADER_LENGTH)  " bytes of packet "
325
0
           "data, got %zd bytes", packet_len);
326
0
    goto invalid;
327
0
  }
328
329
  /*
330
   *  Enforce RFC requirements, for sanity.
331
   *  Anything after 4k will be discarded.
332
   */
333
0
  if (packet_len > MAX_PACKET_LEN) {
334
0
    FR_DEBUG_STRERROR_PRINTF("Length field value too large, expected maximum of "
335
0
           STRINGIFY(MAX_PACKET_LEN) " bytes, got %zd bytes", packet_len);
336
0
    goto invalid;
337
0
  }
338
339
0
  *code = header[0];
340
341
  /*
342
   *  The packet says it's this long, but the actual UDP
343
   *  size could still be smaller.
344
   */
345
0
  return packet_len;
346
0
}
347
348
/** Sign a previously encoded packet
349
 *
350
 * Calculates the request/response authenticator for packets which need it, and fills
351
 * in the message-authenticator value if the attribute is present in the encoded packet.
352
 *
353
 * @param[in,out] packet  (request or response).
354
 * @param[in] vector    original packet vector to use
355
 * @param[in] secret    to sign the packet with.
356
 * @param[in] secret_len  The length of the secret.
357
 * @return
358
 *  - <0 on error
359
 *  - 0 on success
360
 */
361
int fr_radius_sign(uint8_t *packet, uint8_t const *vector,
362
       uint8_t const *secret, size_t secret_len)
363
0
{
364
0
  uint8_t   *msg, *end;
365
0
  size_t    packet_len = fr_nbo_to_uint16(packet + 2);
366
367
  /*
368
   *  No real limit on secret length, this is just
369
   *  to catch uninitialised fields.
370
   */
371
0
  if (!fr_cond_assert(secret_len <= UINT16_MAX)) {
372
0
    fr_strerror_printf("Secret is too long.  Expected <= %u, got %zu",
373
0
           (unsigned int) UINT16_MAX, secret_len);
374
0
    return -1;
375
0
  }
376
377
0
  if (packet_len < RADIUS_HEADER_LENGTH) {
378
0
    fr_strerror_const("Packet must be encoded before calling fr_radius_sign()");
379
0
    return -1;
380
0
  }
381
382
  /*
383
   *  Find Message-Authenticator.  Its value has to be
384
   *  calculated before we calculate the Request
385
   *  Authenticator or the Response Authenticator.
386
   */
387
0
  msg = packet + RADIUS_HEADER_LENGTH;
388
0
  end = packet + packet_len;
389
390
0
  while (msg < end) {
391
0
    if ((end - msg) < 2) goto invalid_attribute;
392
393
0
    if (msg[0] != FR_MESSAGE_AUTHENTICATOR) {
394
0
      if (msg[1] < 2) goto invalid_attribute;
395
396
0
      if ((msg + msg[1]) > end) {
397
0
      invalid_attribute:
398
0
        fr_strerror_printf("Invalid attribute at offset %zd", msg - packet);
399
0
        return -1;
400
0
      }
401
0
      msg += msg[1];
402
0
      continue;
403
0
    }
404
405
0
    if (msg[1] < 18) {
406
0
      fr_strerror_const("Message-Authenticator is too small");
407
0
      return -1;
408
0
    }
409
410
0
    switch (packet[0]) {
411
0
    case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
412
0
    case FR_RADIUS_CODE_DISCONNECT_REQUEST:
413
0
    case FR_RADIUS_CODE_COA_REQUEST:
414
0
      memset(packet + 4, 0, RADIUS_AUTH_VECTOR_LENGTH);
415
0
      break;
416
417
0
    case FR_RADIUS_CODE_ACCESS_ACCEPT:
418
0
    case FR_RADIUS_CODE_ACCESS_REJECT:
419
0
    case FR_RADIUS_CODE_ACCESS_CHALLENGE:
420
0
    case FR_RADIUS_CODE_ACCOUNTING_RESPONSE:
421
0
    case FR_RADIUS_CODE_DISCONNECT_ACK:
422
0
    case FR_RADIUS_CODE_DISCONNECT_NAK:
423
0
    case FR_RADIUS_CODE_COA_ACK:
424
0
    case FR_RADIUS_CODE_COA_NAK:
425
0
    case FR_RADIUS_CODE_PROTOCOL_ERROR:
426
0
      if (!vector) goto need_original;
427
0
      memcpy(packet + 4, vector, RADIUS_AUTH_VECTOR_LENGTH);
428
0
      break;
429
430
0
    case FR_RADIUS_CODE_ACCESS_REQUEST:
431
0
    case FR_RADIUS_CODE_STATUS_SERVER:
432
      /* packet + 4 MUST be the Request Authenticator filled with random data */
433
0
      break;
434
435
0
    default:
436
0
      goto bad_packet;
437
0
    }
438
439
    /*
440
     *  Force Message-Authenticator to be zero,
441
     *  calculate the HMAC, and put it into the
442
     *  Message-Authenticator attribute.
443
     */
444
0
    memset(msg + 2, 0, RADIUS_AUTH_VECTOR_LENGTH);
445
0
    fr_hmac_md5(msg + 2, packet, packet_len, secret, secret_len);
446
0
    break;
447
0
  }
448
449
  /*
450
   *  Initialize the request authenticator.
451
   */
452
0
  switch (packet[0]) {
453
0
  case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
454
0
  case FR_RADIUS_CODE_DISCONNECT_REQUEST:
455
0
  case FR_RADIUS_CODE_COA_REQUEST:
456
0
    memset(packet + 4, 0, RADIUS_AUTH_VECTOR_LENGTH);
457
0
    break;
458
459
0
  case FR_RADIUS_CODE_ACCESS_ACCEPT:
460
0
  case FR_RADIUS_CODE_ACCESS_REJECT:
461
0
  case FR_RADIUS_CODE_ACCESS_CHALLENGE:
462
0
  case FR_RADIUS_CODE_ACCOUNTING_RESPONSE:
463
0
  case FR_RADIUS_CODE_DISCONNECT_ACK:
464
0
  case FR_RADIUS_CODE_DISCONNECT_NAK:
465
0
  case FR_RADIUS_CODE_COA_ACK:
466
0
  case FR_RADIUS_CODE_COA_NAK:
467
0
  case FR_RADIUS_CODE_PROTOCOL_ERROR:
468
0
    if (!vector) {
469
0
    need_original:
470
0
      fr_strerror_const("Cannot sign response packet without a request packet");
471
0
      return -1;
472
0
    }
473
0
    memcpy(packet + 4, vector, RADIUS_AUTH_VECTOR_LENGTH);
474
0
    break;
475
476
    /*
477
     *  The Request Authenticator is random numbers.
478
     *  We don't need to sign anything else, so
479
     *  return.
480
     */
481
0
  case FR_RADIUS_CODE_ACCESS_REQUEST:
482
0
  case FR_RADIUS_CODE_STATUS_SERVER:
483
0
    return 0;
484
485
0
  default:
486
0
  bad_packet:
487
0
    fr_strerror_printf("Cannot sign unknown packet code %u", packet[0]);
488
0
    return -1;
489
0
  }
490
491
  /*
492
   *  Request / Response Authenticator = MD5(packet + secret)
493
   */
494
0
  {
495
0
    fr_md5_ctx_t  *md5_ctx;
496
497
0
    md5_ctx = fr_md5_ctx_alloc_from_list();
498
0
    fr_md5_update(md5_ctx, packet, packet_len);
499
0
    fr_md5_update(md5_ctx, secret, secret_len);
500
0
    fr_md5_final(packet + 4, md5_ctx);
501
0
    fr_md5_ctx_free_from_list(&md5_ctx);
502
0
  }
503
504
0
  return 0;
505
0
}
506
507
char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1] = {
508
  [FR_RADIUS_FAIL_NONE] = "none",
509
  [FR_RADIUS_FAIL_MIN_LENGTH_PACKET] = "packet is smaller than the minimum packet length",
510
  [FR_RADIUS_FAIL_MAX_LENGTH_PACKET] = "packet is larger than the maximum packet length",
511
  [FR_RADIUS_FAIL_MIN_LENGTH_FIELD] = "header 'length' field has a value smaller than the minimum packet length",
512
  [FR_RADIUS_FAIL_MIN_LENGTH_MISMATCH] = "header 'length' field has a value larger than the received data",
513
  [FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE] = "unknown packet code",
514
  [FR_RADIUS_FAIL_UNEXPECTED_REQUEST_CODE] = "unexpected request code",
515
  [FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE] = "unexpected response code",
516
  [FR_RADIUS_FAIL_TOO_MANY_ATTRIBUTES] = "packet contains too many attributes",
517
518
  [FR_RADIUS_FAIL_INVALID_ATTRIBUTE] = "attribute number 0 is invalid",
519
520
  [FR_RADIUS_FAIL_HEADER_OVERFLOW] = "attribute header overflows the packet",
521
  [FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT] = "attribute 'length' field contains invalid value",
522
  [FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW] = "attribute 'length' field overflows the packet",
523
  [FR_RADIUS_FAIL_ATTRIBUTE_DECODE] = "unable to decode attributes",
524
525
  [FR_RADIUS_FAIL_MA_INVALID_LENGTH] = "Message-Authenticator has invalid length",
526
  [FR_RADIUS_FAIL_MA_MISSING] = "Message-Authenticator is required for this packet, but it is missing",
527
  [FR_RADIUS_FAIL_MA_INVALID] = "Message-Authenticator fails verification. shared secret is incorrect",
528
  [FR_RADIUS_FAIL_MA_TOO_MANY] = "More than one Message-Authenticator in a packet is invalid",
529
  [FR_RADIUS_FAIL_PROXY_STATE_MISSING_MA] = "The packet contains Proxy-State, but no Message-Authenticator",
530
531
  [FR_RADIUS_FAIL_VERIFY] = "packet fails verification, shared secret is incorrect",
532
  [FR_RADIUS_FAIL_NO_MATCHING_REQUEST] = "did not find request which matched response",
533
  [FR_RADIUS_FAIL_IO_ERROR] = "IO error",
534
  [FR_RADIUS_FAIL_MAX] = "???",
535
};
536
537
/** See if the data pointed to by PTR is a valid RADIUS packet.
538
 *
539
 * @param[in] packet    to check.
540
 * @param[in,out] packet_len_p  The size of the packet data.
541
 * @param[in] max_attributes  to allow in the packet.
542
 * @param[in] require_message_authenticator whether we require Message-Authenticator.
543
 * @param[in] reason    if not NULL, will have the failure reason written to where it points.
544
 * @return
545
 *  - True on success.
546
 *  - False on failure.
547
 */
548
bool fr_radius_ok(uint8_t const *packet, size_t *packet_len_p,
549
      uint32_t max_attributes, bool require_message_authenticator, fr_radius_decode_fail_t *reason)
550
4.88k
{
551
4.88k
  uint8_t const   *attr, *end;
552
4.88k
  size_t      totallen;
553
4.88k
  bool      seen_ma = false;
554
4.88k
  uint32_t    num_attributes;
555
4.88k
  fr_radius_decode_fail_t failure = FR_RADIUS_FAIL_NONE;
556
4.88k
  size_t      packet_len = *packet_len_p;
557
558
  /*
559
   *  Check for packets smaller than the packet header.
560
   *
561
   *  RFC 2865, Section 3., subsection 'length' says:
562
   *
563
   *  "The minimum length is 20 ..."
564
   */
565
4.88k
  if (packet_len < RADIUS_HEADER_LENGTH) {
566
9
    failure = FR_RADIUS_FAIL_MIN_LENGTH_PACKET;
567
9
    goto finish;
568
9
  }
569
570
571
  /*
572
   *  Check for packets with mismatched size.
573
   *  i.e. We've received 128 bytes, and the packet header
574
   *  says it's 256 bytes long.
575
   */
576
4.87k
  totallen = fr_nbo_to_uint16(packet + 2);
577
578
  /*
579
   *  Code of 0 is not understood.
580
   *  Code of 16 or greater is not understood.
581
   */
582
4.87k
  if ((packet[0] == 0) ||
583
4.87k
      (packet[0] >= FR_RADIUS_CODE_MAX)) {
584
10
    failure = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE;
585
10
    goto finish;
586
10
  }
587
588
4.86k
  switch (packet[0]) {
589
    /*
590
     *  Message-Authenticator is required in Status-Server
591
     *  packets, otherwise they can be trivially forged.
592
     */
593
6
  case FR_RADIUS_CODE_STATUS_SERVER:
594
6
    require_message_authenticator = true;
595
6
    break;
596
597
    /*
598
     *  Message-Authenticator may or may not be
599
     *  required for Access-* packets.
600
     */
601
556
  case FR_RADIUS_CODE_ACCESS_REQUEST:
602
969
  case FR_RADIUS_CODE_ACCESS_ACCEPT:
603
1.34k
  case FR_RADIUS_CODE_ACCESS_CHALLENGE:
604
1.52k
  case FR_RADIUS_CODE_ACCESS_REJECT:
605
1.62k
  case FR_RADIUS_CODE_PROTOCOL_ERROR:
606
1.62k
    break;
607
608
    /*
609
     *  Message-Authenticator is not required for all other packets, but is required if the
610
     *  caller asks for it.
611
     */
612
334
  case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
613
655
  case FR_RADIUS_CODE_ACCOUNTING_RESPONSE:
614
615
1.28k
  case FR_RADIUS_CODE_COA_REQUEST:
616
1.71k
  case FR_RADIUS_CODE_COA_ACK:
617
2.45k
  case FR_RADIUS_CODE_COA_NAK:
618
619
2.65k
  case FR_RADIUS_CODE_DISCONNECT_REQUEST:
620
2.89k
  case FR_RADIUS_CODE_DISCONNECT_ACK:
621
3.22k
  case FR_RADIUS_CODE_DISCONNECT_NAK:
622
3.22k
    break;
623
624
    /*
625
     *  All other packet codes are not handled by the encoder, so we reject them.
626
     */
627
12
  default:
628
12
    failure = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE;
629
12
    goto finish;
630
4.86k
  }
631
632
  /*
633
   *  Repeat the length checks.  This time, instead of
634
   *  looking at the data we received, look at the value
635
   *  of the 'length' field inside of the packet.
636
   *
637
   *  Check for packets smaller than the packet header.
638
   *
639
   *  RFC 2865, Section 3., subsection 'length' says:
640
   *
641
   *  "The minimum length is 20 ..."
642
   */
643
4.85k
  if (totallen < RADIUS_HEADER_LENGTH) {
644
5
    failure = FR_RADIUS_FAIL_MIN_LENGTH_FIELD;
645
5
    goto finish;
646
5
  }
647
648
  /*
649
   *  And again, for the value of the 'length' field.
650
   *
651
   *  RFC 2865, Section 3., subsection 'length' says:
652
   *
653
   *  " ... and maximum length is 4096."
654
   *
655
   *  HOWEVER.  This requirement is for the network layer.
656
   *  If the code gets here, we assume that a well-formed
657
   *  packet is an OK packet.
658
   *
659
   *  We allow both the UDP data length, and the RADIUS
660
   *  "length" field to contain up to 64K of data.
661
   */
662
663
  /*
664
   *  RFC 2865, Section 3., subsection 'length' says:
665
   *
666
   *  "If the packet is shorter than the Length field
667
   *  indicates, it MUST be silently discarded."
668
   *
669
   *  i.e. No response to the NAS.
670
   */
671
4.84k
  if (totallen > packet_len) {
672
21
    failure = FR_RADIUS_FAIL_MIN_LENGTH_MISMATCH;
673
21
    goto finish;
674
21
  }
675
676
  /*
677
   *  RFC 2865, Section 3., subsection 'length' says:
678
   *
679
   *  "Octets outside the range of the Length field MUST be
680
   *  treated as padding and ignored on reception."
681
   */
682
4.82k
  if (totallen < packet_len) {
683
162
    *packet_len_p = packet_len = totallen;
684
162
  }
685
686
  /*
687
   *  Walk through the packet's attributes, ensuring that
688
   *  they add up EXACTLY to the size of the packet.
689
   *
690
   *  If they don't, then the attributes either under-fill
691
   *  or over-fill the packet.  Any parsing of the packet
692
   *  is impossible, and will result in unknown side effects.
693
   *
694
   *  This would ONLY happen with buggy RADIUS implementations,
695
   *  or with an intentional attack.  Either way, we do NOT want
696
   *  to be vulnerable to this problem.
697
   */
698
4.82k
  attr = packet + RADIUS_HEADER_LENGTH;
699
4.82k
  end = packet + packet_len;
700
4.82k
  num_attributes = 0;
701
702
67.0k
  while (attr < end) {
703
    /*
704
     *  We need at least 2 bytes to check the
705
     *  attribute header.
706
     */
707
62.2k
    if ((end - attr) < 2) {
708
3
      failure = FR_RADIUS_FAIL_HEADER_OVERFLOW;
709
3
      goto finish;
710
3
    }
711
712
    /*
713
     *  Attribute number zero is NOT defined.
714
     */
715
62.2k
    if (attr[0] == 0) {
716
11
      failure = FR_RADIUS_FAIL_INVALID_ATTRIBUTE;
717
11
      goto finish;
718
11
    }
719
720
    /*
721
     *  Attributes are at LEAST as long as the ID & length
722
     *  fields.  Anything shorter is an invalid attribute.
723
     */
724
62.2k
    if (attr[1] < 2) {
725
8
      failure = FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT;
726
8
      goto finish;
727
8
    }
728
729
    /*
730
     *  If there are fewer bytes in the packet than in the
731
     *  attribute, it's a bad packet.
732
     */
733
62.2k
    if ((attr + attr[1]) > end) {
734
10
      failure = FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW;
735
10
      goto finish;
736
10
    }
737
738
    /*
739
     *  Sanity check the attributes for length.
740
     */
741
62.1k
    switch (attr[0]) {
742
61.8k
    default:  /* don't do anything by default */
743
61.8k
      break;
744
745
      /*
746
       *  If there's an EAP-Message, we require
747
       *  a Message-Authenticator.
748
       */
749
61.8k
    case FR_EAP_MESSAGE:
750
293
      require_message_authenticator = true;
751
293
      break;
752
753
15
    case FR_MESSAGE_AUTHENTICATOR:
754
15
      if (attr[1] != 2 + RADIUS_AUTH_VECTOR_LENGTH) {
755
12
        failure = FR_RADIUS_FAIL_MA_INVALID_LENGTH;
756
12
        goto finish;
757
12
      }
758
759
      /*
760
       *  Can't have two of them.
761
       */
762
3
      if (seen_ma) {
763
1
        failure = FR_RADIUS_FAIL_MA_TOO_MANY;
764
1
        goto finish;
765
1
      }
766
767
2
      seen_ma = true;
768
2
      break;
769
62.1k
    }
770
771
62.1k
    attr += attr[1];
772
62.1k
    num_attributes++; /* seen one more attribute */
773
774
    /*
775
     *  If we're configured to look for a maximum number of
776
     *  attributes, and we've seen more than that maximum,
777
     *  then throw the packet away, as a possible DoS.
778
     */
779
62.1k
    if (num_attributes > max_attributes) {
780
1
      failure = FR_RADIUS_FAIL_TOO_MANY_ATTRIBUTES;
781
1
      goto finish;
782
1
    }
783
62.1k
  }
784
785
  /*
786
   *  http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
787
   *
788
   *  A packet with an EAP-Message attribute MUST also have
789
   *  a Message-Authenticator attribute.
790
   *
791
   *  A Message-Authenticator all by itself is OK, though.
792
   *
793
   *  Similarly, Status-Server packets MUST contain
794
   *  Message-Authenticator attributes.
795
   */
796
4.78k
  if (require_message_authenticator && !seen_ma) {
797
9
    failure = FR_RADIUS_FAIL_MA_MISSING;
798
9
    goto finish;
799
9
  }
800
801
4.88k
finish:
802
803
4.88k
  if (reason) *reason = failure;
804
805
4.88k
  return (failure == FR_RADIUS_FAIL_NONE);
806
4.78k
}
807
808
809
/** Verify the signature of a request / response packet
810
 *
811
 *  This function does its work by calling fr_radius_sign(), and then comparing the signature in the packet
812
 *  with the one we calculated.  If they differ, there's a problem.
813
 *
814
 *  @note - We rely on the security of the shared secret for UDP and TCP transport.  For TLS transport, we
815
 *  rely on TLS to make the RADIUS packets both secure and private.
816
 *
817
 *  @note - The BlastRADIUS mitigations require that "require_message_authenticator" and "limit_proxy_state"
818
 *  are used only for Access-Request packets.  These mitigations MUST NOT be used for any any other packet
819
 *  codes.
820
 *
821
 *  The caller should have called fr_radius_packet_ok() to see if the packet is well-formed, at least for the
822
 *  base RFC attributes.
823
 *
824
 * @param[in] packet        the raw RADIUS packet (request or response)
825
 * @param[in] vector        the original packet vector
826
 * @param[in] secret        the shared secret
827
 * @param[in] secret_len      the length of the secret
828
 * @param[in] require_message_authenticator whether we require Message-Authenticator.
829
 * @param[in] limit_proxy_state     whether we allow Proxy-State without Message-Authenticator.
830
 * @return
831
 *  < <0 on error (negative fr_radius_decode_fail_t)
832
 *  - 0 on success.
833
 */
834
int fr_radius_verify(uint8_t *packet, uint8_t const *vector,
835
         uint8_t const *secret, size_t secret_len,
836
         bool require_message_authenticator, bool limit_proxy_state)
837
0
{
838
0
  bool    found_message_authenticator = false;
839
0
  bool    found_proxy_state = false;
840
0
  int   rcode;
841
0
  int   code;
842
0
  uint8_t   *attr, *msg, *end;
843
0
  size_t    packet_len = fr_nbo_to_uint16(packet + 2);
844
0
  uint8_t   request_authenticator[RADIUS_AUTH_VECTOR_LENGTH];
845
0
  uint8_t   message_authenticator[RADIUS_AUTH_VECTOR_LENGTH];
846
847
0
  if (packet_len < RADIUS_HEADER_LENGTH) {
848
0
    fr_strerror_printf("invalid packet length %zu", packet_len);
849
0
    return -FR_RADIUS_FAIL_MIN_LENGTH_PACKET;
850
0
  }
851
852
0
  code = packet[0];
853
0
  if (!code || (code >= FR_RADIUS_CODE_MAX)) {
854
0
    fr_strerror_printf("Unknown reply code %d", code);
855
0
    return -FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE;
856
0
  }
857
858
  /*
859
   *  RFC 5997 says that all Status-Server packets MUST contain Message-Authenticator.
860
   */
861
0
  require_message_authenticator |= (code == FR_RADIUS_CODE_STATUS_SERVER);
862
863
0
  memcpy(request_authenticator, packet + 4, sizeof(request_authenticator));
864
865
  /*
866
   *  Find Message-Authenticator.  Its value has to be
867
   *  calculated before we calculate the Request
868
   *  Authenticator or the Response Authenticator.
869
   */
870
0
  msg = NULL;
871
0
  attr = packet + RADIUS_HEADER_LENGTH;
872
0
  end = packet + packet_len;
873
874
  /*
875
   *  See what we need to do in order to verify the packet.
876
   *
877
   *  Note that fr_radius_packet_ok() also does these checks, but it's worth re-doing them here so
878
   *  that potential API mis-use is safe.  i.e. we do "defense in depth".
879
   */
880
0
  while (attr < end) {
881
0
    if ((end - attr) < 2) goto invalid_attribute;
882
883
0
    if (attr[1] < 2) goto invalid_attribute;
884
885
0
    if ((attr + attr[1]) > end) {
886
0
    invalid_attribute:
887
0
      fr_strerror_printf("invalid attribute at offset %zd", attr - packet);
888
0
      return -FR_RADIUS_FAIL_INVALID_ATTRIBUTE;
889
0
    }
890
891
    /*
892
     *  If there's no Message-Authenticator, then we need to check Proxy-State, but only if
893
     *  the caller asked us to limit Proxy-State.
894
     */
895
0
    if (attr[0] == FR_PROXY_STATE) {
896
0
      found_proxy_state = limit_proxy_state;
897
0
      goto next;
898
0
    }
899
900
    /*
901
     *  Check the contents of Message-Authenticator
902
     */
903
0
    if (attr[0] == FR_MESSAGE_AUTHENTICATOR) {
904
0
      if (found_message_authenticator) {
905
0
        fr_strerror_const("Multiple Message-Authenticators are invalid");
906
0
        return -FR_RADIUS_FAIL_MA_TOO_MANY;
907
0
      }
908
909
910
0
      if (attr[1] != 18) {
911
0
        fr_strerror_const("too small Message-Authenticator");
912
0
        return -FR_RADIUS_FAIL_MA_INVALID_LENGTH;
913
0
      }
914
915
      /*
916
       *  If we have found Message-Authenticator, then we verify that.  We also can stop
917
       *  processing the packet, as we don't care about the contents of Proxy-State.
918
       */
919
0
      memcpy(message_authenticator, attr + 2, sizeof(message_authenticator));
920
0
      found_message_authenticator = true;
921
0
      msg = attr;
922
0
      goto next;
923
0
    }
924
925
    /*
926
     *  RFC 3579 Section 3.1 requires Message-Authenticator if the packet contains
927
     *  EAP-Message.
928
     */
929
0
    if (attr[0] == FR_EAP_MESSAGE) require_message_authenticator = true;
930
931
0
  next:
932
0
    attr += attr[1];
933
0
  }
934
935
  /*
936
   *  Enforce limit_proxy_state for Access-Request packets.
937
   */
938
0
  if (code == FR_RADIUS_CODE_ACCESS_REQUEST) {
939
0
    if (limit_proxy_state && found_proxy_state && !found_message_authenticator) {
940
0
      fr_strerror_const("Proxy-State is not allowed without Message-Authenticator");
941
0
      return -FR_RADIUS_FAIL_PROXY_STATE_MISSING_MA;
942
0
    }
943
0
  }
944
945
  /*
946
   *  The require_message_authenticator flag can be set for any of these packet types.  For other
947
   *  packet types, we check it if it exists, but we allow packets to not contain it.
948
   */
949
0
  if (require_message_authenticator && !found_message_authenticator) {
950
0
    fr_strerror_printf("%s is missing the required Message-Authenticator attribute",
951
0
           fr_radius_packet_name[code]);
952
0
    return -FR_RADIUS_FAIL_MA_MISSING;
953
0
  }
954
955
  /*
956
   *  Overwrite the contents of Message-Authenticator
957
   *  with the one we calculate.
958
   */
959
0
  rcode = fr_radius_sign(packet, vector, secret, secret_len);
960
0
  if (rcode < 0) {
961
0
    fr_strerror_const_push("Failed calculating correct authenticator");
962
0
    return -FR_RADIUS_FAIL_VERIFY;
963
0
  }
964
965
  /*
966
   *  Check the Message-Authenticator first.
967
   *
968
   *  If it's invalid, restore the original
969
   *  Message-Authenticator and Request Authenticator
970
   *  fields.
971
   *
972
   *  If it's valid the original and calculated
973
   *  message authenticators are the same, so we don't
974
   *  need to do anything.
975
   */
976
0
  if (msg &&
977
0
      (fr_digest_cmp(message_authenticator, msg + 2, sizeof(message_authenticator)) != 0)) {
978
0
    memcpy(msg + 2, message_authenticator, sizeof(message_authenticator));
979
0
    memcpy(packet + 4, request_authenticator, sizeof(request_authenticator));
980
981
0
    fr_strerror_const("invalid Message-Authenticator (shared secret is incorrect)");
982
0
    return -FR_RADIUS_FAIL_MA_INVALID;
983
0
  }
984
985
  /*
986
   *  These are random numbers, so there's no point in
987
   *  comparing them.
988
   */
989
0
  if ((code == FR_RADIUS_CODE_ACCESS_REQUEST) || (code == FR_RADIUS_CODE_STATUS_SERVER)) {
990
0
    return 0;
991
0
  }
992
993
  /*
994
   *  Check the Request Authenticator.
995
   */
996
0
  if (fr_digest_cmp(request_authenticator, packet + 4, sizeof(request_authenticator)) != 0) {
997
0
    memcpy(packet + 4, request_authenticator, sizeof(request_authenticator));
998
0
    if (vector) {
999
0
      fr_strerror_const("invalid Response Authenticator (shared secret is incorrect)");
1000
0
    } else {
1001
0
      fr_strerror_const("invalid Request Authenticator (shared secret is incorrect)");
1002
0
    }
1003
0
    return -FR_RADIUS_FAIL_VERIFY;
1004
0
  }
1005
1006
0
  return 0;
1007
0
}
1008
1009
void *fr_radius_next_encodable(fr_dcursor_t *cursor, void *current, void *uctx);
1010
1011
void *fr_radius_next_encodable(fr_dcursor_t *cursor, void *current, void *uctx)
1012
0
{
1013
0
  fr_pair_t *c = current;
1014
0
  fr_dict_t *dict = talloc_get_type_abort(uctx, fr_dict_t);
1015
1016
0
  while ((c = fr_dcursor_list_next(cursor, c))) {
1017
0
    PAIR_VERIFY(c);
1018
0
    if ((c->da->dict == dict) &&
1019
0
        (!c->da->flags.internal || ((c->da->attr > FR_TAG_BASE) && (c->da->attr < (FR_TAG_BASE + 0x20))))) {
1020
0
      break;
1021
0
    }
1022
0
  }
1023
1024
0
  return c;
1025
0
}
1026
1027
1028
ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx)
1029
0
{
1030
0
  ssize_t     slen;
1031
0
  fr_pair_t const   *vp;
1032
0
  fr_dcursor_t    cursor;
1033
0
  fr_dbuff_t    work_dbuff, length_dbuff;
1034
1035
  /*
1036
   *  The RADIUS header can't do more than 64K of data.
1037
   */
1038
0
  work_dbuff = FR_DBUFF_MAX(dbuff, 65535);
1039
1040
0
  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, packet_ctx->code, packet_ctx->id);
1041
0
  length_dbuff = FR_DBUFF(&work_dbuff);
1042
0
  FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) RADIUS_HEADER_LENGTH);
1043
1044
0
  switch (packet_ctx->code) {
1045
0
  case FR_RADIUS_CODE_ACCESS_REQUEST:
1046
0
  case FR_RADIUS_CODE_STATUS_SERVER:
1047
0
    packet_ctx->request_authenticator = fr_dbuff_current(&work_dbuff);
1048
1049
    /*
1050
     *  Allow over-rides of the authentication vector for testing.
1051
     */
1052
0
    vp = fr_pair_find_by_da(vps, NULL, attr_packet_authentication_vector);
1053
0
    if (vp && (vp->vp_length >= RADIUS_AUTH_VECTOR_LENGTH)) {
1054
0
      FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, vp->vp_octets, RADIUS_AUTH_VECTOR_LENGTH);
1055
0
    } else {
1056
0
      int i;
1057
1058
0
      for (i = 0; i < 4; i++) {
1059
0
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t) fr_rand());
1060
0
      }
1061
0
    }
1062
0
    break;
1063
1064
0
  case FR_RADIUS_CODE_ACCESS_ACCEPT:
1065
0
  case FR_RADIUS_CODE_ACCESS_REJECT:
1066
0
  case FR_RADIUS_CODE_ACCESS_CHALLENGE:
1067
0
  case FR_RADIUS_CODE_ACCOUNTING_RESPONSE:
1068
0
  case FR_RADIUS_CODE_DISCONNECT_ACK:
1069
0
  case FR_RADIUS_CODE_DISCONNECT_NAK:
1070
0
  case FR_RADIUS_CODE_COA_ACK:
1071
0
  case FR_RADIUS_CODE_COA_NAK:
1072
0
  case FR_RADIUS_CODE_PROTOCOL_ERROR:
1073
0
    if (!packet_ctx->request_authenticator) {
1074
0
      fr_strerror_const("Cannot encode response without request");
1075
0
      return -1;
1076
0
    }
1077
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, packet_ctx->request_authenticator, RADIUS_AUTH_VECTOR_LENGTH);
1078
0
    break;
1079
1080
0
  case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
1081
0
  case FR_RADIUS_CODE_DISCONNECT_REQUEST:
1082
    /*
1083
     *  Tunnel-Password encoded attributes are allowed
1084
     *  in CoA-Request packets, by RFC 5176 Section
1085
     *  3.6.  HOWEVER, the tunnel passwords are
1086
     *  "encrypted" using the Request Authenticator,
1087
     *  which is all zeros!  That makes them much
1088
     *  easier to decrypt.  The only solution here is
1089
     *  to say "don't do that!"
1090
     */
1091
0
  case FR_RADIUS_CODE_COA_REQUEST:
1092
0
    packet_ctx->request_authenticator = fr_dbuff_current(&work_dbuff);
1093
1094
0
    FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, RADIUS_AUTH_VECTOR_LENGTH);
1095
0
    break;
1096
1097
0
  default:
1098
0
    fr_strerror_printf("Cannot encode unknown packet code %d", packet_ctx->code);
1099
0
    return -1;
1100
0
  }
1101
1102
  /*
1103
   *  Always add Message-Authenticator after the packet
1104
   *  header for insecure transport protocols.
1105
   */
1106
0
  if (!packet_ctx->common->secure_transport) switch (packet_ctx->code) {
1107
0
  case FR_RADIUS_CODE_ACCESS_ACCEPT:
1108
0
  case FR_RADIUS_CODE_ACCESS_REJECT:
1109
0
  case FR_RADIUS_CODE_ACCESS_CHALLENGE:
1110
#ifdef NAS_VIOLATES_RFC
1111
    /*
1112
     *  Allow ridiculous behavior for vendors who violate the RFCs.
1113
     *
1114
     *  But only if there's no EAP-Message in the packet.
1115
     */
1116
    if (packet_ctx->allow_vulnerable_clients && !fr_pair_find_by_da(vps, NULL, attr_eap_message)) {
1117
      break;
1118
    }
1119
    FALL_THROUGH;
1120
#endif
1121
1122
0
  case FR_RADIUS_CODE_ACCESS_REQUEST:
1123
0
  case FR_RADIUS_CODE_STATUS_SERVER:
1124
0
  case FR_RADIUS_CODE_PROTOCOL_ERROR:
1125
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_MESSAGE_AUTHENTICATOR, 0x12,
1126
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
1128
0
    packet_ctx->seen_message_authenticator = true;
1129
0
    break;
1130
1131
0
  default:
1132
0
    break;
1133
0
  }
1134
1135
  /*
1136
   *  If we're sending Protocol-Error, add in
1137
   *  Original-Packet-Code manually.  If the user adds it
1138
   *  later themselves, well, too bad.
1139
   */
1140
0
  if (packet_ctx->code == FR_RADIUS_CODE_PROTOCOL_ERROR) {
1141
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_EXTENDED_ATTRIBUTE_1, 0x07, 0x04 /* Original-Packet-Code */,
1142
0
           0x00, 0x00, 0x00, packet_ctx->request_code);
1143
0
  }
1144
1145
  /*
1146
   *  Loop over the reply attributes for the packet.
1147
   */
1148
0
  fr_pair_dcursor_iter_init(&cursor, vps, fr_radius_next_encodable, dict_radius);
1149
0
  while ((vp = fr_dcursor_current(&cursor))) {
1150
0
    PAIR_VERIFY(vp);
1151
1152
    /*
1153
     *  Encode an individual VP
1154
     */
1155
0
    slen = fr_radius_encode_pair(&work_dbuff, &cursor, packet_ctx);
1156
0
    if (slen < 0) return slen;
1157
0
  } /* done looping over all attributes */
1158
1159
  /*
1160
   *  Add Proxy-State to the end of the packet if the caller requested it.
1161
   */
1162
0
  if (packet_ctx->add_proxy_state) {
1163
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_PROXY_STATE, (uint8_t) (2 + sizeof(packet_ctx->common->proxy_state)));
1164
0
    FR_DBUFF_IN_RETURN(&work_dbuff, packet_ctx->common->proxy_state);
1165
0
  }
1166
1167
  /*
1168
   *  Fill in the length field we zeroed out earlier.
1169
   *
1170
   */
1171
0
  fr_dbuff_in(&length_dbuff, (uint16_t) (fr_dbuff_used(&work_dbuff)));
1172
1173
0
  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "%s encoded packet", __FUNCTION__);
1174
1175
0
  return fr_dbuff_set(dbuff, &work_dbuff);
1176
0
}
1177
1178
ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
1179
       uint8_t *packet, size_t packet_len,
1180
       fr_radius_decode_ctx_t *decode_ctx)
1181
4.77k
{
1182
4.77k
  ssize_t     slen;
1183
4.77k
  uint8_t const   *attr, *end;
1184
4.77k
  static const uint8_t    zeros[RADIUS_AUTH_VECTOR_LENGTH] = {};
1185
1186
4.77k
  decode_ctx->reason = FR_RADIUS_FAIL_NONE;
1187
1188
4.77k
  if (!decode_ctx->request_authenticator) {
1189
0
    switch (packet[0]) {
1190
0
    case FR_RADIUS_CODE_ACCESS_REQUEST:
1191
0
    case FR_RADIUS_CODE_STATUS_SERVER:
1192
0
      decode_ctx->request_authenticator = packet + 4;
1193
0
      break;
1194
1195
0
    case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
1196
0
    case FR_RADIUS_CODE_COA_REQUEST:
1197
0
    case FR_RADIUS_CODE_DISCONNECT_REQUEST:
1198
0
      decode_ctx->request_authenticator = zeros;
1199
0
      break;
1200
1201
0
    default:
1202
0
      fr_strerror_const("No authentication vector passed for packet decode");
1203
0
      decode_ctx->reason = FR_RADIUS_FAIL_NO_MATCHING_REQUEST;
1204
0
      return -1;
1205
0
    }
1206
0
  }
1207
1208
4.77k
  if (decode_ctx->request_code) {
1209
0
    unsigned int code = packet[0];
1210
1211
0
    if (code >= FR_RADIUS_CODE_MAX) {
1212
0
      decode_ctx->reason = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE;
1213
0
      return -1;
1214
0
    }
1215
0
    if (decode_ctx->request_code >= FR_RADIUS_CODE_MAX) {
1216
0
      decode_ctx->reason = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE;
1217
0
      return -1;
1218
0
    }
1219
1220
0
    if (!allowed_replies[code]) {
1221
0
      decode_ctx->reason = FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE;
1222
0
      return -1;
1223
0
    }
1224
1225
    /*
1226
     *  Protocol error can reply to any packet.
1227
     *
1228
     *  Status-Server can get any reply.
1229
     *
1230
     *  Otherwise the reply code must be associated with the request code we sent.
1231
     */
1232
0
    if ((allowed_replies[code] != decode_ctx->request_code) &&
1233
0
        (code != FR_RADIUS_CODE_PROTOCOL_ERROR) &&
1234
0
        (decode_ctx->request_code != FR_RADIUS_CODE_STATUS_SERVER)) {
1235
0
      decode_ctx->reason = FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE;
1236
0
      return -1;
1237
0
    }
1238
0
  }
1239
1240
  /*
1241
   *  We can skip verification for dynamic client checks, and where packets are unsigned as with
1242
   *  RADIUS/1.1.
1243
   */
1244
4.77k
  if (decode_ctx->verify) {
1245
0
    if (!decode_ctx->request_authenticator) decode_ctx->request_authenticator = zeros;
1246
1247
0
    if (fr_radius_verify(packet, decode_ctx->request_authenticator,
1248
0
             (uint8_t const *) decode_ctx->common->secret, decode_ctx->common->secret_length,
1249
0
             decode_ctx->require_message_authenticator, decode_ctx->limit_proxy_state) < 0) {
1250
0
      decode_ctx->reason = FR_RADIUS_FAIL_VERIFY;
1251
0
      return -1;
1252
0
    }
1253
0
  }
1254
1255
4.77k
  attr = packet + 20;
1256
4.77k
  end = packet + packet_len;
1257
1258
  /*
1259
   *  The caller MUST have called fr_radius_ok() first.  If
1260
   *  he doesn't, all hell breaks loose.
1261
   */
1262
61.8k
  while (attr < end) {
1263
57.1k
    slen = fr_radius_decode_pair(ctx, out, attr, (end - attr), decode_ctx);
1264
57.1k
    if (slen < 0) {
1265
72
      decode_ctx->reason = FR_RADIUS_FAIL_ATTRIBUTE_DECODE;
1266
72
      return slen;
1267
72
    }
1268
1269
    /*
1270
     *  If slen is larger than the room in the packet,
1271
     *  all kinds of bad things happen.
1272
     */
1273
57.1k
     if (!fr_cond_assert(slen <= (end - attr))) {
1274
0
       return -slen;
1275
0
     }
1276
1277
57.1k
    attr += slen;
1278
57.1k
    talloc_free_children(decode_ctx->tmp_ctx);
1279
57.1k
  }
1280
1281
  /*
1282
   *  We've parsed the whole packet, return that.
1283
   */
1284
4.70k
  return packet_len;
1285
4.77k
}
1286
1287
/** Simple wrapper for callers who just need a shared secret
1288
 *
1289
 *  @note - All callers verify the packet via fr_radius_packet_verify() before calling this function.
1290
 */
1291
ssize_t fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out,
1292
        uint8_t *packet, size_t packet_len,
1293
        uint8_t const *vector, char const *secret)
1294
0
{
1295
0
  ssize_t rcode;
1296
0
  fr_radius_ctx_t   common_ctx = {};
1297
0
  fr_radius_decode_ctx_t  packet_ctx = {};
1298
1299
0
  common_ctx.secret = secret;
1300
0
  common_ctx.secret_length = strlen(secret);
1301
1302
0
  packet_ctx.common = &common_ctx;
1303
0
  packet_ctx.tmp_ctx = talloc(ctx, uint8_t);
1304
0
  packet_ctx.request_authenticator = vector;
1305
0
  packet_ctx.end = packet + packet_len;
1306
1307
0
  rcode = fr_radius_decode(ctx, out, packet, packet_len, &packet_ctx);
1308
0
  talloc_free(packet_ctx.tmp_ctx);
1309
1310
0
  return rcode;
1311
0
}
1312
1313
int fr_radius_global_init(void)
1314
10
{
1315
10
  if (instance_count > 0) {
1316
2
    instance_count++;
1317
2
    return 0;
1318
2
  }
1319
1320
8
  instance_count++;
1321
1322
8
  if (fr_dict_autoload(libfreeradius_radius_dict) < 0) {
1323
0
  fail:
1324
0
    instance_count--;
1325
0
    return -1;
1326
0
  }
1327
1328
8
  if (fr_dict_attr_autoload(libfreeradius_radius_dict_attr) < 0) {
1329
0
    fr_dict_autofree(libfreeradius_radius_dict);
1330
0
    goto fail;
1331
0
  }
1332
1333
8
  instantiated = true;
1334
8
  return 0;
1335
8
}
1336
1337
void fr_radius_global_free(void)
1338
10
{
1339
10
  if (!instantiated) return;
1340
1341
10
  if (--instance_count != 0) return;
1342
1343
8
  fr_dict_autofree(libfreeradius_radius_dict);
1344
1345
8
  instantiated = false;
1346
8
}
1347
1348
static bool attr_valid(fr_dict_attr_t *da)
1349
69.1k
{
1350
69.1k
  fr_radius_attr_flags_t const *flags = fr_radius_attr_flags(da);
1351
1352
69.1k
  if (da->parent->type == FR_TYPE_STRUCT) {
1353
1.38k
    if (flags->extended) {
1354
0
      fr_strerror_const("Attributes with 'extended' flag cannot be used inside of a 'struct'");
1355
0
      return false;
1356
0
    }
1357
1358
1.38k
    if (flags->long_extended) {
1359
0
      fr_strerror_const("Attributes with 'long_extended' flag cannot be used inside of a 'struct'");
1360
0
      return false;
1361
0
    }
1362
1363
1364
1.38k
    if (flags->concat) {
1365
0
      fr_strerror_const("Attributes with 'concat' flag cannot be used inside of a 'struct'");
1366
0
      return false;
1367
0
    }
1368
1369
1.38k
    if (flags->has_tag) {
1370
0
      fr_strerror_const("Attributes with 'tag' flag cannot be used inside of a 'struct'");
1371
0
      return false;
1372
0
    }
1373
1374
1.38k
    if (flags->abinary) {
1375
0
      fr_strerror_const("Attributes with 'abinary' flag cannot be used inside of a 'struct'");
1376
0
      return false;
1377
0
    }
1378
1379
1.38k
    if (flags->encrypt > 0) {
1380
0
      fr_strerror_const("Attributes with 'encrypt' flag cannot be used inside of a 'struct'");
1381
0
      return false;
1382
0
    }
1383
1384
1.38k
    return true;
1385
1.38k
  }
1386
1387
67.8k
  if (da->flags.length > 253) {
1388
0
    fr_strerror_printf("Attributes cannot be more than 253 octets in length");
1389
0
    return false;
1390
0
  }
1391
  /*
1392
   *  Secret things are secret.
1393
   */
1394
67.8k
  if (flags->encrypt != 0) da->flags.secret = true;
1395
1396
67.8k
  if (flags->concat) {
1397
32
    if (!da->parent->flags.is_root) {
1398
0
      fr_strerror_const("Attributes with the 'concat' flag MUST be at the root of the dictionary");
1399
0
      return false;
1400
0
    }
1401
1402
32
    if (da->type != FR_TYPE_OCTETS) {
1403
0
      fr_strerror_const("Attributes with the 'concat' flag MUST be of data type 'octets'");
1404
0
      return false;
1405
0
    }
1406
1407
32
    return true; /* can't use any other flag */
1408
32
  }
1409
1410
  /*
1411
   *  Tagged attributes can only be of two data types.  They
1412
   *  can, however, be VSAs.
1413
   */
1414
67.7k
  if (flags->has_tag) {
1415
336
    if ((da->type != FR_TYPE_UINT32) && (da->type != FR_TYPE_STRING)) {
1416
0
      fr_strerror_printf("The 'has_tag' flag can only be used for attributes of type 'integer' "
1417
0
             "or 'string'");
1418
0
      return false;
1419
0
    }
1420
1421
336
    if (!(da->parent->flags.is_root ||
1422
256
          ((da->parent->type == FR_TYPE_VENDOR) &&
1423
256
           (da->parent->parent && da->parent->parent->type == FR_TYPE_VSA)))) {
1424
0
      fr_strerror_const("The 'has_tag' flag can only be used with RFC and VSA attributes");
1425
0
      return false;
1426
0
    }
1427
1428
336
    return true;
1429
336
  }
1430
1431
67.4k
  if (flags->extended) {
1432
32
    if (da->type != FR_TYPE_TLV) {
1433
0
      fr_strerror_const("The 'long' or 'extended' flag can only be used for attributes of type 'tlv'");
1434
0
      return false;
1435
0
    }
1436
1437
32
    if (!da->parent->flags.is_root) {
1438
0
      fr_strerror_const("The 'long' flag can only be used for top-level RFC attributes");
1439
0
      return false;
1440
0
    }
1441
1442
32
    return true;
1443
32
  }
1444
1445
  /*
1446
   *  Stupid hacks for MS-CHAP-MPPE-Keys.  The User-Password
1447
   *  encryption method has no provisions for encoding the
1448
   *  length of the data.  For User-Password, the data is
1449
   *  (presumably) all printable non-zero data.  For
1450
   *  MS-CHAP-MPPE-Keys, the data is binary crap.  So... we
1451
   *  MUST specify a length in the dictionary.
1452
   */
1453
67.4k
  if ((flags->encrypt == RADIUS_FLAG_ENCRYPT_USER_PASSWORD) && (da->type != FR_TYPE_STRING)) {
1454
8
    if (da->type != FR_TYPE_OCTETS) {
1455
0
      fr_strerror_printf("The 'encrypt=User-Password' flag can only be used with "
1456
0
             "attributes of type 'string'");
1457
0
      return false;
1458
0
    }
1459
1460
8
    if (da->flags.length == 0) {
1461
0
      fr_strerror_printf("The 'encrypt=User-Password' flag MUST be used with an explicit length for "
1462
0
             "'octets' data types");
1463
0
      return false;
1464
0
    }
1465
8
  }
1466
1467
67.4k
  switch (da->type) {
1468
23.8k
  case FR_TYPE_STRING:
1469
23.8k
    break;
1470
1471
656
  case FR_TYPE_TLV:
1472
3.27k
  case FR_TYPE_IPV4_ADDR:
1473
27.7k
  case FR_TYPE_UINT32:
1474
30.5k
  case FR_TYPE_OCTETS:
1475
30.5k
    if (flags->encrypt != RADIUS_FLAG_ENCRYPT_ASCEND_SECRET) break;
1476
0
    FALL_THROUGH;
1477
1478
13.0k
  default:
1479
13.0k
    if (flags->encrypt) {
1480
0
      fr_strerror_printf("The 'encrypt' flag cannot be used with attributes of type '%s'",
1481
0
             fr_type_to_str(da->type));
1482
0
      return false;
1483
0
    }
1484
67.4k
  }
1485
1486
67.4k
  return true;
1487
67.4k
}
1488
1489
fr_dict_protocol_t libfreeradius_radius_dict_protocol = {
1490
  .name = "radius",
1491
  .default_type_size = 1,
1492
  .default_type_length = 1,
1493
  .attr = {
1494
    .flags = {
1495
      .table = radius_flags,
1496
      .table_len = NUM_ELEMENTS(radius_flags),
1497
      .len = sizeof(fr_radius_attr_flags_t),
1498
    },
1499
    .valid = attr_valid,
1500
  },
1501
1502
  .init = fr_radius_global_init,
1503
  .free = fr_radius_global_free,
1504
1505
  .decode = fr_radius_decode_foreign,
1506
  .encode = fr_radius_encode_foreign,
1507
};