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