]> The Tcpdump Group git mirrors - tcpdump/blob - print-radius.c
CVE-2017-13032/RADIUS: Check whether a byte exists before testing its value.
[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 goto trunc;
507 if (*data && (*data <=0x1F) )
508 ND_PRINT((ndo, "Tag[%u] ", *data));
509 else
510 ND_PRINT((ndo, "Tag[Unused] "));
511 data++;
512 length--;
513 ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data)));
514 data+=2;
515 length-=2;
516 break;
517 case TUNNEL_CLIENT_END:
518 case TUNNEL_SERVER_END:
519 case TUNNEL_PRIV_GROUP:
520 case TUNNEL_ASSIGN_ID:
521 case TUNNEL_CLIENT_AUTH:
522 case TUNNEL_SERVER_AUTH:
523 if (*data <= 0x1F)
524 {
525 if (length < 1)
526 goto trunc;
527 if (*data)
528 ND_PRINT((ndo, "Tag[%u] ", *data));
529 else
530 ND_PRINT((ndo, "Tag[Unused] "));
531 data++;
532 length--;
533 }
534 break;
535 case EGRESS_VLAN_NAME:
536 if (length < 1)
537 goto trunc;
538 ND_PRINT((ndo, "%s (0x%02x) ",
539 tok2str(rfc4675_tagged,"Unknown tag",*data),
540 *data));
541 data++;
542 length--;
543 break;
544 }
545
546 for (i=0; i < length && *data; i++, data++)
547 ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
548
549 return;
550
551 trunc:
552 ND_PRINT((ndo, "%s", tstr));
553 }
554
555 /*
556 * print vendor specific attributes
557 */
558 static void
559 print_vendor_attr(netdissect_options *ndo,
560 register const u_char *data, u_int length, u_short attr_code _U_)
561 {
562 u_int idx;
563 u_int vendor_id;
564 u_int vendor_type;
565 u_int vendor_length;
566
567 if (length < 4)
568 goto trunc;
569 ND_TCHECK2(*data, 4);
570 vendor_id = EXTRACT_32BITS(data);
571 data+=4;
572 length-=4;
573
574 ND_PRINT((ndo, "Vendor: %s (%u)",
575 tok2str(smi_values,"Unknown",vendor_id),
576 vendor_id));
577
578 while (length >= 2) {
579 ND_TCHECK2(*data, 2);
580
581 vendor_type = *(data);
582 vendor_length = *(data+1);
583
584 if (vendor_length < 2)
585 {
586 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
587 vendor_type,
588 vendor_length));
589 return;
590 }
591 if (vendor_length > length)
592 {
593 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
594 vendor_type,
595 vendor_length));
596 return;
597 }
598 data+=2;
599 vendor_length-=2;
600 length-=2;
601 ND_TCHECK2(*data, vendor_length);
602
603 ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u, Value: ",
604 vendor_type,
605 vendor_length));
606 for (idx = 0; idx < vendor_length ; idx++, data++)
607 ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data));
608 length-=vendor_length;
609 }
610 return;
611
612 trunc:
613 ND_PRINT((ndo, "%s", tstr));
614 }
615
616 /******************************/
617 /* Print an attribute numeric */
618 /* value pointed by 'data' */
619 /* and 'length' size. */
620 /******************************/
621 /* Returns nothing. */
622 /******************************/
623 static void
624 print_attr_num(netdissect_options *ndo,
625 register const u_char *data, u_int length, u_short attr_code)
626 {
627 uint32_t timeout;
628
629 if (length != 4)
630 {
631 ND_PRINT((ndo, "ERROR: length %u != 4", length));
632 return;
633 }
634
635 ND_TCHECK2(data[0],4);
636 /* This attribute has standard values */
637 if (attr_type[attr_code].siz_subtypes)
638 {
639 static const char **table;
640 uint32_t data_value;
641 table = attr_type[attr_code].subtypes;
642
643 if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
644 {
645 if (!*data)
646 ND_PRINT((ndo, "Tag[Unused] "));
647 else
648 ND_PRINT((ndo, "Tag[%d] ", *data));
649 data++;
650 data_value = EXTRACT_24BITS(data);
651 }
652 else
653 {
654 data_value = EXTRACT_32BITS(data);
655 }
656 if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
657 attr_type[attr_code].first_subtype) &&
658 data_value >= attr_type[attr_code].first_subtype )
659 ND_PRINT((ndo, "%s", table[data_value]));
660 else
661 ND_PRINT((ndo, "#%u", data_value));
662 }
663 else
664 {
665 switch(attr_code) /* Be aware of special cases... */
666 {
667 case FRM_IPX:
668 if (EXTRACT_32BITS( data) == 0xFFFFFFFE )
669 ND_PRINT((ndo, "NAS Select"));
670 else
671 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
672 break;
673
674 case SESSION_TIMEOUT:
675 case IDLE_TIMEOUT:
676 case ACCT_DELAY:
677 case ACCT_SESSION_TIME:
678 case ACCT_INT_INTERVAL:
679 timeout = EXTRACT_32BITS( data);
680 if ( timeout < 60 )
681 ND_PRINT((ndo, "%02d secs", timeout));
682 else
683 {
684 if ( timeout < 3600 )
685 ND_PRINT((ndo, "%02d:%02d min",
686 timeout / 60, timeout % 60));
687 else
688 ND_PRINT((ndo, "%02d:%02d:%02d hours",
689 timeout / 3600, (timeout % 3600) / 60,
690 timeout % 60));
691 }
692 break;
693
694 case FRM_ATALK_LINK:
695 if (EXTRACT_32BITS(data) )
696 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
697 else
698 ND_PRINT((ndo, "Unnumbered"));
699 break;
700
701 case FRM_ATALK_NETWORK:
702 if (EXTRACT_32BITS(data) )
703 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
704 else
705 ND_PRINT((ndo, "NAS assigned"));
706 break;
707
708 case TUNNEL_PREFERENCE:
709 if (*data)
710 ND_PRINT((ndo, "Tag[%d] ", *data));
711 else
712 ND_PRINT((ndo, "Tag[Unused] "));
713 data++;
714 ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
715 break;
716
717 case EGRESS_VLAN_ID:
718 ND_PRINT((ndo, "%s (0x%02x) ",
719 tok2str(rfc4675_tagged,"Unknown tag",*data),
720 *data));
721 data++;
722 ND_PRINT((ndo, "%d", EXTRACT_24BITS(data)));
723 break;
724
725 default:
726 ND_PRINT((ndo, "%d", EXTRACT_32BITS(data)));
727 break;
728
729 } /* switch */
730
731 } /* if-else */
732
733 return;
734
735 trunc:
736 ND_PRINT((ndo, "%s", tstr));
737 }
738
739 /*****************************/
740 /* Print an attribute IPv4 */
741 /* address value pointed by */
742 /* 'data' and 'length' size. */
743 /*****************************/
744 /* Returns nothing. */
745 /*****************************/
746 static void
747 print_attr_address(netdissect_options *ndo,
748 register const u_char *data, u_int length, u_short attr_code)
749 {
750 if (length != 4)
751 {
752 ND_PRINT((ndo, "ERROR: length %u != 4", length));
753 return;
754 }
755
756 ND_TCHECK2(data[0],4);
757
758 switch(attr_code)
759 {
760 case FRM_IPADDR:
761 case LOG_IPHOST:
762 if (EXTRACT_32BITS(data) == 0xFFFFFFFF )
763 ND_PRINT((ndo, "User Selected"));
764 else
765 if (EXTRACT_32BITS(data) == 0xFFFFFFFE )
766 ND_PRINT((ndo, "NAS Select"));
767 else
768 ND_PRINT((ndo, "%s",ipaddr_string(ndo, data)));
769 break;
770
771 default:
772 ND_PRINT((ndo, "%s", ipaddr_string(ndo, data)));
773 break;
774 }
775
776 return;
777
778 trunc:
779 ND_PRINT((ndo, "%s", tstr));
780 }
781
782 /*************************************/
783 /* Print an attribute of 'secs since */
784 /* January 1, 1970 00:00 UTC' value */
785 /* pointed by 'data' and 'length' */
786 /* size. */
787 /*************************************/
788 /* Returns nothing. */
789 /*************************************/
790 static void
791 print_attr_time(netdissect_options *ndo,
792 register const u_char *data, u_int length, u_short attr_code _U_)
793 {
794 time_t attr_time;
795 char string[26];
796
797 if (length != 4)
798 {
799 ND_PRINT((ndo, "ERROR: length %u != 4", length));
800 return;
801 }
802
803 ND_TCHECK2(data[0],4);
804
805 attr_time = EXTRACT_32BITS(data);
806 strlcpy(string, ctime(&attr_time), sizeof(string));
807 /* Get rid of the newline */
808 string[24] = '\0';
809 ND_PRINT((ndo, "%.24s", string));
810 return;
811
812 trunc:
813 ND_PRINT((ndo, "%s", tstr));
814 }
815
816 /***********************************/
817 /* Print an attribute of 'strange' */
818 /* data format pointed by 'data' */
819 /* and 'length' size. */
820 /***********************************/
821 /* Returns nothing. */
822 /***********************************/
823 static void
824 print_attr_strange(netdissect_options *ndo,
825 register const u_char *data, u_int length, u_short attr_code)
826 {
827 u_short len_data;
828
829 switch(attr_code)
830 {
831 case ARAP_PASS:
832 if (length != 16)
833 {
834 ND_PRINT((ndo, "ERROR: length %u != 16", length));
835 return;
836 }
837 ND_PRINT((ndo, "User_challenge ("));
838 ND_TCHECK2(data[0],8);
839 len_data = 8;
840 PRINT_HEX(len_data, data);
841 ND_PRINT((ndo, ") User_resp("));
842 ND_TCHECK2(data[0],8);
843 len_data = 8;
844 PRINT_HEX(len_data, data);
845 ND_PRINT((ndo, ")"));
846 break;
847
848 case ARAP_FEATURES:
849 if (length != 14)
850 {
851 ND_PRINT((ndo, "ERROR: length %u != 14", length));
852 return;
853 }
854 ND_TCHECK2(data[0],1);
855 if (*data)
856 ND_PRINT((ndo, "User can change password"));
857 else
858 ND_PRINT((ndo, "User cannot change password"));
859 data++;
860 ND_TCHECK2(data[0],1);
861 ND_PRINT((ndo, ", Min password length: %d", *data));
862 data++;
863 ND_PRINT((ndo, ", created at: "));
864 ND_TCHECK2(data[0],4);
865 len_data = 4;
866 PRINT_HEX(len_data, data);
867 ND_PRINT((ndo, ", expires in: "));
868 ND_TCHECK2(data[0],4);
869 len_data = 4;
870 PRINT_HEX(len_data, data);
871 ND_PRINT((ndo, ", Current Time: "));
872 ND_TCHECK2(data[0],4);
873 len_data = 4;
874 PRINT_HEX(len_data, data);
875 break;
876
877 case ARAP_CHALLENGE_RESP:
878 if (length < 8)
879 {
880 ND_PRINT((ndo, "ERROR: length %u != 8", length));
881 return;
882 }
883 ND_TCHECK2(data[0],8);
884 len_data = 8;
885 PRINT_HEX(len_data, data);
886 break;
887 }
888 return;
889
890 trunc:
891 ND_PRINT((ndo, "%s", tstr));
892 }
893
894 static void
895 radius_attrs_print(netdissect_options *ndo,
896 register const u_char *attr, u_int length)
897 {
898 register const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
899 const char *attr_string;
900
901 while (length > 0)
902 {
903 if (length < 2)
904 goto trunc;
905 ND_TCHECK(*rad_attr);
906
907 if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type))
908 attr_string = attr_type[rad_attr->type].name;
909 else
910 attr_string = "Unknown";
911 if (rad_attr->len < 2)
912 {
913 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, must be >= 2)",
914 attr_string,
915 rad_attr->type,
916 rad_attr->len));
917 return;
918 }
919 if (rad_attr->len > length)
920 {
921 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, goes past end of packet)",
922 attr_string,
923 rad_attr->type,
924 rad_attr->len));
925 return;
926 }
927 ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u, Value: ",
928 attr_string,
929 rad_attr->type,
930 rad_attr->len));
931
932 if (rad_attr->type < TAM_SIZE(attr_type))
933 {
934 if (rad_attr->len > 2)
935 {
936 if ( attr_type[rad_attr->type].print_func )
937 (*attr_type[rad_attr->type].print_func)(
938 ndo, ((const u_char *)(rad_attr+1)),
939 rad_attr->len - 2, rad_attr->type);
940 }
941 }
942 /* do we also want to see a hex dump ? */
943 if (ndo->ndo_vflag> 1)
944 print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (rad_attr->len)-2);
945
946 length-=(rad_attr->len);
947 rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+rad_attr->len);
948 }
949 return;
950
951 trunc:
952 ND_PRINT((ndo, "%s", tstr));
953 }
954
955 void
956 radius_print(netdissect_options *ndo,
957 const u_char *dat, u_int length)
958 {
959 register const struct radius_hdr *rad;
960 u_int len, auth_idx;
961
962 ND_TCHECK2(*dat, MIN_RADIUS_LEN);
963 rad = (const struct radius_hdr *)dat;
964 len = EXTRACT_16BITS(&rad->len);
965
966 if (len < MIN_RADIUS_LEN)
967 {
968 ND_PRINT((ndo, "%s", tstr));
969 return;
970 }
971
972 if (len > length)
973 len = length;
974
975 if (ndo->ndo_vflag < 1) {
976 ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u",
977 tok2str(radius_command_values,"Unknown Command",rad->code),
978 rad->code,
979 rad->id,
980 len));
981 return;
982 }
983 else {
984 ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
985 len,
986 tok2str(radius_command_values,"Unknown Command",rad->code),
987 rad->code,
988 rad->id));
989
990 for(auth_idx=0; auth_idx < 16; auth_idx++)
991 ND_PRINT((ndo, "%02x", rad->auth[auth_idx]));
992 }
993
994 if (len > MIN_RADIUS_LEN)
995 radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
996 return;
997
998 trunc:
999 ND_PRINT((ndo, "%s", tstr));
1000 }