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