All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
radius.c
Go to the documentation of this file.
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: bb5ce533b6dde6e72c54a7d67756ced7ac36b4fe $
19  *
20  * @file radius.c
21  * @brief Functions to send/receive radius packets.
22  *
23  * @copyright 2000-2003,2006 The FreeRADIUS server project
24  */
25 
26 RCSID("$Id: bb5ce533b6dde6e72c54a7d67756ced7ac36b4fe $")
27 
28 #include <freeradius-devel/libradius.h>
29 
30 #include <freeradius-devel/md5.h>
31 #include <freeradius-devel/udp.h>
32 
33 #include <fcntl.h>
34 #include <ctype.h>
35 
36 #ifdef WITH_UDPFROMTO
37 #include <freeradius-devel/udpfromto.h>
38 #endif
39 
40 typedef struct radius_packet_t {
41  uint8_t code;
42  uint8_t id;
43  uint8_t length[2];
45  uint8_t data[1];
47 
48 /*
49  * Some messages get printed out only in debugging mode.
50  */
51 #define FR_DEBUG_STRERROR_PRINTF if (fr_debug_lvl) fr_strerror_printf
53  { "auth", PW_CODE_ACCESS_REQUEST },
54  { "challenge", PW_CODE_ACCESS_CHALLENGE },
55  { "acct", PW_CODE_ACCOUNTING_REQUEST },
56  { "status", PW_CODE_STATUS_SERVER },
57  { "disconnect", PW_CODE_DISCONNECT_REQUEST },
58  { "coa", PW_CODE_COA_REQUEST },
59  { "auto", PW_CODE_UNDEFINED },
60 
61  { NULL, 0}
62 };
63 
64 /*
65  * The RFC says 4096 octets max, and most packets are less than 256.
66  */
67 #define MAX_PACKET_LEN 4096
68 
69 /*
70  * The maximum number of attributes which we allow in an incoming
71  * request. If there are more attributes than this, the request
72  * is rejected.
73  *
74  * This helps to minimize the potential for a DoS, when an
75  * attacker spoofs Access-Request packets, which don't have a
76  * Message-Authenticator attribute. This means that the packet
77  * is unsigned, and the attacker can use resources on the server,
78  * even if the end request is rejected.
79  */
80 uint32_t fr_max_attributes = 0;
81 FILE *fr_log_fp = NULL;
82 
83 
84 static void print_hex_data(uint8_t const *ptr, int attrlen, int depth)
85 {
86  int i;
87  static char const tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
88 
89  for (i = 0; i < attrlen; i++) {
90  if ((i > 0) && ((i & 0x0f) == 0x00))
91  fprintf(fr_log_fp, "%.*s", depth, tabs);
92  fprintf(fr_log_fp, "%02x ", ptr[i]);
93  if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
94  }
95  if ((i & 0x0f) != 0) fprintf(fr_log_fp, "\n");
96 }
97 
98 static _fr_thread_local fr_randctx fr_rand_pool; //!< A pool of pre-generated random integers
99 static _fr_thread_local bool fr_rand_initialized = false;
100 
102  "", //!< 0
103  "Access-Request",
104  "Access-Accept",
105  "Access-Reject",
106  "Accounting-Request",
107  "Accounting-Response",
108  "Accounting-Status",
109  "Password-Request",
110  "Password-Accept",
111  "Password-Reject",
112  "Accounting-Message", //!< 10
113  "Access-Challenge",
114  "Status-Server",
115  "Status-Client",
116  "14",
117  "15",
118  "16",
119  "17",
120  "18",
121  "19",
122  "20", //!< 20
123  "Resource-Free-Request",
124  "Resource-Free-Response",
125  "Resource-Query-Request",
126  "Resource-Query-Response",
127  "Alternate-Resource-Reclaim-Request",
128  "NAS-Reboot-Request",
129  "NAS-Reboot-Response",
130  "28",
131  "Next-Passcode",
132  "New-Pin", //!< 30
133  "Terminate-Session",
134  "Password-Expired",
135  "Event-Request",
136  "Event-Response",
137  "35",
138  "36",
139  "37",
140  "38",
141  "39",
142  "Disconnect-Request", //!< 40
143  "Disconnect-ACK",
144  "Disconnect-NAK",
145  "CoA-Request",
146  "CoA-ACK",
147  "CoA-NAK",
148  "46",
149  "47",
150  "48",
151  "49",
152  "IP-Address-Allocate",
153  "IP-Address-Release", //!< 50
154 };
155 
156 void fr_printf_log(char const *fmt, ...)
157 {
158  va_list ap;
159 
160  va_start(ap, fmt);
161  if ((fr_debug_lvl == 0) || !fr_log_fp) {
162  va_end(ap);
163  return;
164  }
165 
166  vfprintf(fr_log_fp, fmt, ap);
167  va_end(ap);
168 
169  return;
170 }
171 
173 {
174  int i;
175 
176  if (!packet->data || !fr_log_fp) return;
177 
178  fprintf(fr_log_fp, " Socket:\t%d\n", packet->sockfd);
179 #ifdef WITH_TCP
180  fprintf(fr_log_fp, " Proto:\t%d\n", packet->proto);
181 #endif
182 
183  if (packet->src_ipaddr.af == AF_INET) {
184  char buffer[INET6_ADDRSTRLEN];
185 
186  fprintf(fr_log_fp, " Src IP:\t%s\n",
187  inet_ntop(packet->src_ipaddr.af,
188  &packet->src_ipaddr.ipaddr,
189  buffer, sizeof(buffer)));
190  fprintf(fr_log_fp, " port:\t%u\n", packet->src_port);
191 
192  fprintf(fr_log_fp, " Dst IP:\t%s\n",
193  inet_ntop(packet->dst_ipaddr.af,
194  &packet->dst_ipaddr.ipaddr,
195  buffer, sizeof(buffer)));
196  fprintf(fr_log_fp, " port:\t%u\n", packet->dst_port);
197  }
198 
199  if (packet->data[0] < FR_MAX_PACKET_CODE) {
200  fprintf(fr_log_fp, " Code:\t\t(%d) %s\n", packet->data[0], fr_packet_codes[packet->data[0]]);
201  } else {
202  fprintf(fr_log_fp, " Code:\t\t%u\n", packet->data[0]);
203  }
204  fprintf(fr_log_fp, " Id:\t\t%u\n", packet->data[1]);
205  fprintf(fr_log_fp, " Length:\t%u\n", ((packet->data[2] << 8) |
206  (packet->data[3])));
207  fprintf(fr_log_fp, " Vector:\t");
208  for (i = 4; i < 20; i++) {
209  fprintf(fr_log_fp, "%02x", packet->data[i]);
210  }
211  fprintf(fr_log_fp, "\n");
212 
213  if (packet->data_len > 20) {
214  int total;
215  uint8_t const *ptr;
216  fprintf(fr_log_fp, " Data:");
217 
218  total = packet->data_len - 20;
219  ptr = packet->data + 20;
220 
221  while (total > 0) {
222  int attrlen;
223  unsigned int vendor = 0;
224 
225  fprintf(fr_log_fp, "\t\t");
226  if (total < 2) { /* too short */
227  fprintf(fr_log_fp, "%02x\n", *ptr);
228  break;
229  }
230 
231  if (ptr[1] > total) { /* too long */
232  for (i = 0; i < total; i++) {
233  fprintf(fr_log_fp, "%02x ", ptr[i]);
234  }
235  break;
236  }
237 
238  fprintf(fr_log_fp, "%02x %02x ", ptr[0], ptr[1]);
239  attrlen = ptr[1] - 2;
240 
241  if ((ptr[0] == PW_VENDOR_SPECIFIC) &&
242  (attrlen > 4)) {
243  vendor = (ptr[3] << 16) | (ptr[4] << 8) | ptr[5];
244  fprintf(fr_log_fp, "%02x%02x%02x%02x (%u) ",
245  ptr[2], ptr[3], ptr[4], ptr[5], vendor);
246  attrlen -= 4;
247  ptr += 6;
248  total -= 6;
249 
250  } else {
251  ptr += 2;
252  total -= 2;
253  }
254 
255  print_hex_data(ptr, attrlen, 3);
256 
257  ptr += attrlen;
258  total -= attrlen;
259  }
260  }
261  fflush(stdout);
262 }
263 
264 
265 /** Build an encrypted secret value to return in a reply packet
266  *
267  * The secret is hidden by xoring with a MD5 digest created from
268  * the shared secret and the authentication vector.
269  * We put them into MD5 in the reverse order from that used when
270  * encrypting passwords to RADIUS.
271  */
272 void fr_radius_make_secret(uint8_t *digest, uint8_t const *vector, char const *secret, uint8_t const *value)
273 {
274  FR_MD5_CTX context;
275  int i;
276 
277  fr_md5_init(&context);
278  fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
279  fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
280  fr_md5_final(digest, &context);
281 
282  for (i = 0; i < AUTH_VECTOR_LEN; i++ ) digest[i] ^= value[i];
283 }
284 
285 /** Basic validation of RADIUS packet header
286  *
287  * @note fr_strerror errors are only available if fr_debug_lvl > 0. This is to reduce CPU time
288  * consumed when discarding malformed packet.
289  *
290  * @param[in] sockfd we're reading from.
291  * @param[out] src_ipaddr of the packet.
292  * @param[out] src_port of the packet.
293  * @param[out] code Pointer to where to write the packet code.
294  * @return
295  * - -1 on failure.
296  * - 1 on decode error.
297  * - >= RADIUS_HDR_LEN on success. This is the packet length as specified in the header.
298  */
299 ssize_t fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code)
300 {
301  ssize_t data_len, packet_len;
302  uint8_t header[4];
303 
304  data_len = udp_recv_peek(sockfd, header, sizeof(header), UDP_FLAGS_PEEK, src_ipaddr, src_port);
305  if (data_len < 0) {
306  if ((errno == EAGAIN) || (errno == EINTR)) return 0;
307  return -1;
308  }
309 
310  /*
311  * Too little data is available, discard the packet.
312  */
313  if (data_len < 4) {
314  char buffer[INET6_ADDRSTRLEN];
315 
316  FR_DEBUG_STRERROR_PRINTF("Expected at least 4 bytes of header data, got %zu bytes", data_len);
317 invalid:
318  FR_DEBUG_STRERROR_PRINTF("Invalid data from %s: %s",
319  inet_ntop(src_ipaddr->af, &src_ipaddr->ipaddr, buffer, sizeof(buffer)),
320  fr_strerror());
321  udp_recv_discard(sockfd);
322 
323  return 0;
324  }
325 
326  /*
327  * See how long the packet says it is.
328  */
329  packet_len = (header[2] * 256) + header[3];
330 
331  /*
332  * The length in the packet says it's less than
333  * a RADIUS header length: discard it.
334  */
335  if (packet_len < RADIUS_HDR_LEN) {
336  FR_DEBUG_STRERROR_PRINTF("Expected at least " STRINGIFY(RADIUS_HDR_LEN) " bytes of packet "
337  "data, got %zu bytes", packet_len);
338  goto invalid;
339  }
340 
341  /*
342  * Enforce RFC requirements, for sanity.
343  * Anything after 4k will be discarded.
344  */
345  if (packet_len > MAX_PACKET_LEN) {
346  FR_DEBUG_STRERROR_PRINTF("Length field value too large, expected maximum of "
347  STRINGIFY(MAX_PACKET_LEN) " bytes, got %zu bytes", packet_len);
348  goto invalid;
349  }
350 
351  *code = header[0];
352 
353  /*
354  * The packet says it's this long, but the actual UDP
355  * size could still be smaller.
356  */
357  return packet_len;
358 }
359 
360 /** Wrapper for recvfrom, which handles recvfromto, IPv6, and all possible combinations
361  *
362  */
363 static ssize_t rad_recvfrom(int sockfd, RADIUS_PACKET *packet, int flags)
364 {
365  ssize_t data_len;
366 
367  data_len = fr_radius_recv_header(sockfd, &packet->src_ipaddr, &packet->src_port, &packet->code);
368  if (data_len < 0) {
369  if ((errno == EAGAIN) || (errno == EINTR)) return 0;
370  return -1;
371  }
372 
373  if (data_len == 0) return -1; /* invalid packet */
374 
375  packet->data = talloc_array(packet, uint8_t, data_len);
376  if (!packet->data) return -1;
377 
378  packet->data_len = data_len;
379 
380  return udp_recv(sockfd, packet->data, packet->data_len, flags,
381  &packet->src_ipaddr, &packet->src_port,
382  &packet->dst_ipaddr, &packet->dst_port,
383  &packet->if_index, &packet->timestamp);
384 }
385 
386 /** Sign a previously encoded packet
387  *
388  */
389 int fr_radius_sign(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
390  char const *secret)
391 {
392  radius_packet_t *hdr = (radius_packet_t *)packet->data;
393 
394  /*
395  * It wasn't assigned an Id, this is bad!
396  */
397  if (packet->id < 0) {
398  fr_strerror_printf("ERROR: RADIUS packets must be assigned an Id");
399  return -1;
400  }
401 
402  if (!packet->data || (packet->data_len < RADIUS_HDR_LEN) ||
403  (packet->offset < 0)) {
404  fr_strerror_printf("ERROR: You must call fr_radius_encode() before fr_radius_sign()");
405  return -1;
406  }
407 
408  /*
409  * If there's a Message-Authenticator, update it
410  * now, BEFORE updating the authentication vector.
411  */
412  if (packet->offset > 0) {
413  uint8_t calc_auth_vector[AUTH_VECTOR_LEN];
414 
415  switch (packet->code) {
417  if (original && original->code == PW_CODE_STATUS_SERVER) {
418  goto do_ack;
419  }
420 
425  case PW_CODE_COA_REQUEST:
426  case PW_CODE_COA_ACK:
427  memset(hdr->vector, 0, AUTH_VECTOR_LEN);
428  break;
429 
430  do_ack:
434  if (!original) {
435  fr_strerror_printf("ERROR: Cannot sign response packet without a request packet");
436  return -1;
437  }
438  memcpy(hdr->vector, original->vector,
440  break;
441 
442  default: /* others have vector already set to zero */
443  break;
444 
445  }
446 
447  /*
448  * Set the authentication vector to zero,
449  * calculate the HMAC, and put it
450  * into the Message-Authenticator
451  * attribute.
452  */
453  fr_hmac_md5(calc_auth_vector, packet->data, packet->data_len,
454  (uint8_t const *) secret, strlen(secret));
455  memcpy(packet->data + packet->offset + 2,
456  calc_auth_vector, AUTH_VECTOR_LEN);
457 
458  /*
459  * Copy the original request vector back
460  * to the raw packet.
461  */
462  memcpy(hdr->vector, packet->vector, AUTH_VECTOR_LEN);
463  }
464 
465  /*
466  * Switch over the packet code, deciding how to
467  * sign the packet.
468  */
469  switch (packet->code) {
470  /*
471  * Request packets are not signed, bur
472  * have a random authentication vector.
473  */
476  break;
477 
478  /*
479  * Reply packets are signed with the
480  * authentication vector of the request.
481  */
482  default:
483  {
484  uint8_t digest[16];
485 
486  FR_MD5_CTX context;
487  fr_md5_init(&context);
488  fr_md5_update(&context, packet->data, packet->data_len);
489  fr_md5_update(&context, (uint8_t const *) secret,
490  strlen(secret));
491  fr_md5_final(digest, &context);
492 
493  memcpy(hdr->vector, digest, AUTH_VECTOR_LEN);
494  memcpy(packet->vector, digest, AUTH_VECTOR_LEN);
495  break;
496  }
497  }/* switch over packet codes */
498 
499  return 0;
500 }
501 
502 /** Reply to the request
503  *
504  * Also attach reply attribute value pairs and any user message provided.
505  */
506 int fr_radius_send(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
507  char const *secret)
508 {
509  /*
510  * Maybe it's a fake packet. Don't send it.
511  */
512  if (!packet || (packet->sockfd < 0)) {
513  return 0;
514  }
515 
516  /*
517  * First time through, allocate room for the packet
518  */
519  if (!packet->data) {
520  /*
521  * Encode the packet.
522  */
523  if (fr_radius_encode(packet, original, secret) < 0) {
524  return -1;
525  }
526 
527  /*
528  * Re-sign it, including updating the
529  * Message-Authenticator.
530  */
531  if (fr_radius_sign(packet, original, secret) < 0) {
532  return -1;
533  }
534 
535  /*
536  * If packet->data points to data, then we print out
537  * the VP list again only for debugging.
538  */
539  }
540 
541 #ifndef NDEBUG
542  if ((fr_debug_lvl > 3) && fr_log_fp) fr_radius_print_hex(packet);
543 #endif
544 
545 #ifdef WITH_TCP
546  /*
547  * If the socket is TCP, call write(). Calling sendto()
548  * is allowed on some platforms, but it's not nice. Even
549  * worse, if UDPFROMTO is defined, we *can't* use it on
550  * TCP sockets. So... just call write().
551  */
552  if (packet->proto == IPPROTO_TCP) {
553  ssize_t rcode;
554 
555  rcode = write(packet->sockfd, packet->data, packet->data_len);
556  if (rcode >= 0) return rcode;
557 
558  fr_strerror_printf("sendto failed: %s", fr_syserror(errno));
559  return -1;
560  }
561 #endif
562 
563  /*
564  * And send it on it's way.
565  */
566  return udp_send(packet->sockfd, packet->data, packet->data_len, 0,
567  &packet->src_ipaddr, packet->src_port, packet->if_index,
568  &packet->dst_ipaddr, packet->dst_port);
569 }
570 
571 /** Do a comparison of two authentication digests by comparing the FULL digest
572  *
573  * Otherwise, the server can be subject to timing attacks that allow attackers
574  * find a valid message authenticator.
575  *
576  * http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf
577  */
578 int fr_radius_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
579 {
580  int result = 0;
581  size_t i;
582 
583  for (i = 0; i < length; i++) {
584  result |= a[i] ^ b[i];
585  }
586 
587  return result; /* 0 is OK, !0 is !OK, just like memcmp */
588 }
589 
590 
591 /** Validates the requesting client NAS
592  *
593  * Calculates the request Authenticator based on the clients private key.
594  */
595 static int calc_acctdigest(RADIUS_PACKET *packet, char const *secret)
596 {
597  uint8_t digest[AUTH_VECTOR_LEN];
598  FR_MD5_CTX context;
599 
600  /*
601  * Zero out the auth_vector in the received packet.
602  * Then append the shared secret to the received packet,
603  * and calculate the MD5 sum. This must be the same
604  * as the original MD5 sum (packet->vector).
605  */
606  memset(packet->data + 4, 0, AUTH_VECTOR_LEN);
607 
608  /*
609  * MD5(packet + secret);
610  */
611  fr_md5_init(&context);
612  fr_md5_update(&context, packet->data, packet->data_len);
613  fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
614  fr_md5_final(digest, &context);
615 
616  /*
617  * Return 0 if OK, 2 if not OK.
618  */
619  if (fr_radius_digest_cmp(digest, packet->vector, AUTH_VECTOR_LEN) != 0) return 2;
620  return 0;
621 }
622 
623 
624 /** Validates the requesting client NAS
625  *
626  * Calculates the response Authenticator based on the clients
627  * private key.
628  */
629 static int calc_replydigest(RADIUS_PACKET *packet, RADIUS_PACKET *original,
630  char const *secret)
631 {
632  uint8_t calc_digest[AUTH_VECTOR_LEN];
633  FR_MD5_CTX context;
634 
635  /*
636  * Very bad!
637  */
638  if (original == NULL) {
639  return 3;
640  }
641 
642  /*
643  * Copy the original vector in place.
644  */
645  memcpy(packet->data + 4, original->vector, AUTH_VECTOR_LEN);
646 
647  /*
648  * MD5(packet + secret);
649  */
650  fr_md5_init(&context);
651  fr_md5_update(&context, packet->data, packet->data_len);
652  fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
653  fr_md5_final(calc_digest, &context);
654 
655  /*
656  * Copy the packet's vector back to the packet.
657  */
658  memcpy(packet->data + 4, packet->vector, AUTH_VECTOR_LEN);
659 
660  /*
661  * Return 0 if OK, 2 if not OK.
662  */
663  if (fr_radius_digest_cmp(packet->vector, calc_digest, AUTH_VECTOR_LEN) != 0) return 2;
664  return 0;
665 }
666 
667 
668 /** See how big of a packet is in the buffer.
669  *
670  * Packet is not 'const * const' because we may update data_len, if there's more data
671  * in the UDP packet than in the RADIUS packet.
672  *
673  * @param data pointer to the packet buffer
674  * @param data_len length of the packet buffer
675  * @return
676  * <= 0 packet is bad.
677  * >0 how much of the data is a packet (can be larger than data_len)
678  */
679 ssize_t fr_radius_len(uint8_t const *data, size_t data_len)
680 {
681  size_t totallen;
682  uint8_t const *attr, *end;
683 
684  /*
685  * Want at least this much before doing anything else
686  */
687  if (!data || (data_len < RADIUS_HDR_LEN)) return RADIUS_HDR_LEN;
688 
689  /*
690  * We want at least this much data for a real RADIUS packet/
691  */
692  totallen = (data[2] << 8) | data[3];
693  if (data_len < totallen) return totallen;
694 
695  if (totallen == RADIUS_HDR_LEN) return totallen;
696 
697  attr = data + RADIUS_HDR_LEN;
698  end = data + totallen;
699 
700  /*
701  * Do a quick pass to sanity check it.
702  */
703  while (attr < end) {
704  if ((end - attr) < 2) return -(attr - data);
705 
706  if (attr[0] == 0) return -(attr - data);
707 
708  if (attr[1] < 2) return - (attr + 1 - data);
709 
710  if ((attr + attr[1]) > end) return -(attr + 1 - data);
711 
712  attr += attr[1];
713  }
714 
715  return totallen;
716 }
717 
718 
719 /** See if the data pointed to by PTR is a valid RADIUS packet.
720  *
721  * Packet is not 'const * const' because we may update data_len, if there's more data
722  * in the UDP packet than in the RADIUS packet.
723  *
724  * @param packet to check
725  * @param flags to control decoding
726  * @param reason if not NULL, will have the failure reason written to where it points.
727  * @return
728  * - True on success.
729  * - False on failure.
730  */
731 bool fr_radius_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
732 {
733  uint8_t *attr;
734  size_t totallen;
735  int count;
736  radius_packet_t *hdr;
737  char host_ipaddr[INET6_ADDRSTRLEN];
738  bool require_ma = false;
739  bool seen_ma = false;
740  uint32_t num_attributes;
742 
743  /*
744  * Check for packets smaller than the packet header.
745  *
746  * RFC 2865, Section 3., subsection 'length' says:
747  *
748  * "The minimum length is 20 ..."
749  */
750  if (packet->data_len < RADIUS_HDR_LEN) {
751  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: too short (received %zu < minimum %d)",
752  inet_ntop(packet->src_ipaddr.af,
753  &packet->src_ipaddr.ipaddr,
754  host_ipaddr, sizeof(host_ipaddr)),
755  packet->data_len, RADIUS_HDR_LEN);
757  goto finish;
758  }
759 
760 
761  /*
762  * Check for packets with mismatched size.
763  * i.e. We've received 128 bytes, and the packet header
764  * says it's 256 bytes long.
765  */
766  totallen = (packet->data[2] << 8) | packet->data[3];
767  hdr = (radius_packet_t *)packet->data;
768 
769  /*
770  * Code of 0 is not understood.
771  * Code of 16 or greate is not understood.
772  */
773  if ((hdr->code == 0) ||
774  (hdr->code >= FR_MAX_PACKET_CODE)) {
775  FR_DEBUG_STRERROR_PRINTF("Bad RADIUS packet from host %s: unknown packet code %d",
776  inet_ntop(packet->src_ipaddr.af,
777  &packet->src_ipaddr.ipaddr,
778  host_ipaddr, sizeof(host_ipaddr)),
779  hdr->code);
781  goto finish;
782  }
783 
784  /*
785  * Message-Authenticator is required in Status-Server
786  * packets, otherwise they can be trivially forged.
787  */
788  if (hdr->code == PW_CODE_STATUS_SERVER) require_ma = true;
789 
790  /*
791  * It's also required if the caller asks for it.
792  */
793  if (flags) require_ma = true;
794 
795  /*
796  * Repeat the length checks. This time, instead of
797  * looking at the data we received, look at the value
798  * of the 'length' field inside of the packet.
799  *
800  * Check for packets smaller than the packet header.
801  *
802  * RFC 2865, Section 3., subsection 'length' says:
803  *
804  * "The minimum length is 20 ..."
805  */
806  if (totallen < RADIUS_HDR_LEN) {
807  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: too short (length %zu < minimum %d)",
808  inet_ntop(packet->src_ipaddr.af,
809  &packet->src_ipaddr.ipaddr,
810  host_ipaddr, sizeof(host_ipaddr)),
811  totallen, RADIUS_HDR_LEN);
813  goto finish;
814  }
815 
816  /*
817  * And again, for the value of the 'length' field.
818  *
819  * RFC 2865, Section 3., subsection 'length' says:
820  *
821  * " ... and maximum length is 4096."
822  *
823  * HOWEVER. This requirement is for the network layer.
824  * If the code gets here, we assume that a well-formed
825  * packet is an OK packet.
826  *
827  * We allow both the UDP data length, and the RADIUS
828  * "length" field to contain up to 64K of data.
829  */
830 
831  /*
832  * RFC 2865, Section 3., subsection 'length' says:
833  *
834  * "If the packet is shorter than the Length field
835  * indicates, it MUST be silently discarded."
836  *
837  * i.e. No response to the NAS.
838  */
839  if (packet->data_len < totallen) {
840  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: received %zu octets, packet length says %zu",
841  inet_ntop(packet->src_ipaddr.af,
842  &packet->src_ipaddr.ipaddr,
843  host_ipaddr, sizeof(host_ipaddr)),
844  packet->data_len, totallen);
846  goto finish;
847  }
848 
849  /*
850  * RFC 2865, Section 3., subsection 'length' says:
851  *
852  * "Octets outside the range of the Length field MUST be
853  * treated as padding and ignored on reception."
854  */
855  if (packet->data_len > totallen) {
856  /*
857  * We're shortening the packet below, but just
858  * to be paranoid, zero out the extra data.
859  */
860  memset(packet->data + totallen, 0, packet->data_len - totallen);
861  packet->data_len = totallen;
862  }
863 
864  /*
865  * Walk through the packet's attributes, ensuring that
866  * they add up EXACTLY to the size of the packet.
867  *
868  * If they don't, then the attributes either under-fill
869  * or over-fill the packet. Any parsing of the packet
870  * is impossible, and will result in unknown side effects.
871  *
872  * This would ONLY happen with buggy RADIUS implementations,
873  * or with an intentional attack. Either way, we do NOT want
874  * to be vulnerable to this problem.
875  */
876  attr = hdr->data;
877  count = totallen - RADIUS_HDR_LEN;
878  num_attributes = 0;
879 
880  while (count > 0) {
881  /*
882  * We need at least 2 bytes to check the
883  * attribute header.
884  */
885  if (count < 2) {
886  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: attribute header overflows the packet",
887  inet_ntop(packet->src_ipaddr.af,
888  &packet->src_ipaddr.ipaddr,
889  host_ipaddr, sizeof(host_ipaddr)));
890  failure = DECODE_FAIL_HEADER_OVERFLOW;
891  goto finish;
892  }
893 
894  /*
895  * Attribute number zero is NOT defined.
896  */
897  if (attr[0] == 0) {
898  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: Invalid attribute 0",
899  inet_ntop(packet->src_ipaddr.af,
900  &packet->src_ipaddr.ipaddr,
901  host_ipaddr, sizeof(host_ipaddr)));
903  goto finish;
904  }
905 
906  /*
907  * Attributes are at LEAST as long as the ID & length
908  * fields. Anything shorter is an invalid attribute.
909  */
910  if (attr[1] < 2) {
911  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: attribute %u too short",
912  inet_ntop(packet->src_ipaddr.af,
913  &packet->src_ipaddr.ipaddr,
914  host_ipaddr, sizeof(host_ipaddr)),
915  attr[0]);
917  goto finish;
918  }
919 
920  /*
921  * If there are fewer bytes in the packet than in the
922  * attribute, it's a bad packet.
923  */
924  if (count < attr[1]) {
925  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: attribute %u data overflows the packet",
926  inet_ntop(packet->src_ipaddr.af,
927  &packet->src_ipaddr.ipaddr,
928  host_ipaddr, sizeof(host_ipaddr)),
929  attr[0]);
931  goto finish;
932  }
933 
934  /*
935  * Sanity check the attributes for length.
936  */
937  switch (attr[0]) {
938  default: /* don't do anything by default */
939  break;
940 
941  /*
942  * Track this for prioritizing ongoing EAP sessions.
943  */
944  case PW_STATE:
945  if (attr[1] > 2) packet->rounds = attr[2];
946  break;
947 
948  /*
949  * If there's an EAP-Message, we require
950  * a Message-Authenticator.
951  */
952  case PW_EAP_MESSAGE:
953  require_ma = true;
954  break;
955 
956  case PW_MESSAGE_AUTHENTICATOR:
957  if (attr[1] != 2 + AUTH_VECTOR_LEN) {
958  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: Message-Authenticator has invalid length %d",
959  inet_ntop(packet->src_ipaddr.af,
960  &packet->src_ipaddr.ipaddr,
961  host_ipaddr, sizeof(host_ipaddr)),
962  attr[1] - 2);
964  goto finish;
965  }
966  seen_ma = true;
967  break;
968  }
969 
970  /*
971  * FIXME: Look up the base 255 attributes in the
972  * dictionary, and switch over their type. For
973  * integer/date/ip, the attribute length SHOULD
974  * be 6.
975  */
976  count -= attr[1]; /* grab the attribute length */
977  attr += attr[1];
978  num_attributes++; /* seen one more attribute */
979  }
980 
981  /*
982  * If the attributes add up to a packet, it's allowed.
983  *
984  * If not, we complain, and throw the packet away.
985  */
986  if (count != 0) {
987  FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: packet attributes do NOT exactly fill the packet",
988  inet_ntop(packet->src_ipaddr.af,
989  &packet->src_ipaddr.ipaddr,
990  host_ipaddr, sizeof(host_ipaddr)));
992  goto finish;
993  }
994 
995  /*
996  * If we're configured to look for a maximum number of
997  * attributes, and we've seen more than that maximum,
998  * then throw the packet away, as a possible DoS.
999  */
1000  if ((fr_max_attributes > 0) &&
1001  (num_attributes > fr_max_attributes)) {
1002  FR_DEBUG_STRERROR_PRINTF("Possible DoS attack from host %s: Too many attributes in request (received %d, max %d are allowed).",
1003  inet_ntop(packet->src_ipaddr.af,
1004  &packet->src_ipaddr.ipaddr,
1005  host_ipaddr, sizeof(host_ipaddr)),
1006  num_attributes, fr_max_attributes);
1008  goto finish;
1009  }
1010 
1011  /*
1012  * http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
1013  *
1014  * A packet with an EAP-Message attribute MUST also have
1015  * a Message-Authenticator attribute.
1016  *
1017  * A Message-Authenticator all by itself is OK, though.
1018  *
1019  * Similarly, Status-Server packets MUST contain
1020  * Message-Authenticator attributes.
1021  */
1022  if (require_ma && !seen_ma) {
1023  FR_DEBUG_STRERROR_PRINTF("Insecure packet from host %s: Packet does not contain required Message-Authenticator attribute",
1024  inet_ntop(packet->src_ipaddr.af,
1025  &packet->src_ipaddr.ipaddr,
1026  host_ipaddr, sizeof(host_ipaddr)));
1027  failure = DECODE_FAIL_MA_MISSING;
1028  goto finish;
1029  }
1030 
1031  /*
1032  * Fill RADIUS header fields
1033  */
1034  packet->code = hdr->code;
1035  packet->id = hdr->id;
1036  memcpy(packet->vector, hdr->vector, AUTH_VECTOR_LEN);
1037 
1038 
1039  finish:
1040 
1041  if (reason) {
1042  *reason = failure;
1043  }
1044  return (failure == DECODE_FAIL_NONE);
1045 }
1046 
1047 /** Receive UDP client requests, and fill in the basics of a RADIUS_PACKET structure
1048  *
1049  */
1050 RADIUS_PACKET *fr_radius_recv(TALLOC_CTX *ctx, int fd, int flags)
1051 {
1052  ssize_t data_len;
1053  RADIUS_PACKET *packet;
1054 
1055  /*
1056  * Allocate the new request data structure
1057  */
1058  packet = fr_radius_alloc(ctx, false);
1059  if (!packet) {
1060  fr_strerror_printf("out of memory");
1061  return NULL;
1062  }
1063 
1064  data_len = rad_recvfrom(fd, packet, UDP_FLAGS_NONE);
1065  if (data_len < 0) {
1066  FR_DEBUG_STRERROR_PRINTF("Error receiving packet: %s", fr_syserror(errno));
1067  fr_radius_free(&packet);
1068  return NULL;
1069  }
1070 
1071 #ifdef WITH_VERIFY_PTR
1072  /*
1073  * Double-check that the fields we want are filled in.
1074  */
1075  if ((packet->src_ipaddr.af == AF_UNSPEC) ||
1076  (packet->src_port == 0) ||
1077  (packet->dst_ipaddr.af == AF_UNSPEC) ||
1078  (packet->dst_port == 0)) {
1079  FR_DEBUG_STRERROR_PRINTF("Error receiving packet: %s", fr_syserror(errno));
1080  fr_radius_free(&packet);
1081  return NULL;
1082  }
1083 #endif
1084 
1085  packet->data_len = data_len; /* unsigned vs signed */
1086 
1087  /*
1088  * If the packet is too big, then rad_recvfrom did NOT
1089  * allocate memory. Instead, it just discarded the
1090  * packet.
1091  */
1092  if (packet->data_len > MAX_PACKET_LEN) {
1093  FR_DEBUG_STRERROR_PRINTF("Discarding packet: Larger than RFC limitation of 4096 bytes");
1094  fr_radius_free(&packet);
1095  return NULL;
1096  }
1097 
1098  /*
1099  * Read no data. Continue.
1100  * This check is AFTER the MAX_PACKET_LEN check above, because
1101  * if the packet is larger than MAX_PACKET_LEN, we also have
1102  * packet->data == NULL
1103  */
1104  if ((packet->data_len == 0) || !packet->data) {
1105  FR_DEBUG_STRERROR_PRINTF("Empty packet: Socket is not ready");
1106  fr_radius_free(&packet);
1107  return NULL;
1108  }
1109 
1110  /*
1111  * See if it's a well-formed RADIUS packet.
1112  */
1113  if (!fr_radius_ok(packet, flags, NULL)) {
1114  fr_radius_free(&packet);
1115  return NULL;
1116  }
1117 
1118  /*
1119  * Remember which socket we read the packet from.
1120  */
1121  packet->sockfd = fd;
1122 
1123  /*
1124  * FIXME: Do even more filtering by only permitting
1125  * certain IP's. The problem is that we don't know
1126  * how to do this properly for all possible clients...
1127  */
1128 
1129  /*
1130  * Explicitely set the VP list to empty.
1131  */
1132  packet->vps = NULL;
1133 
1134 #ifndef NDEBUG
1135  if ((fr_debug_lvl > 3) && fr_log_fp) fr_radius_print_hex(packet);
1136 #endif
1137 
1138  return packet;
1139 }
1140 
1141 /** Verify the Request/Response Authenticator (and Message-Authenticator if present) of a packet
1142  *
1143  */
1144 int fr_radius_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
1145 {
1146  uint8_t *ptr;
1147  int length;
1148  int attrlen;
1149  int rcode;
1150  char buffer[INET6_ADDRSTRLEN];
1151 
1152  if (!packet || !packet->data) return -1;
1153 
1154  /*
1155  * Before we allocate memory for the attributes, do more
1156  * sanity checking.
1157  */
1158  ptr = packet->data + RADIUS_HDR_LEN;
1159  length = packet->data_len - RADIUS_HDR_LEN;
1160  while (length > 0) {
1161  uint8_t msg_auth_vector[AUTH_VECTOR_LEN];
1162  uint8_t calc_auth_vector[AUTH_VECTOR_LEN];
1163 
1164  attrlen = ptr[1];
1165 
1166  switch (ptr[0]) {
1167  default: /* don't do anything. */
1168  break;
1169 
1170  /*
1171  * Note that more than one Message-Authenticator
1172  * attribute is invalid.
1173  */
1174  case PW_MESSAGE_AUTHENTICATOR:
1175  memcpy(msg_auth_vector, &ptr[2], sizeof(msg_auth_vector));
1176  memset(&ptr[2], 0, AUTH_VECTOR_LEN);
1177 
1178  switch (packet->code) {
1179  default:
1180  break;
1181 
1183  if (original &&
1184  (original->code == PW_CODE_STATUS_SERVER)) {
1185  goto do_ack;
1186  }
1187 
1190  case PW_CODE_COA_REQUEST:
1191  memset(packet->data + 4, 0, AUTH_VECTOR_LEN);
1192  break;
1193 
1194  do_ack:
1195  case PW_CODE_ACCESS_ACCEPT:
1196  case PW_CODE_ACCESS_REJECT:
1200  case PW_CODE_COA_ACK:
1201  case PW_CODE_COA_NAK:
1202  if (!original) {
1203  fr_strerror_printf("Cannot validate Message-Authenticator in response "
1204  "packet without a request packet");
1205  return -1;
1206  }
1207  memcpy(packet->data + 4, original->vector, AUTH_VECTOR_LEN);
1208  break;
1209  }
1210 
1211  fr_hmac_md5(calc_auth_vector, packet->data, packet->data_len,
1212  (uint8_t const *) secret, strlen(secret));
1213  if (fr_radius_digest_cmp(calc_auth_vector, msg_auth_vector,
1214  sizeof(calc_auth_vector)) != 0) {
1215  fr_strerror_printf("Received packet from %s with invalid Message-Authenticator! "
1216  "(Shared secret is incorrect.)",
1217  inet_ntop(packet->src_ipaddr.af,
1218  &packet->src_ipaddr.ipaddr,
1219  buffer, sizeof(buffer)));
1220  /* Silently drop packet, according to RFC 3579 */
1221  return -1;
1222  } /* else the message authenticator was good */
1223 
1224  /*
1225  * Reinitialize Authenticators.
1226  */
1227  memcpy(&ptr[2], msg_auth_vector, AUTH_VECTOR_LEN);
1228  memcpy(packet->data + 4, packet->vector, AUTH_VECTOR_LEN);
1229  break;
1230  } /* switch over the attributes */
1231 
1232  ptr += attrlen;
1233  length -= attrlen;
1234  } /* loop over the packet, sanity checking the attributes */
1235 
1236  /*
1237  * It looks like a RADIUS packet, but we don't know what it is
1238  * so can't validate the authenticators.
1239  */
1240  if ((packet->code == 0) || (packet->code >= FR_MAX_PACKET_CODE)) {
1241  fr_strerror_printf("Received Unknown packet code %d "
1242  "from client %s port %d: Cannot validate Request/Response Authenticator.",
1243  packet->code,
1244  inet_ntop(packet->src_ipaddr.af,
1245  &packet->src_ipaddr.ipaddr,
1246  buffer, sizeof(buffer)),
1247  packet->src_port);
1248  return -1;
1249  }
1250 
1251  /*
1252  * Calculate and/or verify Request or Response Authenticator.
1253  */
1254  switch (packet->code) {
1256  case PW_CODE_STATUS_SERVER:
1257  /*
1258  * The authentication vector is random
1259  * nonsense, invented by the client.
1260  */
1261  break;
1262 
1263  case PW_CODE_COA_REQUEST:
1266  if (calc_acctdigest(packet, secret) > 1) {
1267  fr_strerror_printf("Received %s packet "
1268  "from client %s with invalid Request Authenticator! "
1269  "(Shared secret is incorrect.)",
1270  fr_packet_codes[packet->code],
1271  inet_ntop(packet->src_ipaddr.af,
1272  &packet->src_ipaddr.ipaddr,
1273  buffer, sizeof(buffer)));
1274  return -1;
1275  }
1276  break;
1277 
1278  /* Verify the reply digest */
1279  case PW_CODE_ACCESS_ACCEPT:
1280  case PW_CODE_ACCESS_REJECT:
1285  case PW_CODE_COA_ACK:
1286  case PW_CODE_COA_NAK:
1287  rcode = calc_replydigest(packet, original, secret);
1288  if (rcode > 1) {
1289  fr_strerror_printf("Received %s packet "
1290  "from home server %s port %d with invalid Response Authenticator! "
1291  "(Shared secret is incorrect.)",
1292  fr_packet_codes[packet->code],
1293  inet_ntop(packet->src_ipaddr.af,
1294  &packet->src_ipaddr.ipaddr,
1295  buffer, sizeof(buffer)),
1296  packet->src_port);
1297  return -1;
1298  }
1299  break;
1300 
1301  default:
1302  fr_strerror_printf("Received Unknown packet code %d "
1303  "from client %s port %d: Cannot validate Request/Response Authenticator",
1304  packet->code,
1305  inet_ntop(packet->src_ipaddr.af,
1306  &packet->src_ipaddr.ipaddr,
1307  buffer, sizeof(buffer)),
1308  packet->src_port);
1309  return -1;
1310  }
1311 
1312  return 0;
1313 }
1314 
1315 /** Encode a packet
1316  *
1317  */
1318 int fr_radius_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
1319  char const *secret)
1320 {
1321  radius_packet_t *hdr;
1322  uint8_t *ptr;
1323  uint16_t total_length;
1324  int len;
1325  VALUE_PAIR const *vp;
1326  vp_cursor_t cursor;
1327  fr_radius_ctx_t encoder_ctx = { .packet = packet, .original = original, .secret = secret };
1328 
1329  /*
1330  * A 4K packet, aligned on 64-bits.
1331  */
1332  uint64_t data[MAX_PACKET_LEN / sizeof(uint64_t)];
1333 
1334  /*
1335  * Double-check some things based on packet code.
1336  */
1337  switch (packet->code) {
1338  case PW_CODE_ACCESS_ACCEPT:
1339  case PW_CODE_ACCESS_REJECT:
1341  if (!original) {
1342  fr_strerror_printf("ERROR: Cannot sign response packet without a request packet");
1343  return -1;
1344  }
1345  break;
1346 
1347  /*
1348  * These packet vectors start off as all zero.
1349  */
1352  case PW_CODE_COA_REQUEST:
1353  memset(packet->vector, 0, sizeof(packet->vector));
1354  break;
1355 
1356  default:
1357  break;
1358  }
1359 
1360  /*
1361  * Use memory on the stack, until we know how
1362  * large the packet will be.
1363  */
1364  hdr = (radius_packet_t *) data;
1365 
1366  /*
1367  * Build standard header
1368  */
1369  hdr->code = packet->code;
1370  hdr->id = packet->id;
1371 
1372  memcpy(hdr->vector, packet->vector, sizeof(hdr->vector));
1373 
1374  total_length = RADIUS_HDR_LEN;
1375 
1376  /*
1377  * Load up the configuration values for the user
1378  */
1379  ptr = hdr->data;
1380  packet->offset = 0;
1381 
1382  /*
1383  * Loop over the reply attributes for the packet.
1384  */
1385  fr_cursor_init(&cursor, &packet->vps);
1386  while ((vp = fr_cursor_current(&cursor))) {
1387  size_t last_len;
1388  char const *last_name = NULL;
1389 
1390  VERIFY_VP(vp);
1391 
1392  /*
1393  * Ignore non-wire attributes, but allow extended
1394  * attributes.
1395  *
1396  * @fixme We should be able to get rid of this check
1397  * and just look at da->flags.internal
1398  */
1399  if (vp->da->flags.internal || ((vp->da->vendor == 0) && (vp->da->attr >= 256))) {
1400 #ifndef NDEBUG
1401  /*
1402  * Permit the admin to send BADLY formatted
1403  * attributes with a debug build.
1404  */
1405  if (vp->da->attr == PW_RAW_ATTRIBUTE) {
1406  memcpy(ptr, vp->vp_octets, vp->vp_length);
1407  len = vp->vp_length;
1408  fr_cursor_next(&cursor);
1409  goto next;
1410  }
1411 #endif
1412  fr_cursor_next(&cursor);
1413  continue;
1414  }
1415 
1416  /*
1417  * Set the Message-Authenticator to the correct
1418  * length and initial value.
1419  */
1420  if (!vp->da->vendor && (vp->da->attr == PW_MESSAGE_AUTHENTICATOR)) {
1421  /*
1422  * Cache the offset to the
1423  * Message-Authenticator
1424  */
1425  packet->offset = total_length;
1426  last_len = 16;
1427  } else {
1428  last_len = vp->vp_length;
1429  }
1430  last_name = vp->da->name;
1431 
1432  len = fr_radius_encode_pair(ptr, ((uint8_t *)data) + sizeof(data) - ptr, &cursor, &encoder_ctx);
1433  if (len < 0) return -1;
1434 
1435  /*
1436  * Failed to encode the attribute, likely because
1437  * the packet is full.
1438  */
1439  if (len == 0) {
1440  if (last_len != 0) {
1441  fr_strerror_printf("WARNING: Failed encoding attribute %s\n", last_name);
1442  break;
1443  } else {
1444  fr_strerror_printf("WARNING: Skipping zero-length attribute %s\n", last_name);
1445  }
1446  }
1447 
1448 #ifndef NDEBUG
1449  next: /* Used only for Raw-Attribute */
1450 #endif
1451  ptr += len;
1452  total_length += len;
1453  } /* done looping over all attributes */
1454 
1455  /*
1456  * Fill in the rest of the fields, and copy the data over
1457  * from the local stack to the newly allocated memory.
1458  *
1459  * Yes, all this 'memcpy' is slow, but it means
1460  * that we only allocate the minimum amount of
1461  * memory for a request.
1462  */
1463  packet->data_len = total_length;
1464  packet->data = talloc_array(packet, uint8_t, packet->data_len);
1465  if (!packet->data) {
1466  fr_strerror_printf("Out of memory");
1467  return -1;
1468  }
1469 
1470  memcpy(packet->data, hdr, packet->data_len);
1471  hdr = (radius_packet_t *) packet->data;
1472 
1473  total_length = htons(total_length);
1474  memcpy(hdr->length, &total_length, sizeof(total_length));
1475 
1476  return 0;
1477 }
1478 
1479 /** Calculate/check digest, and decode radius attributes
1480  *
1481  * @return
1482  * - 0 on success
1483  * - -1 on decoding error.
1484  */
1485 int fr_radius_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
1486 {
1487  int packet_length;
1488  uint32_t num_attributes;
1489  uint8_t *ptr;
1490  radius_packet_t *hdr;
1491  VALUE_PAIR *head = NULL;
1492  vp_cursor_t cursor, out;
1493  fr_radius_ctx_t decoder_ctx = {
1494  .original = original,
1495  .packet = packet,
1496  .secret = secret
1497  };
1498  /*
1499  * Extract attribute-value pairs
1500  */
1501  hdr = (radius_packet_t *)packet->data;
1502  ptr = hdr->data;
1503  packet_length = packet->data_len - RADIUS_HDR_LEN;
1504  num_attributes = 0;
1505 
1506  fr_cursor_init(&cursor, &head);
1507 
1508  /*
1509  * Loop over the attributes, decoding them into VPs.
1510  */
1511  while (packet_length > 0) {
1512  ssize_t my_len;
1513 
1514  /*
1515  * This may return many VPs
1516  */
1517  my_len = fr_radius_decode_pair(packet, &cursor, fr_dict_root(fr_dict_internal), ptr, packet_length,
1518  &decoder_ctx);
1519  if (my_len < 0) {
1520  fr_pair_list_free(&head);
1521  return -1;
1522  }
1523 
1524  /*
1525  * Count the ones which were just added
1526  */
1527  while (fr_cursor_next(&cursor)) num_attributes++;
1528 
1529  /*
1530  * VSA's may not have been counted properly in
1531  * fr_radius_ok() above, as it is hard to count
1532  * then without using the dictionary. We
1533  * therefore enforce the limits here, too.
1534  */
1535  if ((fr_max_attributes > 0) && (num_attributes > fr_max_attributes)) {
1536  char host_ipaddr[INET6_ADDRSTRLEN];
1537 
1538  fr_pair_list_free(&head);
1539  fr_strerror_printf("Possible DoS attack from host %s: Too many attributes in request "
1540  "(received %d, max %d are allowed)",
1541  inet_ntop(packet->src_ipaddr.af,
1542  &packet->src_ipaddr.ipaddr,
1543  host_ipaddr, sizeof(host_ipaddr)),
1544  num_attributes, fr_max_attributes);
1545  return -1;
1546  }
1547 
1548  ptr += my_len;
1549  packet_length -= my_len;
1550  }
1551 
1552  fr_cursor_init(&out, &packet->vps);
1553  fr_cursor_last(&out); /* Move insertion point to the end of the list */
1554  fr_cursor_merge(&out, head);
1555 
1556  /*
1557  * Merge information from the outside world into our
1558  * random pool.
1559  */
1560  fr_rand_seed(packet->data, RADIUS_HDR_LEN);
1561 
1562  return 0;
1563 }
1564 
1565 /** Seed the random number generator
1566  *
1567  * May be called any number of times.
1568  */
1569 void fr_rand_seed(void const *data, size_t size)
1570 {
1571  uint32_t hash;
1572 
1573  /*
1574  * Ensure that the pool is initialized.
1575  */
1576  if (!fr_rand_initialized) {
1577  int fd;
1578 
1579  memset(&fr_rand_pool, 0, sizeof(fr_rand_pool));
1580 
1581  fd = open("/dev/urandom", O_RDONLY);
1582  if (fd >= 0) {
1583  size_t total;
1584  ssize_t this;
1585 
1586  total = 0;
1587  while (total < sizeof(fr_rand_pool.randrsl)) {
1588  this = read(fd, fr_rand_pool.randrsl,
1589  sizeof(fr_rand_pool.randrsl) - total);
1590  if ((this < 0) && (errno != EINTR)) break;
1591  if (this > 0) total += this;
1592  }
1593  close(fd);
1594  } else {
1595  fr_rand_pool.randrsl[0] = fd;
1596  fr_rand_pool.randrsl[1] = time(NULL);
1597  fr_rand_pool.randrsl[2] = errno;
1598  }
1599 
1600  fr_randinit(&fr_rand_pool, 1);
1601  fr_rand_pool.randcnt = 0;
1602  fr_rand_initialized = 1;
1603  }
1604 
1605  if (!data) return;
1606 
1607  /*
1608  * Hash the user data
1609  */
1610  hash = fr_rand();
1611  if (!hash) hash = fr_rand();
1612  hash = fr_hash_update(data, size, hash);
1613 
1614  fr_rand_pool.randmem[fr_rand_pool.randcnt] ^= hash;
1615 }
1616 
1617 
1618 /** Return a 32-bit random number
1619  *
1620  */
1621 uint32_t fr_rand(void)
1622 {
1623  uint32_t num;
1624 
1625  /*
1626  * Ensure that the pool is initialized.
1627  */
1628  if (!fr_rand_initialized) {
1629  fr_rand_seed(NULL, 0);
1630  }
1631 
1632  num = fr_rand_pool.randrsl[fr_rand_pool.randcnt++];
1633  if (fr_rand_pool.randcnt >= 256) {
1634  fr_rand_pool.randcnt = 0;
1635  fr_isaac(&fr_rand_pool);
1636  }
1637 
1638  return num;
1639 }
1640 
1641 
1642 /** Allocate a new RADIUS_PACKET
1643  *
1644  * @param ctx the context in which the packet is allocated. May be NULL if
1645  * the packet is not associated with a REQUEST.
1646  * @param new_vector if true a new request authenticator will be generated.
1647  * @return
1648  * - New RADIUS_PACKET.
1649  * - NULL on error.
1650  */
1651 RADIUS_PACKET *fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
1652 {
1653  RADIUS_PACKET *rp;
1654 
1655  rp = talloc_zero(ctx, RADIUS_PACKET);
1656  if (!rp) {
1657  fr_strerror_printf("out of memory");
1658  return NULL;
1659  }
1660  rp->id = -1;
1661  rp->offset = -1;
1662 
1663  if (new_vector) {
1664  int i;
1665  uint32_t hash, base;
1666 
1667  /*
1668  * Don't expose the actual contents of the random
1669  * pool.
1670  */
1671  base = fr_rand();
1672  for (i = 0; i < AUTH_VECTOR_LEN; i += sizeof(uint32_t)) {
1673  hash = fr_rand() ^ base;
1674  memcpy(rp->vector + i, &hash, sizeof(hash));
1675  }
1676  }
1677  fr_rand(); /* stir the pool again */
1678 
1679  return rp;
1680 }
1681 
1682 /** Allocate a new RADIUS_PACKET response
1683  *
1684  * @param ctx the context in which the packet is allocated. May be NULL if
1685  * the packet is not associated with a REQUEST.
1686  * @param packet The request packet.
1687  * @return
1688  * - New RADIUS_PACKET.
1689  * - NULL on error.
1690  */
1692 {
1693  RADIUS_PACKET *reply;
1694 
1695  if (!packet) return NULL;
1696 
1697  reply = fr_radius_alloc(ctx, false);
1698  if (!reply) return NULL;
1699 
1700  /*
1701  * Initialize the fields from the request.
1702  */
1703  reply->sockfd = packet->sockfd;
1704  reply->dst_ipaddr = packet->src_ipaddr;
1705  reply->src_ipaddr = packet->dst_ipaddr;
1706  reply->dst_port = packet->src_port;
1707  reply->src_port = packet->dst_port;
1708  reply->if_index = packet->if_index;
1709  reply->id = packet->id;
1710  reply->code = 0; /* UNKNOWN code */
1711  memcpy(reply->vector, packet->vector,
1712  sizeof(reply->vector));
1713  reply->vps = NULL;
1714  reply->data = NULL;
1715  reply->data_len = 0;
1716 
1717 #ifdef WITH_TCP
1718  reply->proto = packet->proto;
1719 #endif
1720  return reply;
1721 }
1722 
1723 
1724 /** Free a RADIUS_PACKET
1725  *
1726  */
1727 void fr_radius_free(RADIUS_PACKET **radius_packet_ptr)
1728 {
1730 
1731  if (!radius_packet_ptr || !*radius_packet_ptr) return;
1732  radius_packet = *radius_packet_ptr;
1733 
1734  VERIFY_PACKET(radius_packet);
1735 
1736  fr_pair_list_free(&radius_packet->vps);
1737 
1738  talloc_free(radius_packet);
1739  *radius_packet_ptr = NULL;
1740 }
1741 
1742 /** Duplicate a RADIUS_PACKET
1743  *
1744  * @param ctx the context in which the packet is allocated. May be NULL if
1745  * the packet is not associated with a REQUEST.
1746  * @param in The packet to copy
1747  * @return
1748  * - New RADIUS_PACKET.
1749  * - NULL on error.
1750  */
1751 RADIUS_PACKET *fr_radius_copy(TALLOC_CTX *ctx, RADIUS_PACKET const *in)
1752 {
1753  RADIUS_PACKET *out;
1754 
1755  out = fr_radius_alloc(ctx, false);
1756  if (!out) return NULL;
1757 
1758  /*
1759  * Bootstrap by copying everything.
1760  */
1761  memcpy(out, in, sizeof(*out));
1762 
1763  /*
1764  * Then reset necessary fields
1765  */
1766  out->sockfd = -1;
1767 
1768  out->data = NULL;
1769  out->data_len = 0;
1770 
1771  out->vps = fr_pair_list_copy(out, in->vps);
1772  out->offset = 0;
1773 
1774  return out;
1775 }
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
Definition: pair.c:544
int sockfd
Socket this packet was read from.
Definition: libradius.h:147
static int sockfd
Definition: radclient.c:59
int fr_radius_sign(RADIUS_PACKET *packet, RADIUS_PACKET const *original, char const *secret)
Sign a previously encoded packet.
Definition: radius.c:389
int id
Packet ID (used to link requests/responses).
Definition: libradius.h:154
struct timeval timestamp
When we received the packet.
Definition: libradius.h:159
ssize_t udp_recv_peek(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Peek at the header of a UDP packet.
Definition: udp.c:125
#define FR_MAX_PACKET_CODE
Definition: libradius.h:370
int fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
Encode a data structure into a RADIUS attribute.
VALUE_PAIR * fr_cursor_last(vp_cursor_t *cursor)
Wind cursor to the last pair in the list.
Definition: cursor.c:126
RFC2865 - Access-Challenge.
Definition: radius.h:102
uint8_t id
Definition: radius.c:42
#define UDP_FLAGS_NONE
Definition: udp.h:38
RADIUS_PACKET * radius_packet(REQUEST *request, pair_lists_t list_name)
Resolve a list to the RADIUS_PACKET holding the HEAD pointer for a VALUE_PAIR list.
Definition: tmpl.c:279
RADIUS_PACKET * fr_radius_alloc_reply(TALLOC_CTX *ctx, RADIUS_PACKET *packet)
Allocate a new RADIUS_PACKET response.
Definition: radius.c:1691
decode_fail_t
Definition: libradius.h:173
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
char const * fr_packet_codes[FR_MAX_PACKET_CODE]
Definition: radius.c:101
#define FR_DEBUG_STRERROR_PRINTF
Definition: radius.c:51
FILE * fr_log_fp
Definition: radius.c:81
#define VERIFY_VP(_x)
Definition: pair.h:44
void fr_md5_init(FR_MD5_CTX *ctx)
Initialise a new MD5 context.
Definition: md5.c:84
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
FR_NAME_NUMBER const fr_request_types[]
Definition: radius.c:52
void fr_rand_seed(void const *data, size_t size)
Seed the random number generator.
Definition: radius.c:1569
RADIUS_PACKET * fr_radius_copy(TALLOC_CTX *ctx, RADIUS_PACKET const *in)
Duplicate a RADIUS_PACKET.
Definition: radius.c:1751
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
static int calc_acctdigest(RADIUS_PACKET *packet, char const *secret)
Validates the requesting client NAS.
Definition: radius.c:595
void fr_radius_make_secret(uint8_t *digest, uint8_t const *vector, char const *secret, uint8_t const *value)
Build an encrypted secret value to return in a reply packet.
Definition: radius.c:272
void fr_randinit(fr_randctx *ctx, int flag)
Definition: isaac.c:65
static void print_hex_data(uint8_t const *ptr, int attrlen, int depth)
Definition: radius.c:84
uint8_t length
Definition: proto_bfd.c:203
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: radius.c:1621
uint8_t * data
Packet data (body).
Definition: libradius.h:160
RFC3575/RFC5176 - Disconnect-Ack (positive)
Definition: radius.h:106
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
uint16_t src_port
Src port of packet.
Definition: libradius.h:151
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Definition: libradius.h:150
int fr_debug_lvl
Definition: misc.c:40
#define MAX_PACKET_LEN
Definition: radius.c:67
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
fr_dict_attr_flags_t flags
Flags.
Definition: dict.h:88
static ssize_t rad_recvfrom(int sockfd, RADIUS_PACKET *packet, int flags)
Wrapper for recvfrom, which handles recvfromto, IPv6, and all possible combinations.
Definition: radius.c:363
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:124
RFC2866 - Accounting-Response.
Definition: radius.h:96
uint32_t fr_hash_update(void const *data, size_t size, uint32_t hash)
Definition: hash.c:761
void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen) CC_BOUNDED(__string__
RFC2865 - Access-Reject.
Definition: radius.h:94
RFC3575/RFC5176 - CoA-Ack (positive)
Definition: radius.h:109
int af
Address family.
Definition: inet.h:42
RFC2865 - Access-Request.
Definition: radius.h:92
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
static char const tabs[]
Definition: command.c:894
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
Definition: pair.c:1394
uint8_t code
Definition: radius.c:41
#define AUTH_VECTOR_LEN
Definition: libradius.h:118
static _fr_thread_local bool fr_rand_initialized
Definition: radius.c:99
void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len) CC_BOUNDED(__minbytes__
void fr_printf_log(char const *fmt,...)
Definition: radius.c:156
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *vp)
Merges multiple VALUE_PAIR into the cursor.
Definition: cursor.c:394
RFC2866 - Accounting-Request.
Definition: radius.h:95
#define STRINGIFY(x)
Definition: build.h:34
int fr_radius_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
Verify the Request/Response Authenticator (and Message-Authenticator if present) of a packet...
Definition: radius.c:1144
ssize_t udp_recv(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t *dst_ipaddr, uint16_t *dst_port, int *if_index, struct timeval *when)
unsigned int attr
Attribute number.
Definition: dict.h:79
ssize_t udp_send(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t src_port, int if_index, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port)
union fr_ipaddr_t::@1 ipaddr
RFC3575/RFC5176 - CoA-Nak (not willing to perform)
Definition: radius.h:110
unsigned int code
Packet code (type).
Definition: libradius.h:155
uint8_t length[2]
Definition: radius.c:43
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
Definition: radius.c:1651
RFC2865 - Access-Accept.
Definition: radius.h:93
unsigned int vendor
Vendor that defines this attribute.
Definition: dict.h:78
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
uint32_t fr_max_attributes
Definition: radius.c:80
VALUE_PAIR * fr_cursor_current(vp_cursor_t *cursor)
Return the VALUE_PAIR the cursor current points to.
Definition: cursor.c:304
#define UDP_FLAGS_PEEK
Definition: udp.h:40
void fr_isaac(fr_randctx *ctx)
Definition: isaac.c:29
#define VERIFY_PACKET(_x)
Definition: pair.h:46
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition: dict.h:44
RFC3575/RFC5176 - CoA-Request.
Definition: radius.h:108
uint8_t vector[AUTH_VECTOR_LEN]
RADIUS authentication vector.
Definition: libradius.h:157
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
bool fr_radius_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
See if the data pointed to by PTR is a valid RADIUS packet.
Definition: radius.c:731
Packet code has not been set.
Definition: radius.h:91
int if_index
Index of receiving interface.
Definition: libradius.h:148
RADIUS_PACKET const * original
Definition: libradius.h:268
ssize_t fr_radius_len(uint8_t const *data, size_t data_len)
See how big of a packet is in the buffer.
Definition: radius.c:679
struct radius_packet_t radius_packet_t
int fr_radius_send(RADIUS_PACKET *packet, RADIUS_PACKET const *original, char const *secret)
Reply to the request.
Definition: radius.c:506
uint32_t rounds
for State[0]
Definition: libradius.h:165
char name[1]
Attribute name.
Definition: dict.h:89
uint8_t data[]
Definition: eap_pwd.h:625
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx)
Create a "normal" VALUE_PAIR from the given data.
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
Definition: cursor.c:263
size_t data_len
Length of packet data.
Definition: libradius.h:161
int fr_radius_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original, char const *secret)
Encode a packet.
Definition: radius.c:1318
static char const * secret
Definition: radclient.c:44
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
#define RADIUS_HDR_LEN
Definition: net.h:69
ssize_t offset
Definition: libradius.h:163
int fr_radius_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL digest.
Definition: radius.c:578
RFC2865/RFC5997 - Status Server (request)
Definition: radius.h:103
void void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) CC_BOUNDED(__minbytes__
IPv4/6 prefix.
Definition: inet.h:41
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
RADIUS_PACKET const * packet
Definition: libradius.h:267
ssize_t fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code)
Basic validation of RADIUS packet header.
Definition: radius.c:299
RFC3575/RFC5176 - Disconnect-Nak (not willing to perform)
Definition: radius.h:107
#define RCSID(id)
Definition: build.h:135
uint8_t vector[AUTH_VECTOR_LEN]
Definition: radius.c:44
RADIUS_PACKET * fr_radius_recv(TALLOC_CTX *ctx, int fd, int flags)
Receive UDP client requests, and fill in the basics of a RADIUS_PACKET structure. ...
Definition: radius.c:1050
fr_dict_t * fr_dict_internal
Internal server dictionary.
Definition: dict.c:81
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict.c:2339
void fr_radius_free(RADIUS_PACKET **radius_packet_ptr)
Free a RADIUS_PACKET.
Definition: radius.c:1727
void udp_recv_discard(int sockfd)
Discard the next UDP packet.
Definition: udp.c:105
uint8_t data[1]
Definition: radius.c:45
int fr_radius_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
Calculate/check digest, and decode radius attributes.
Definition: radius.c:1485
static int calc_replydigest(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
Validates the requesting client NAS.
Definition: radius.c:629
RFC3575/RFC5176 - Disconnect-Request.
Definition: radius.h:105
void fr_radius_print_hex(RADIUS_PACKET *packet)
Definition: radius.c:172
static _fr_thread_local fr_randctx fr_rand_pool
A pool of pre-generated random integers.
Definition: radius.c:98