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