]> The Tcpdump Group git mirrors - tcpdump/blob - print-radius.c
CVE-2017-13002/AODV: Add some missing bounds checks.
[tcpdump] / print-radius.c
1 /*
2 * Copyright (C) 2000 Alfredo Andres Omella. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * 3. The names of the authors may not be used to endorse or promote
15 * products derived from this software without specific prior
16 * written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23 /* \summary: Radius protocol printer */
24
25 /*
26 * Radius printer routines as specified on:
27 *
28 * RFC 2865:
29 * "Remote Authentication Dial In User Service (RADIUS)"
30 *
31 * RFC 2866:
32 * "RADIUS Accounting"
33 *
34 * RFC 2867:
35 * "RADIUS Accounting Modifications for Tunnel Protocol Support"
36 *
37 * RFC 2868:
38 * "RADIUS Attributes for Tunnel Protocol Support"
39 *
40 * RFC 2869:
41 * "RADIUS Extensions"
42 *
43 * RFC 3580:
44 * "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
45 * "Usage Guidelines"
46 *
47 * RFC 4675:
48 * "RADIUS Attributes for Virtual LAN and Priority Support"
49 *
50 * RFC 4849:
51 * "RADIUS Filter Rule Attribute"
52 *
53 * RFC 5176:
54 * "Dynamic Authorization Extensions to RADIUS"
55 *
56 * RFC 7155:
57 * "Diameter Network Access Server Application"
58 *
59 * Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15
60 *
61 * TODO: Among other things to print ok MacIntosh and Vendor values
62 */
63
64 #ifdef HAVE_CONFIG_H
65 #include "config.h"
66 #endif
67
68 #include <netdissect-stdinc.h>
69
70 #include <string.h>
71
72 #include "netdissect.h"
73 #include "addrtoname.h"
74 #include "extract.h"
75 #include "oui.h"
76
77 static const char tstr[] = " [|radius]";
78
79 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
80
81 #define PRINT_HEX(bytes_len, ptr_data) \
82 while(bytes_len) \
83 { \
84 ND_PRINT((ndo, "%02X", *ptr_data )); \
85 ptr_data++; \
86 bytes_len--; \
87 }
88
89
90 /* Radius packet codes */
91 #define RADCMD_ACCESS_REQ 1 /* Access-Request */
92 #define RADCMD_ACCESS_ACC 2 /* Access-Accept */
93 #define RADCMD_ACCESS_REJ 3 /* Access-Reject */
94 #define RADCMD_ACCOUN_REQ 4 /* Accounting-Request */
95 #define RADCMD_ACCOUN_RES 5 /* Accounting-Response */
96 #define RADCMD_ACCESS_CHA 11 /* Access-Challenge */
97 #define RADCMD_STATUS_SER 12 /* Status-Server */
98 #define RADCMD_STATUS_CLI 13 /* Status-Client */
99 #define RADCMD_DISCON_REQ 40 /* Disconnect-Request */
100 #define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */
101 #define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */
102 #define RADCMD_COA_REQ 43 /* CoA-Request */
103 #define RADCMD_COA_ACK 44 /* CoA-ACK */
104 #define RADCMD_COA_NAK 45 /* CoA-NAK */
105 #define RADCMD_RESERVED 255 /* Reserved */
106
107 static const struct tok radius_command_values[] = {
108 { RADCMD_ACCESS_REQ, "Access-Request" },
109 { RADCMD_ACCESS_ACC, "Access-Accept" },
110 { RADCMD_ACCESS_REJ, "Access-Reject" },
111 { RADCMD_ACCOUN_REQ, "Accounting-Request" },
112 { RADCMD_ACCOUN_RES, "Accounting-Response" },
113 { RADCMD_ACCESS_CHA, "Access-Challenge" },
114 { RADCMD_STATUS_SER, "Status-Server" },
115 { RADCMD_STATUS_CLI, "Status-Client" },
116 { RADCMD_DISCON_REQ, "Disconnect-Request" },
117 { RADCMD_DISCON_ACK, "Disconnect-ACK" },
118 { RADCMD_DISCON_NAK, "Disconnect-NAK" },
119 { RADCMD_COA_REQ, "CoA-Request" },
120 { RADCMD_COA_ACK, "CoA-ACK" },
121 { RADCMD_COA_NAK, "CoA-NAK" },
122 { RADCMD_RESERVED, "Reserved" },
123 { 0, NULL}
124 };
125
126 /********************************/
127 /* Begin Radius Attribute types */
128 /********************************/
129 #define SERV_TYPE 6
130 #define FRM_IPADDR 8
131 #define LOG_IPHOST 14
132 #define LOG_SERVICE 15
133 #define FRM_IPX 23
134 #define SESSION_TIMEOUT 27
135 #define IDLE_TIMEOUT 28
136 #define FRM_ATALK_LINK 37
137 #define FRM_ATALK_NETWORK 38
138
139 #define ACCT_DELAY 41
140 #define ACCT_SESSION_TIME 46
141
142 #define EGRESS_VLAN_ID 56
143 #define EGRESS_VLAN_NAME 58
144
145 #define TUNNEL_TYPE 64
146 #define TUNNEL_MEDIUM 65
147 #define TUNNEL_CLIENT_END 66
148 #define TUNNEL_SERVER_END 67
149 #define TUNNEL_PASS 69
150
151 #define ARAP_PASS 70
152 #define ARAP_FEATURES 71
153
154 #define TUNNEL_PRIV_GROUP 81
155 #define TUNNEL_ASSIGN_ID 82
156 #define TUNNEL_PREFERENCE 83
157
158 #define ARAP_CHALLENGE_RESP 84
159 #define ACCT_INT_INTERVAL 85
160
161 #define TUNNEL_CLIENT_AUTH 90
162 #define TUNNEL_SERVER_AUTH 91
163 /********************************/
164 /* End Radius Attribute types */
165 /********************************/
166
167 #define RFC4675_TAGGED 0x31
168 #define RFC4675_UNTAGGED 0x32
169
170 static const struct tok rfc4675_tagged[] = {
171 { RFC4675_TAGGED, "Tagged" },
172 { RFC4675_UNTAGGED, "Untagged" },
173 { 0, NULL}
174 };
175
176
177 static void print_attr_string(netdissect_options *, register const u_char *, u_int, u_short );
178 static void print_attr_num(netdissect_options *, register const u_char *, u_int, u_short );
179 static void print_vendor_attr(netdissect_options *, register const u_char *, u_int, u_short );
180 static void print_attr_address(netdissect_options *, register const u_char *, u_int, u_short);
181 static void print_attr_time(netdissect_options *, register const u_char *, u_int, u_short);
182 static void print_attr_strange(netdissect_options *, register const u_char *, u_int, u_short);
183
184
185 struct radius_hdr { uint8_t code; /* Radius packet code */
186 uint8_t id; /* Radius packet id */
187 uint16_t len; /* Radius total length */
188 uint8_t auth[16]; /* Authenticator */
189 };
190
191 #define MIN_RADIUS_LEN 20
192
193 struct radius_attr { uint8_t type; /* Attribute type */
194 uint8_t len; /* Attribute length */
195 };
196
197
198 /* Service-Type Attribute standard values */
199 static const char *serv_type[]={ NULL,
200 "Login",
201 "Framed",
202 "Callback Login",
203 "Callback Framed",
204 "Outbound",
205 "Administrative",
206 "NAS Prompt",
207 "Authenticate Only",
208 "Callback NAS Prompt",
209 "Call Check",
210 "Callback Administrative",
211 };
212
213 /* Framed-Protocol Attribute standard values */
214 static const char *frm_proto[]={ NULL,
215 "PPP",
216 "SLIP",
217 "ARAP",
218 "Gandalf proprietary",
219 "Xylogics IPX/SLIP",
220 "X.75 Synchronous",
221 };
222
223 /* Framed-Routing Attribute standard values */
224 static const char *frm_routing[]={ "None",
225 "Send",
226 "Listen",
227 "Send&Listen",
228 };
229
230 /* Framed-Compression Attribute standard values */
231 static const char *frm_comp[]={ "None",
232 "VJ TCP/IP",
233 "IPX",
234 "Stac-LZS",
235 };
236
237 /* Login-Service Attribute standard values */
238 static const char *login_serv[]={ "Telnet",
239 "Rlogin",
240 "TCP Clear",
241 "PortMaster(proprietary)",
242 "LAT",
243 "X.25-PAD",
244 "X.25-T3POS",
245 "Unassigned",
246 "TCP Clear Quiet",
247 };
248
249
250 /* Termination-Action Attribute standard values */
251 static const char *term_action[]={ "Default",
252 "RADIUS-Request",
253 };
254
255 /* Ingress-Filters Attribute standard values */
256 static const char *ingress_filters[]={ NULL,
257 "Enabled",
258 "Disabled",
259 };
260
261 /* NAS-Port-Type Attribute standard values */
262 static const char *nas_port_type[]={ "Async",
263 "Sync",
264 "ISDN Sync",
265 "ISDN Async V.120",
266 "ISDN Async V.110",
267 "Virtual",
268 "PIAFS",
269 "HDLC Clear Channel",
270 "X.25",
271 "X.75",
272 "G.3 Fax",
273 "SDSL",
274 "ADSL-CAP",
275 "ADSL-DMT",
276 "ISDN-DSL",
277 "Ethernet",
278 "xDSL",
279 "Cable",
280 "Wireless - Other",
281 "Wireless - IEEE 802.11",
282 };
283
284 /* Acct-Status-Type Accounting Attribute standard values */
285 static const char *acct_status[]={ NULL,
286 "Start",
287 "Stop",
288 "Interim-Update",
289 "Unassigned",
290 "Unassigned",
291 "Unassigned",
292 "Accounting-On",
293 "Accounting-Off",
294 "Tunnel-Start",
295 "Tunnel-Stop",
296 "Tunnel-Reject",
297 "Tunnel-Link-Start",
298 "Tunnel-Link-Stop",
299 "Tunnel-Link-Reject",
300 "Failed",
301 };
302
303 /* Acct-Authentic Accounting Attribute standard values */
304 static const char *acct_auth[]={ NULL,
305 "RADIUS",
306 "Local",
307 "Remote",
308 };
309
310 /* Acct-Terminate-Cause Accounting Attribute standard values */
311 static const char *acct_term[]={ NULL,
312 "User Request",
313 "Lost Carrier",
314 "Lost Service",
315 "Idle Timeout",
316 "Session Timeout",
317 "Admin Reset",
318 "Admin Reboot",
319 "Port Error",
320 "NAS Error",
321 "NAS Request",
322 "NAS Reboot",
323 "Port Unneeded",
324 "Port Preempted",
325 "Port Suspended",
326 "Service Unavailable",
327 "Callback",
328 "User Error",
329 "Host Request",
330 };
331
332 /* Tunnel-Type Attribute standard values */
333 static const char *tunnel_type[]={ NULL,
334 "PPTP",
335 "L2F",
336 "L2TP",
337 "ATMP",
338 "VTP",
339 "AH",
340 "IP-IP",
341 "MIN-IP-IP",
342 "ESP",
343 "GRE",
344 "DVS",
345 "IP-in-IP Tunneling",
346 "VLAN",
347 };
348
349 /* Tunnel-Medium-Type Attribute standard values */
350 static const char *tunnel_medium[]={ NULL,
351 "IPv4",
352 "IPv6",
353 "NSAP",
354 "HDLC",
355 "BBN 1822",
356 "802",
357 "E.163",
358 "E.164",
359 "F.69",
360 "X.121",
361 "IPX",
362 "Appletalk",
363 "Decnet IV",
364 "Banyan Vines",
365 "E.164 with NSAP subaddress",
366 };
367
368 /* ARAP-Zone-Access Attribute standard values */
369 static const char *arap_zone[]={ NULL,
370 "Only access to dfl zone",
371 "Use zone filter inc.",
372 "Not used",
373 "Use zone filter exc.",
374 };
375
376 static const char *prompt[]={ "No Echo",
377 "Echo",
378 };
379
380
381 static struct attrtype {
382 const char *name; /* Attribute name */
383 const char **subtypes; /* Standard Values (if any) */
384 u_char siz_subtypes; /* Size of total standard values */
385 u_char first_subtype; /* First standard value is 0 or 1 */
386 void (*print_func)(netdissect_options *, register const u_char *, u_int, u_short);
387 } attr_type[]=
388 {
389 { NULL, NULL, 0, 0, NULL },
390 { "User-Name", NULL, 0, 0, print_attr_string },
391 { "User-Password", NULL, 0, 0, NULL },
392 { "CHAP-Password", NULL, 0, 0, NULL },
393 { "NAS-IP-Address", NULL, 0, 0, print_attr_address },
394 { "NAS-Port", NULL, 0, 0, print_attr_num },
395 { "Service-Type", serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
396 { "Framed-Protocol", frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
397 { "Framed-IP-Address", NULL, 0, 0, print_attr_address },
398 { "Framed-IP-Netmask", NULL, 0, 0, print_attr_address },
399 { "Framed-Routing", frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
400 { "Filter-Id", NULL, 0, 0, print_attr_string },
401 { "Framed-MTU", NULL, 0, 0, print_attr_num },
402 { "Framed-Compression", frm_comp, TAM_SIZE(frm_comp), 0, print_attr_num },
403 { "Login-IP-Host", NULL, 0, 0, print_attr_address },
404 { "Login-Service", login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
405 { "Login-TCP-Port", NULL, 0, 0, print_attr_num },
406 { "Unassigned", NULL, 0, 0, NULL }, /*17*/
407 { "Reply-Message", NULL, 0, 0, print_attr_string },
408 { "Callback-Number", NULL, 0, 0, print_attr_string },
409 { "Callback-Id", NULL, 0, 0, print_attr_string },
410 { "Unassigned", NULL, 0, 0, NULL }, /*21*/
411 { "Framed-Route", NULL, 0, 0, print_attr_string },
412 { "Framed-IPX-Network", NULL, 0, 0, print_attr_num },
413 { "State", NULL, 0, 0, print_attr_string },
414 { "Class", NULL, 0, 0, print_attr_string },
415 { "Vendor-Specific", NULL, 0, 0, print_vendor_attr },
416 { "Session-Timeout", NULL, 0, 0, print_attr_num },
417 { "Idle-Timeout", NULL, 0, 0, print_attr_num },
418 { "Termination-Action", term_action, TAM_SIZE(term_action), 0, print_attr_num },
419 { "Called-Station-Id", NULL, 0, 0, print_attr_string },
420 { "Calling-Station-Id", NULL, 0, 0, print_attr_string },
421 { "NAS-Identifier", NULL, 0, 0, print_attr_string },
422 { "Proxy-State", NULL, 0, 0, print_attr_string },
423 { "Login-LAT-Service", NULL, 0, 0, print_attr_string },
424 { "Login-LAT-Node", NULL, 0, 0, print_attr_string },
425 { "Login-LAT-Group", NULL, 0, 0, print_attr_string },
426 { "Framed-AppleTalk-Link", NULL, 0, 0, print_attr_num },
427 { "Framed-AppleTalk-Network", NULL, 0, 0, print_attr_num },
428 { "Framed-AppleTalk-Zone", NULL, 0, 0, print_attr_string },
429 { "Acct-Status-Type", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
430 { "Acct-Delay-Time", NULL, 0, 0, print_attr_num },
431 { "Acct-Input-Octets", NULL, 0, 0, print_attr_num },
432 { "Acct-Output-Octets", NULL, 0, 0, print_attr_num },
433 { "Acct-Session-Id", NULL, 0, 0, print_attr_string },
434 { "Acct-Authentic", acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
435 { "Acct-Session-Time", NULL, 0, 0, print_attr_num },
436 { "Acct-Input-Packets", NULL, 0, 0, print_attr_num },
437 { "Acct-Output-Packets", NULL, 0, 0, print_attr_num },
438 { "Acct-Terminate-Cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
439 { "Acct-Multi-Session-Id", NULL, 0, 0, print_attr_string },
440 { "Acct-Link-Count", NULL, 0, 0, print_attr_num },
441 { "Acct-Input-Gigawords", NULL, 0, 0, print_attr_num },
442 { "Acct-Output-Gigawords", NULL, 0, 0, print_attr_num },
443 { "Unassigned", NULL, 0, 0, NULL }, /*54*/
444 { "Event-Timestamp", NULL, 0, 0, print_attr_time },
445 { "Egress-VLANID", NULL, 0, 0, print_attr_num },
446 { "Ingress-Filters", ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
447 { "Egress-VLAN-Name", NULL, 0, 0, print_attr_string },
448 { "User-Priority-Table", NULL, 0, 0, NULL },
449 { "CHAP-Challenge", NULL, 0, 0, print_attr_string },
450 { "NAS-Port-Type", nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
451 { "Port-Limit", NULL, 0, 0, print_attr_num },
452 { "Login-LAT-Port", NULL, 0, 0, print_attr_string }, /*63*/
453 { "Tunnel-Type", tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
454 { "Tunnel-Medium-Type", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
455 { "Tunnel-Client-Endpoint", NULL, 0, 0, print_attr_string },
456 { "Tunnel-Server-Endpoint", NULL, 0, 0, print_attr_string },
457 { "Acct-Tunnel-Connection", NULL, 0, 0, print_attr_string },
458 { "Tunnel-Password", NULL, 0, 0, print_attr_string },
459 { "ARAP-Password", NULL, 0, 0, print_attr_strange },
460 { "ARAP-Features", NULL, 0, 0, print_attr_strange },
461 { "ARAP-Zone-Access", arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
462 { "ARAP-Security", NULL, 0, 0, print_attr_string },
463 { "ARAP-Security-Data", NULL, 0, 0, print_attr_string },
464 { "Password-Retry", NULL, 0, 0, print_attr_num },
465 { "Prompt", prompt, TAM_SIZE(prompt), 0, print_attr_num },
466 { "Connect-Info", NULL, 0, 0, print_attr_string },
467 { "Configuration-Token", NULL, 0, 0, print_attr_string },
468 { "EAP-Message", NULL, 0, 0, print_attr_string },
469 { "Message-Authenticator", NULL, 0, 0, print_attr_string }, /*80*/
470 { "Tunnel-Private-Group-ID", NULL, 0, 0, print_attr_string },
471 { "Tunnel-Assignment-ID", NULL, 0, 0, print_attr_string },
472 { "Tunnel-Preference", NULL, 0, 0, print_attr_num },
473 { "ARAP-Challenge-Response", NULL, 0, 0, print_attr_strange },
474 { "Acct-Interim-Interval", NULL, 0, 0, print_attr_num },
475 { "Acct-Tunnel-Packets-Lost", NULL, 0, 0, print_attr_num }, /*86*/
476 { "NAS-Port-Id", NULL, 0, 0, print_attr_string },
477 { "Framed-Pool", NULL, 0, 0, print_attr_string },
478 { "CUI", NULL, 0, 0, print_attr_string },
479 { "Tunnel-Client-Auth-ID", NULL, 0, 0, print_attr_string },
480 { "Tunnel-Server-Auth-ID", NULL, 0, 0, print_attr_string },
481 { "NAS-Filter-Rule", NULL, 0, 0, print_attr_string },
482 { "Unassigned", NULL, 0, 0, NULL }, /*93*/
483 { "Originating-Line-Info", NULL, 0, 0, NULL }
484 };
485
486
487 /*****************************/
488 /* Print an attribute string */
489 /* value pointed by 'data' */
490 /* and 'length' size. */
491 /*****************************/
492 /* Returns nothing. */
493 /*****************************/
494 static void
495 print_attr_string(netdissect_options *ndo,
496 register const u_char *data, u_int length, u_short attr_code)
497 {
498 register u_int i;
499
500 ND_TCHECK2(data[0],length);
501
502 switch(attr_code)
503 {
504 case TUNNEL_PASS:
505 if (length < 3)
506 {
507 ND_PRINT((ndo, "%s", tstr));
508 return;
509 }
510 if (*data && (*data <=0x1F) )
511 ND_PRINT((ndo, "Tag[%u] ", *data));
512 else
513 ND_PRINT((ndo, "Tag[Unused] "));
514 data++;
515 length--;
516 ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
517 data+=2;
518 length-=2;
519 break;
520 case TUNNEL_CLIENT_END:
521 case TUNNEL_SERVER_END:
522 case TUNNEL_PRIV_GROUP:
523 case TUNNEL_ASSIGN_ID:
524 case TUNNEL_CLIENT_AUTH:
525 case TUNNEL_SERVER_AUTH:
526 if (*data <= 0x1F)
527 {
528 if (length < 1)
529 {
530 ND_PRINT((ndo, "%s", tstr));
531 return;
532 }
533 if (*data)
534 ND_PRINT((ndo, "Tag[%u] ", *data));
535 else
536 ND_PRINT((ndo, "Tag[Unused] "));
537 data++;
538 length--;
539 }
540 break;
541 case EGRESS_VLAN_NAME:
542 ND_PRINT((ndo, "%s (0x%02x) ",
543 tok2str(rfc4675_tagged,"Unknown tag",*data),
544 *data));
545 data++;
546 length--;
547 break;
548 }
549
550 for (i=0; *data && i < length ; i++, data++)
551 ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
552
553 return;
554
555 trunc:
556 ND_PRINT((ndo, "%s", tstr));
557 }
558
559 /*
560 * print vendor specific attributes
561 */
562 static void
563 print_vendor_attr(netdissect_options *ndo,
564 register const u_char *data, u_int length, u_short attr_code _U_)
565 {
566 u_int idx;
567 u_int vendor_id;
568 u_int vendor_type;
569 u_int vendor_length;
570
571 if (length < 4)
572 goto trunc;
573 ND_TCHECK2(*data, 4);
574 vendor_id = EXTRACT_32BITS(data);
575 data+=4;
576 length-=4;
577
578 ND_PRINT((ndo, "Vendor: %s (%u)",
579 tok2str(smi_values,"Unknown",vendor_id),
580 vendor_id));
581
582 while (length >= 2) {
583 ND_TCHECK2(*data, 2);
584
585 vendor_type = *(data);
586 vendor_length = *(data+1);
587
588 if (vendor_length < 2)
589 {
590 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
591 vendor_type,
592 vendor_length));
593 return;
594 }
595 if (vendor_length > length)
596 {
597 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
598 vendor_type,
599 vendor_length));
600 return;
601 }
602 data+=2;
603 vendor_length-=2;
604 length-=2;
605 ND_TCHECK2(*data, vendor_length);
606
607 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u, Value: ",
608 vendor_type,
609 vendor_length));
610 for (idx = 0; idx < vendor_length ; idx++, data++)
611 ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
612 length-=vendor_length;
613 }
614 return;
615
616 trunc:
617 ND_PRINT((ndo, "%s", tstr));
618 }
619
620 /******************************/
621 /* Print an attribute numeric */
622 /* value pointed by 'data' */
623 /* and 'length' size. */
624 /******************************/
625 /* Returns nothing. */
626 /******************************/
627 static void
628 print_attr_num(netdissect_options *ndo,
629 register const u_char *data, u_int length, u_short attr_code)
630 {
631 uint32_t timeout;
632
633 if (length != 4)
634 {
635 ND_PRINT((ndo, "ERROR: length %u != 4", length));
636 return;
637 }
638
639 ND_TCHECK2(data[0],4);
640 /* This attribute has standard values */
641 if (attr_type[attr_code].siz_subtypes)
642 {
643 static const char **table;
644 uint32_t data_value;
645 table = attr_type[attr_code].subtypes;
646
647 if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
648 {
649 if (!*data)
650 ND_PRINT((ndo, "Tag[Unused] "));
651 else
652 ND_PRINT((ndo, "Tag[%d] ", *data));
653 data++;
654 data_value = EXTRACT_24BITS(data);
655 }
656 else
657 {
658 data_value = EXTRACT_32BITS(data);
659 }
660 if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
661 attr_type[attr_code].first_subtype) &&
662 data_value >= attr_type[attr_code].first_subtype )
663 ND_PRINT((ndo, "%s", table[data_value]));
664 else
665 ND_PRINT((ndo, "#%u", data_value));
666 }
667 else
668 {
669 switch(attr_code) /* Be aware of special cases... */
670 {
671 case FRM_IPX:
672 if (EXTRACT_32BITS( data) == 0xFFFFFFFE )
673 ND_PRINT((ndo, "NAS Select"));
674 else
675 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
676 break;
677
678 case SESSION_TIMEOUT:
679 case IDLE_TIMEOUT:
680 case ACCT_DELAY:
681 case ACCT_SESSION_TIME:
682 case ACCT_INT_INTERVAL:
683 timeout = EXTRACT_32BITS( data);
684 if ( timeout < 60 )
685 ND_PRINT((ndo, "%02d secs", timeout));
686 else
687 {
688 if ( timeout < 3600 )
689 ND_PRINT((ndo, "%02d:%02d min",
690 timeout / 60, timeout % 60));
691 else
692 ND_PRINT((ndo, "%02d:%02d:%02d hours",
693 timeout / 3600, (timeout % 3600) / 60,
694 timeout % 60));
695 }
696 break;
697
698 case FRM_ATALK_LINK:
699 if (EXTRACT_32BITS(data) )
700 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
701 else
702 ND_PRINT((ndo, "Unnumbered"));
703 break;
704
705 case FRM_ATALK_NETWORK:
706 if (EXTRACT_32BITS(data) )
707 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
708 else
709 ND_PRINT((ndo, "NAS assigned"));
710 break;
711
712 case TUNNEL_PREFERENCE:
713 if (*data)
714 ND_PRINT((ndo, "Tag[%d] ", *data));
715 else
716 ND_PRINT((ndo, "Tag[Unused] "));
717 data++;
718 ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
719 break;
720
721 case EGRESS_VLAN_ID:
722 ND_PRINT((ndo, "%s (0x%02x) ",
723 tok2str(rfc4675_tagged,"Unknown tag",*data),
724 *data));
725 data++;
726 ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
727 break;
728
729 default:
730 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
731 break;
732
733 } /* switch */
734
735 } /* if-else */
736
737 return;
738
739 trunc:
740 ND_PRINT((ndo, "%s", tstr));
741 }
742
743 /*****************************/
744 /* Print an attribute IPv4 */
745 /* address value pointed by */
746 /* 'data' and 'length' size. */
747 /*****************************/
748 /* Returns nothing. */
749 /*****************************/
750 static void
751 print_attr_address(netdissect_options *ndo,
752 register const u_char *data, u_int length, u_short attr_code)
753 {
754 if (length != 4)
755 {
756 ND_PRINT((ndo, "ERROR: length %u != 4", length));
757 return;
758 }
759
760 ND_TCHECK2(data[0],4);
761
762 switch(attr_code)
763 {
764 case FRM_IPADDR:
765 case LOG_IPHOST:
766 if (EXTRACT_32BITS(data) == 0xFFFFFFFF )
767 ND_PRINT((ndo, "User Selected"));
768 else
769 if (EXTRACT_32BITS(data) == 0xFFFFFFFE )
770 ND_PRINT((ndo, "NAS Select"));
771 else
772 ND_PRINT((ndo, "%s",ipaddr_string(ndo, data)));
773 break;
774
775 default:
776 ND_PRINT((ndo, "%s", ipaddr_string(ndo, data)));
777 break;
778 }
779
780 return;
781
782 trunc:
783 ND_PRINT((ndo, "%s", tstr));
784 }
785
786 /*************************************/
787 /* Print an attribute of 'secs since */
788 /* January 1, 1970 00:00 UTC' value */
789 /* pointed by 'data' and 'length' */
790 /* size. */
791 /*************************************/
792 /* Returns nothing. */
793 /*************************************/
794 static void
795 print_attr_time(netdissect_options *ndo,
796 register const u_char *data, u_int length, u_short attr_code _U_)
797 {
798 time_t attr_time;
799 char string[26];
800
801 if (length != 4)
802 {
803 ND_PRINT((ndo, "ERROR: length %u != 4", length));
804 return;
805 }
806
807 ND_TCHECK2(data[0],4);
808
809 attr_time = EXTRACT_32BITS(data);
810 strlcpy(string, ctime(&attr_time), sizeof(string));
811 /* Get rid of the newline */
812 string[24] = '\0';
813 ND_PRINT((ndo, "%.24s", string));
814 return;
815
816 trunc:
817 ND_PRINT((ndo, "%s", tstr));
818 }
819
820 /***********************************/
821 /* Print an attribute of 'strange' */
822 /* data format pointed by 'data' */
823 /* and 'length' size. */
824 /***********************************/
825 /* Returns nothing. */
826 /***********************************/
827 static void
828 print_attr_strange(netdissect_options *ndo,
829 register const u_char *data, u_int length, u_short attr_code)
830 {
831 u_short len_data;
832
833 switch(attr_code)
834 {
835 case ARAP_PASS:
836 if (length != 16)
837 {
838 ND_PRINT((ndo, "ERROR: length %u != 16", length));
839 return;
840 }
841 ND_PRINT((ndo, "User_challenge ("));
842 ND_TCHECK2(data[0],8);
843 len_data = 8;
844 PRINT_HEX(len_data, data);
845 ND_PRINT((ndo, ") User_resp("));
846 ND_TCHECK2(data[0],8);
847 len_data = 8;
848 PRINT_HEX(len_data, data);
849 ND_PRINT((ndo, ")"));
850 break;
851
852 case ARAP_FEATURES:
853 if (length != 14)
854 {
855 ND_PRINT((ndo, "ERROR: length %u != 14", length));
856 return;
857 }
858 ND_TCHECK2(data[0],1);
859 if (*data)
860 ND_PRINT((ndo, "User can change password"));
861 else
862 ND_PRINT((ndo, "User cannot change password"));
863 data++;
864 ND_TCHECK2(data[0],1);
865 ND_PRINT((ndo, ", Min password length: %d", *data));
866 data++;
867 ND_PRINT((ndo, ", created at: "));
868 ND_TCHECK2(data[0],4);
869 len_data = 4;
870 PRINT_HEX(len_data, data);
871 ND_PRINT((ndo, ", expires in: "));
872 ND_TCHECK2(data[0],4);
873 len_data = 4;
874 PRINT_HEX(len_data, data);
875 ND_PRINT((ndo, ", Current Time: "));
876 ND_TCHECK2(data[0],4);
877 len_data = 4;
878 PRINT_HEX(len_data, data);
879 break;
880
881 case ARAP_CHALLENGE_RESP:
882 if (length < 8)
883 {
884 ND_PRINT((ndo, "ERROR: length %u != 8", length));
885 return;
886 }
887 ND_TCHECK2(data[0],8);
888 len_data = 8;
889 PRINT_HEX(len_data, data);
890 break;
891 }
892 return;
893
894 trunc:
895 ND_PRINT((ndo, "%s", tstr));
896 }
897
898 static void
899 radius_attrs_print(netdissect_options *ndo,
900 register const u_char *attr, u_int length)
901 {
902 register const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
903 const char *attr_string;
904
905 while (length > 0)
906 {
907 if (length < 2)
908 goto trunc;
909 ND_TCHECK(*rad_attr);
910
911 if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
912 attr_string = attr_type[rad_attr->type].name;
913 else
914 attr_string = "Unknown";
915 if (rad_attr->len < 2)
916 {
917 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, must be >= 2)",
918 attr_string,
919 rad_attr->type,
920 rad_attr->len));
921 return;
922 }
923 if (rad_attr->len > length)
924 {
925 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, goes past end of packet)",
926 attr_string,
927 rad_attr->type,
928 rad_attr->len));
929 return;
930 }
931 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u, Value: ",
932 attr_string,
933 rad_attr->type,
934 rad_attr->len));
935
936 if (rad_attr->type < TAM_SIZE(attr_type))
937 {
938 if (rad_attr->len > 2)
939 {
940 if ( attr_type[rad_attr->type].print_func )
941 (*attr_type[rad_attr->type].print_func)(
942 ndo, ((const u_char *)(rad_attr+1)),
943 rad_attr->len - 2, rad_attr->type);
944 }
945 }
946 /* do we also want to see a hex dump ? */
947 if (ndo->ndo_vflag> 1)
948 print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (rad_attr->len)-2);
949
950 length-=(rad_attr->len);
951 rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+rad_attr->len);
952 }
953 return;
954
955 trunc:
956 ND_PRINT((ndo, "%s", tstr));
957 }
958
959 void
960 radius_print(netdissect_options *ndo,
961 const u_char *dat, u_int length)
962 {
963 register const struct radius_hdr *rad;
964 u_int len, auth_idx;
965
966 ND_TCHECK2(*dat, MIN_RADIUS_LEN);
967 rad = (const struct radius_hdr *)dat;
968 len = EXTRACT_16BITS(&rad->len);
969
970 if (len < MIN_RADIUS_LEN)
971 {
972 ND_PRINT((ndo, "%s", tstr));
973 return;
974 }
975
976 if (len > length)
977 len = length;
978
979 if (ndo->ndo_vflag < 1) {
980 ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u",
981 tok2str(radius_command_values,"Unknown Command",rad->code),
982 rad->code,
983 rad->id,
984 len));
985 return;
986 }
987 else {
988 ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
989 len,
990 tok2str(radius_command_values,"Unknown Command",rad->code),
991 rad->code,
992 rad->id));
993
994 for(auth_idx=0; auth_idx < 16; auth_idx++)
995 ND_PRINT((ndo, "%02x", rad->auth[auth_idx]));
996 }
997
998 if (len > MIN_RADIUS_LEN)
999 radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
1000 return;
1001
1002 trunc:
1003 ND_PRINT((ndo, "%s", tstr));
1004 }