The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
base.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: 7b7974ebc5b0a3961e4638d6abdc0ee3f896a955 $
19  *
20  * @file protocols/tacacs/encode.c
21  * @brief Low-Level TACACS+ encode functions
22  *
23  * @copyright 2017 The FreeRADIUS server project
24  * @copyright 2017 Network RADIUS SAS (legal@networkradius.com)
25  */
26 #include <freeradius-devel/util/net.h>
27 #include <freeradius-devel/util/md5.h>
28 #include <freeradius-devel/util/struct.h>
29 
30 #include "tacacs.h"
31 #include "attrs.h"
32 
34 
36 
39  { .out = &dict_tacacs, .proto = "tacacs" },
40 
41  { NULL }
42 };
43 
70 
78 
81  { .out = &attr_tacacs_accounting_flags, .name = "Accounting-Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
82  { .out = &attr_tacacs_accounting_status, .name = "Accounting-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
83  { .out = &attr_tacacs_action, .name = "Action", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
84  { .out = &attr_tacacs_authentication_flags, .name = "Authentication-Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
85  { .out = &attr_tacacs_authentication_continue_flags, .name = "Authentication-Continue-Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
86  { .out = &attr_tacacs_authentication_method, .name = "Authentication-Method", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
87  { .out = &attr_tacacs_authentication_service, .name = "Authentication-Service", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
88  { .out = &attr_tacacs_authentication_status, .name = "Authentication-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
89  { .out = &attr_tacacs_authentication_type, .name = "Authentication-Type", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
90  { .out = &attr_tacacs_authorization_status, .name = "Authorization-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
91  { .out = &attr_tacacs_argument_list, .name = "Argument-List", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
92  { .out = &attr_tacacs_client_port, .name = "Client-Port", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
93  { .out = &attr_tacacs_data, .name = "Data", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
94  { .out = &attr_tacacs_flags, .name = "Packet.Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
95  { .out = &attr_tacacs_length, .name = "Packet.Length", .type = FR_TYPE_UINT32, .dict = &dict_tacacs },
96  { .out = &attr_tacacs_packet, .name = "Packet", .type = FR_TYPE_STRUCT, .dict = &dict_tacacs },
97  { .out = &attr_tacacs_packet_body_type, .name = "Packet-Body-Type", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
98  { .out = &attr_tacacs_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_tacacs },
99  { .out = &attr_tacacs_privilege_level, .name = "Privilege-Level", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
100  { .out = &attr_tacacs_remote_address, .name = "Remote-Address", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
101  { .out = &attr_tacacs_sequence_number, .name = "Packet.Sequence-Number", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
102  { .out = &attr_tacacs_server_message, .name = "Server-Message", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
103  { .out = &attr_tacacs_session_id, .name = "Packet.Session-Id", .type = FR_TYPE_UINT32, .dict = &dict_tacacs },
104  { .out = &attr_tacacs_user_message, .name = "User-Message", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
105  { .out = &attr_tacacs_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
106  { .out = &attr_tacacs_version_major, .name = "Packet.Version-Major", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
107  { .out = &attr_tacacs_version_minor, .name = "Packet.Version-Minor", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
108 
109  { .out = &attr_tacacs_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
110  { .out = &attr_tacacs_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
111  { .out = &attr_tacacs_chap_password, .name = "CHAP-Password", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
112  { .out = &attr_tacacs_chap_challenge, .name = "CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
113  { .out = &attr_tacacs_mschap_response, .name = "MS-CHAP-Response", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
114  { .out = &attr_tacacs_mschap2_response, .name = "MS-CHAP2-Response", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
115  { .out = &attr_tacacs_mschap_challenge, .name = "MS-CHAP-Challenge", .type = FR_TYPE_OCTETS, .dict = &dict_tacacs },
116  { NULL }
117 };
118 
120  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_START] = "Authentication-Start",
121  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_PASS] = "Authentication-Pass",
122  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_FAIL] = "Authentication-Fail",
123  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETDATA] = "Authentication-GetData",
124  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETUSER] = "Authentication-GetUser",
125  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETPASS] = "Authentication-GetPass",
126  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_RESTART] = "Authentication-Restart",
127  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_ERROR] = "Authentication-Error",
128 
129  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_CONTINUE] = "Authentication-Continue",
130  [FR_PACKET_TYPE_VALUE_AUTHENTICATION_CONTINUE_ABORT] = "Authentication-Continue-Abort",
131 
132  [FR_PACKET_TYPE_VALUE_AUTHORIZATION_REQUEST] = "Authorization-Request",
133  [FR_PACKET_TYPE_VALUE_AUTHORIZATION_PASS_ADD] = "Authorization-Pass-Add",
134  [FR_PACKET_TYPE_VALUE_AUTHORIZATION_PASS_REPLACE] = "Authorization-Pass-Replace",
135  [FR_PACKET_TYPE_VALUE_AUTHORIZATION_FAIL] = "Authorization-Fail",
136  [FR_PACKET_TYPE_VALUE_AUTHORIZATION_ERROR] = "Authorization-Error",
137 
138  [FR_PACKET_TYPE_VALUE_ACCOUNTING_REQUEST] = "Accounting-Request",
139  [FR_PACKET_TYPE_VALUE_ACCOUNTING_SUCCESS] = "Accounting-Success",
140  [FR_PACKET_TYPE_VALUE_ACCOUNTING_ERROR] = "Accounting-Error",
141 };
142 
143 
145 {
146  if (instance_count > 0) {
147  instance_count++;
148  return 0;
149  }
150 
151  instance_count++;
152 
154  fail:
155  instance_count--;
156  return -1;
157  }
158 
161  goto fail;
162  }
163 
164  return 0;
165 }
166 
168 {
170 
171  if (--instance_count > 0) return;
172 
174 }
175 
176 /** XOR the body based on the secret key.
177  *
178  * This function encrypts (or decrypts) TACACS+ packets, and sets the "encrypted" flag.
179  */
180 int fr_tacacs_body_xor(fr_tacacs_packet_t const *pkt, uint8_t *body, size_t body_len, char const *secret, size_t secret_len)
181 {
183  uint8_t *buf, *end;
184  int pad_offset;
185 
186  /*
187  * Do some basic sanity checks.
188  */
189  if (!secret_len) {
190  fr_strerror_const("Failed to encrypt/decrept the packet, as the secret has zero length.");
191  return -1;
192  }
193 
194  pad_offset = sizeof(pkt->hdr.session_id) + secret_len + sizeof(pkt->hdr.version) + sizeof(pkt->hdr.seq_no);
195 
196  /* MD5_1 = MD5{session_id, key, version, seq_no} */
197  /* MD5_n = MD5{session_id, key, version, seq_no, MD5_n-1} */
198  buf = talloc_array(NULL, uint8_t, pad_offset + MD5_DIGEST_LENGTH);
199  if (!buf) return -1;
200 
201  memcpy(&buf[0], &pkt->hdr.session_id, sizeof(pkt->hdr.session_id));
202  memcpy(&buf[sizeof(pkt->hdr.session_id)], secret, secret_len);
203  memcpy(&buf[sizeof(pkt->hdr.session_id) + secret_len], &pkt->hdr.version, sizeof(pkt->hdr.version));
204  memcpy(&buf[sizeof(pkt->hdr.session_id) + secret_len + sizeof(pkt->hdr.version)], &pkt->hdr.seq_no, sizeof(pkt->hdr.seq_no));
205 
206  fr_md5_calc(pad, buf, pad_offset);
207 
208  end = body + body_len;
209  while (body < end) {
210  size_t i;
211 
212  for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
213  *body ^= pad[i];
214 
215  if (++body == end) goto done;
216  }
217 
218  memcpy(&buf[pad_offset], pad, MD5_DIGEST_LENGTH);
219  fr_md5_calc(pad, buf, pad_offset + MD5_DIGEST_LENGTH);
220  }
221 
222 done:
223  talloc_free(buf);
224 
225  return 0;
226 }
227 
228 /**
229  * Return how long a TACACS+ packet is
230  *
231  * Note that we only look at the 12 byte packet header. We don't
232  * (yet) do validation on authentication / authorization /
233  * accounting headers. The packet may still be determined later
234  * to be invalid.
235  *
236  * @param buffer to check
237  * @param buffer_len length of the buffer
238  * @return
239  * >0 size of the TACACS+ packet. We want. MAY be larger than "buffer_len"
240  * <=0 error, packet should be discarded.
241  */
242 ssize_t fr_tacacs_length(uint8_t const *buffer, size_t buffer_len)
243 {
244  fr_tacacs_packet_t const *pkt = (fr_tacacs_packet_t const *) buffer;
245  size_t length, want;
246 
247  /*
248  * Check that we have a full TACACS+ header before
249  * decoding anything.
250  */
251  if (buffer_len < sizeof(pkt->hdr)) {
252  return sizeof(pkt->hdr);
253  }
254 
255  /*
256  * TACACS major / minor version MUST be 12.0 or 12.1
257  */
258  if (!((buffer[0] == 0xc0) || (buffer[0] == 0xc1))) {
259  fr_strerror_printf("Unsupported TACACS+ version %02x", buffer[0]);
260  return -1;
261  }
262 
263  /*
264  * There's no reason to accept 64K TACACS+ packets.
265  */
266  if ((buffer[8] != 0) || (buffer[9] != 0)) {
267  fr_strerror_const("Packet is too large. Our limit is 64K");
268  return -1;
269  }
270 
271  /*
272  * There are only 3 types of packets which are supported.
273  */
274  if (!((pkt->hdr.type == FR_TAC_PLUS_AUTHEN) ||
275  (pkt->hdr.type == FR_TAC_PLUS_AUTHOR) ||
276  (pkt->hdr.type == FR_TAC_PLUS_ACCT))) {
277  fr_strerror_printf("Unknown packet type %u", pkt->hdr.type);
278  return -1;
279  }
280 
281  length = sizeof(pkt->hdr) + ntohl(pkt->hdr.length);
282 
283  if (buffer_len < length) return length;
284 
285  /*
286  * We want at least the headers for the various packet
287  * types. Note that we do NOT check the lengths in the
288  * headers against buffer / buffer_len. That process is
289  * complex and error-prone. It's best to leave it in one
290  * place: fr_tacacs_decode().
291  */
292  switch (pkt->hdr.type) {
293  default:
294  fr_assert(0); /* should have been caught above */
295  return -1;
296 
297  case FR_TAC_PLUS_AUTHEN:
299  want = sizeof(pkt->hdr) + sizeof(pkt->authen_start);
300 
301  } else if (packet_is_authen_continue(pkt)) {
302  want = sizeof(pkt->hdr) + sizeof(pkt->authen_cont);
303 
304  } else {
306  want = sizeof(pkt->hdr) + sizeof(pkt->authen_reply);
307  }
308  break;
309 
310  case FR_TAC_PLUS_AUTHOR:
311  if (packet_is_author_request(pkt)) {
312  want = sizeof(pkt->hdr) + sizeof(pkt->author_req);
313  } else {
315  want = sizeof(pkt->hdr) + sizeof(pkt->author_reply);
316  }
317  break;
318 
319  case FR_TAC_PLUS_ACCT:
320  if (packet_is_acct_request(pkt)) {
321  want = sizeof(pkt->hdr) + sizeof(pkt->acct_req);
322  } else {
324  want = sizeof(pkt->hdr) + sizeof(pkt->acct_reply);
325  }
326  break;
327  }
328 
329  if (want > length) {
330  fr_strerror_printf("Packet is too small. Want %zu, got %zu", want, length);
331  return -1;
332  }
333 
334  return length;
335 }
336 
337 static void print_hex(fr_log_t const *log, char const *file, int line, char const *prefix, uint8_t const *data, size_t datalen)
338 {
339  if (!datalen) return;
340 
341  fr_log_hex(log, L_DBG, file, line, data, datalen, "%s", prefix);
342 }
343 
344 static void print_ascii(fr_log_t const *log, char const *file, int line, char const *prefix, uint8_t const *data, size_t datalen)
345 {
346  uint8_t const *p;
347 
348  if (!datalen) return;
349 
350  if (datalen > 80) {
351  hex:
352  print_hex(log, file, line, prefix, data, datalen);
353  return;
354  }
355 
356  for (p = data; p < (data + datalen); p++) {
357  if ((*p < 0x20) || (*p > 0x80)) goto hex;
358  }
359 
360  fr_log(log, L_DBG, file, line, "%s %.*s", prefix, (int) datalen, (char const *) data);
361 }
362 
363 #define CHECK(_length) do { \
364  size_t plen = _length; \
365  if ((size_t) (end - p) < plen) { \
366  fr_log_hex(log, L_DBG, file, line, p, end - p, "%s", " TRUNCATED "); \
367  return; \
368  } \
369  data = p; \
370  data_len = plen; \
371  p += plen; \
372  } while (0)
373 
374 #undef ASCII
375 #define ASCII(_prefix, _field) do { \
376  CHECK(_field); \
377  print_ascii(log, file, line, _prefix, data, data_len); \
378  } while (0)
379 
380 #undef HEXIT
381 #define HEXIT(_prefix, _field) do { \
382  CHECK(_field); \
383  print_hex(log, file, line, _prefix, data, data_len); \
384  } while (0)
385 
386 #define PRINT(_fmt, ...) fr_log(log, L_DBG, file, line, _fmt, ## __VA_ARGS__)
387 
388 static void print_args(fr_log_t const *log, char const *file, int line, size_t arg_cnt, uint8_t const *argv, uint8_t const *start, uint8_t const *end)
389 {
390  size_t i, data_len;
391  uint8_t const *p;
392  uint8_t const *data;
393  char prefix[64];
394 
395  if (argv + arg_cnt > end) {
396  PRINT(" ARG cnt overflows packet");
397  return;
398  }
399 
400  p = start;
401  for (i = 0; i < arg_cnt; i++) {
402  if (p == end) {
403  PRINT(" ARG[%zu] is at EOF", i);
404  return;
405  }
406 
407  if ((end - p) < argv[i]) {
408  PRINT(" ARG[%zu] overflows packet", i);
409  print_hex(log, file, line, " ", p, end - p);
410  return;
411  }
412 
413  snprintf(prefix, sizeof(prefix), " arg[%zu] ", i);
414  prefix[21] = '\0';
415 
416  ASCII(prefix, argv[i]);
417  }
418 }
419 
420 void _fr_tacacs_packet_log_hex(fr_log_t const *log, fr_tacacs_packet_t const *packet, size_t packet_len, char const *file, int line)
421 {
422  size_t length, data_len;
423  uint8_t const *p = (uint8_t const *) packet;
424  uint8_t const *hdr, *end, *args;
425  uint8_t const *data;
426 
427  end = ((uint8_t const *) packet) + packet_len;
428 
429  if (packet_len < 12) {
430  print_hex(log, file, line, "header ", p, packet_len);
431  return;
432  }
433 
434  /*
435  * It has to be at least 12 bytes long.
436  */
437  PRINT(" major %u", (p[0] & 0xf0) >> 4);
438  PRINT(" minor %u", (p[0] & 0x0f));
439 
440  PRINT(" type %02x", p[1]);
441  PRINT(" seq_no %02x", p[2]);
442  PRINT(" flags %02x", p[3]);
443 
444  PRINT(" sessid %08x", fr_nbo_to_uint32(p + 4));
445  PRINT(" length %08x", fr_nbo_to_uint32(p + 8));
446 
447  PRINT(" body");
448  length = fr_nbo_to_uint32(p + 8);
449 
450  if ((p[3] & 0x01) == 0) {
451  PRINT(" ... encrypted ...");
452  return;
453  }
454 
455  if (length > 65535) {
456  PRINT(" TOO LARGE");
457  return;
458  }
459 
460  p += 12;
461  hdr = p;
462 
463  if ((p + length) != end) {
464  PRINT("length field does not match input packet length %08lx", packet_len - 12);
465  return;
466  }
467 
468 #define REQUIRE(_length) do { \
469  size_t plen = _length; \
470  if ((size_t) (end - hdr) < plen) { \
471  print_hex(log, file, line, " TRUNCATED ", hdr, end - hdr); \
472  return; \
473  } \
474  p = hdr + plen; \
475  } while (0)
476 
477  switch (packet->hdr.type) {
478  default:
479  print_hex(log, file, line, " data ", p, length);
480  return;
481 
482  case FR_TAC_PLUS_AUTHEN:
483  if (packet_is_authen_start_request(packet)) {
484  PRINT(" authentication-start");
485 
486  REQUIRE(8);
487 
488  PRINT(" action %02x", hdr[0]);
489  PRINT(" priv_lvl %02x", hdr[1]);
490  PRINT(" authen_type %02x", hdr[2]);
491  PRINT(" authen_service %02x", hdr[3]);
492  PRINT(" user_len %02x", hdr[4]);
493  PRINT(" port_len %02x", hdr[5]);
494  PRINT(" rem_addr_len %02x", hdr[6]);
495  PRINT(" data_len %02x", hdr[7]);
496 
497  ASCII(" user ", hdr[4]);
498  ASCII(" port ", hdr[5]);
499  ASCII(" rem_addr ", hdr[6]);
500  HEXIT(" data ", hdr[7]); /* common auth flows */
501 
502  } else if (packet_is_authen_continue(packet)) {
503  PRINT(" authentication-continue");
504 
505  REQUIRE(5);
506 
507  PRINT(" user_msg_len %04x", fr_nbo_to_uint16(hdr));
508  PRINT(" data_len %04x", fr_nbo_to_uint16(hdr + 2));
509  PRINT(" flags %02x", hdr[4]);
510 
511  ASCII(" user_msg ", fr_nbo_to_uint16(hdr));
512  HEXIT(" data ", fr_nbo_to_uint16(hdr + 2));
513 
514  } else {
516 
517  PRINT(" authentication-reply");
518 
519  REQUIRE(6);
520 
521  PRINT(" status %02x", hdr[0]);
522  PRINT(" flags %02x", hdr[1]);
523  PRINT(" server_msg_len %04x", fr_nbo_to_uint16(hdr + 2));
524  PRINT(" data_len %04x", fr_nbo_to_uint16(hdr + 4));
525 
526  ASCII(" server_msg ", fr_nbo_to_uint16(hdr + 2));
527  HEXIT(" data ", fr_nbo_to_uint16(hdr + 4));
528  }
529  break;
530 
531  case FR_TAC_PLUS_AUTHOR:
532  if (packet_is_author_request(packet)) {
533  PRINT(" authorization-request");
534  REQUIRE(8);
535 
536  PRINT(" auth_method %02x", hdr[0]);
537  PRINT(" priv_lvl %02x", hdr[1]);
538  PRINT(" authen_type %02x", hdr[2]);
539  PRINT(" authen_service %02x", hdr[3]);
540  PRINT(" user_len %02x", hdr[4]);
541  PRINT(" port_len %02x", hdr[5]);
542  PRINT(" rem_addr_len %02x", hdr[6]);
543  PRINT(" arg_cnt %02x", hdr[7]);
544  args = p;
545 
546  HEXIT(" argc ", hdr[7]);
547  ASCII(" user ", hdr[4]);
548  ASCII(" port ", hdr[5]);
549  ASCII(" rem_addr ", hdr[6]);
550 
551  print_args(log, file, line, hdr[7], args, p, end);
552 
553  } else {
554  PRINT(" authorization-reply");
555 
557 
558  REQUIRE(6);
559 
560  PRINT(" status %02x", hdr[0]);
561  PRINT(" arg_cnt %02x", hdr[1]);
562  PRINT(" server_msg_len %04x", fr_nbo_to_uint16(hdr + 2));
563  PRINT(" data_len %04x", fr_nbo_to_uint16(hdr + 4));
564  args = p;
565 
566  HEXIT(" argc ", hdr[1]);
567  ASCII(" server_msg ", fr_nbo_to_uint16(hdr + 2));
568  ASCII(" data ", fr_nbo_to_uint16(hdr + 4));
569 
570  print_args(log, file, line, hdr[1], args, p, end);
571  }
572  break;
573 
574  case FR_TAC_PLUS_ACCT:
575  if (packet_is_acct_request(packet)) {
576  PRINT(" accounting-request");
577 
578  REQUIRE(9);
579 
580  PRINT(" flags %02x", hdr[0]);
581  PRINT(" auth_method %02x", hdr[1]);
582  PRINT(" priv_lvl %02x", hdr[2]);
583  PRINT(" authen_type %02x", hdr[3]);
584  PRINT(" authen_service %02x", hdr[4]);
585  PRINT(" user_len %02x", hdr[5]);
586  PRINT(" port_len %02x", hdr[6]);
587  PRINT(" rem_addr_len %02x", hdr[7]);
588  PRINT(" arg_cnt %02x", hdr[8]);
589  args = p;
590 
591  HEXIT(" argc ", hdr[8]);
592  ASCII(" user ", hdr[5]);
593  ASCII(" port ", hdr[6]);
594  ASCII(" rem_addr ", hdr[7]);
595 
596  print_args(log, file, line, hdr[8], args, p, end);
597  } else {
598  PRINT(" accounting-reply");
600 
601  PRINT(" authentication-reply");
602 
603  REQUIRE(5);
604 
605  PRINT(" server_msg_len %04x", fr_nbo_to_uint16(hdr));
606  PRINT(" data_len %04x", fr_nbo_to_uint16(hdr + 2));
607  PRINT(" status %02x", hdr[0]);
608 
609  ASCII(" server_msg ", fr_nbo_to_uint16(hdr));
610  HEXIT(" data ", fr_nbo_to_uint16(hdr + 2));
611  }
612  break;
613  }
614 
615  fr_assert(p == end);
616 }
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
va_list args
Definition: acutest.h:770
int const char int line
Definition: acutest.h:702
#define fr_dict_autofree(_to_free)
Definition: dict.h:674
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition: dict_util.c:3647
#define fr_dict_autoload(_to_load)
Definition: dict.h:671
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
talloc_free(reap)
void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line, uint8_t const *data, size_t data_len, char const *line_prefix_fmt,...)
Print out hex block.
Definition: log.c:800
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition: log.c:599
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
#define MD5_DIGEST_LENGTH
Definition: merged_model.c:248
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Perform a single digest operation on a single input buffer.
Definition: merged_model.c:251
unsigned char uint8_t
Definition: merged_model.c:30
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition: nbo.h:137
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
Definition: nbo.h:158
fr_dict_attr_t const * attr_tacacs_authentication_flags
Definition: base.c:47
int fr_tacacs_body_xor(fr_tacacs_packet_t const *pkt, uint8_t *body, size_t body_len, char const *secret, size_t secret_len)
XOR the body based on the secret key.
Definition: base.c:180
fr_dict_attr_t const * attr_tacacs_length
Definition: base.c:58
void _fr_tacacs_packet_log_hex(fr_log_t const *log, fr_tacacs_packet_t const *packet, size_t packet_len, char const *file, int line)
Definition: base.c:420
fr_dict_attr_autoload_t libfreeradius_tacacs_dict_attr[]
Definition: base.c:80
ssize_t fr_tacacs_length(uint8_t const *buffer, size_t buffer_len)
Definition: base.c:242
fr_dict_attr_t const * attr_tacacs_authentication_continue_flags
Definition: base.c:48
fr_dict_attr_t const * attr_tacacs_user_message
Definition: base.c:67
char const * fr_tacacs_packet_names[FR_TACACS_CODE_MAX]
Definition: base.c:119
static uint32_t instance_count
Definition: base.c:33
static void print_args(fr_log_t const *log, char const *file, int line, size_t arg_cnt, uint8_t const *argv, uint8_t const *start, uint8_t const *end)
Definition: base.c:388
void fr_tacacs_global_free(void)
Definition: base.c:167
fr_dict_t const * dict_tacacs
Definition: base.c:35
static void print_hex(fr_log_t const *log, char const *file, int line, char const *prefix, uint8_t const *data, size_t datalen)
Definition: base.c:337
fr_dict_attr_t const * attr_tacacs_argument_list
Definition: base.c:54
fr_dict_attr_t const * attr_tacacs_chap_challenge
Definition: base.c:74
int fr_tacacs_global_init(void)
Definition: base.c:144
fr_dict_attr_t const * attr_tacacs_user_password
Definition: base.c:72
fr_dict_attr_t const * attr_tacacs_session_id
Definition: base.c:66
fr_dict_attr_t const * attr_tacacs_server_message
Definition: base.c:65
#define PRINT(_fmt,...)
Definition: base.c:386
fr_dict_attr_t const * attr_tacacs_version_major
Definition: base.c:68
#define HEXIT(_prefix, _field)
Definition: base.c:381
fr_dict_autoload_t libfreeradius_tacacs_dict[]
Definition: base.c:38
fr_dict_attr_t const * attr_tacacs_privilege_level
Definition: base.c:62
fr_dict_attr_t const * attr_tacacs_mschap_challenge
Definition: base.c:77
fr_dict_attr_t const * attr_tacacs_authentication_type
Definition: base.c:52
fr_dict_attr_t const * attr_tacacs_mschap_response
Definition: base.c:75
fr_dict_attr_t const * attr_tacacs_accounting_status
Definition: base.c:45
static void print_ascii(fr_log_t const *log, char const *file, int line, char const *prefix, uint8_t const *data, size_t datalen)
Definition: base.c:344
fr_dict_attr_t const * attr_tacacs_version_minor
Definition: base.c:69
fr_dict_attr_t const * attr_tacacs_mschap2_response
Definition: base.c:76
#define REQUIRE(_length)
fr_dict_attr_t const * attr_tacacs_authentication_service
Definition: base.c:50
fr_dict_attr_t const * attr_tacacs_authentication_status
Definition: base.c:51
fr_dict_attr_t const * attr_tacacs_chap_password
Definition: base.c:73
fr_dict_attr_t const * attr_tacacs_packet
Definition: base.c:59
fr_dict_attr_t const * attr_tacacs_packet_body_type
Definition: base.c:60
fr_dict_attr_t const * attr_tacacs_client_port
Definition: base.c:55
fr_dict_attr_t const * attr_tacacs_remote_address
Definition: base.c:63
#define ASCII(_prefix, _field)
Definition: base.c:375
fr_dict_attr_t const * attr_tacacs_action
Definition: base.c:46
fr_dict_attr_t const * attr_tacacs_sequence_number
Definition: base.c:64
fr_dict_attr_t const * attr_tacacs_authorization_status
Definition: base.c:53
fr_dict_attr_t const * attr_tacacs_authentication_method
Definition: base.c:49
fr_dict_attr_t const * attr_tacacs_accounting_flags
Definition: base.c:44
fr_dict_attr_t const * attr_tacacs_data
Definition: base.c:56
fr_dict_attr_t const * attr_tacacs_user_name
Definition: base.c:71
fr_dict_attr_t const * attr_tacacs_flags
Definition: base.c:57
fr_dict_attr_t const * attr_tacacs_packet_type
Definition: base.c:61
VQP attributes.
static char * secret
Definition: radclient-ng.c:69
static bool done
Definition: radclient.c:80
static char const hex[]
Definition: smbencrypt.c:35
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
fr_assert(0)
Definition: log.h:96
#define packet_is_authen_reply(p)
Definition: tacacs.h:51
#define packet_is_authen_continue(p)
Definition: tacacs.h:50
#define packet_is_acct_reply(p)
Definition: tacacs.h:57
@ FR_TAC_PLUS_ACCT
Definition: tacacs.h:67
@ FR_TAC_PLUS_AUTHEN
Definition: tacacs.h:65
@ FR_TAC_PLUS_AUTHOR
Definition: tacacs.h:66
#define packet_is_author_request(p)
Definition: tacacs.h:53
#define packet_is_acct_request(p)
Definition: tacacs.h:56
#define packet_is_authen_start_request(p)
3.4.
Definition: tacacs.h:49
fr_tacacs_packet_hdr_t hdr
Definition: tacacs.h:277
fr_tacacs_type_t type
Definition: tacacs.h:97
@ FR_TACACS_CODE_MAX
Definition: tacacs.h:317
uint32_t session_id
Definition: tacacs.h:100
#define packet_is_author_reply(p)
Definition: tacacs.h:54
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static fr_slen_t data
Definition: value.h:1259