2004-03-31 20:57:42 +00:00
|
|
|
/* packet-radius.c
|
|
|
|
*
|
|
|
|
* Routines for RADIUS packet disassembly
|
|
|
|
* Copyright 1999 Johan Feyaerts
|
|
|
|
* Changed 03/12/2003 Rui Carmo (http://the.taoofmac.com - added all 3GPP VSAs, some parsing)
|
2005-07-15 21:12:27 +00:00
|
|
|
* Changed 07/2005 Luis Ontanon <luis.ontanon@gmail.com> - use FreeRADIUS' dictionary
|
2004-03-31 20:57:42 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
2004-03-31 20:57:42 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
2004-10-04 20:13:35 +00:00
|
|
|
*
|
2004-09-20 19:20:05 +00:00
|
|
|
* References:
|
2004-10-04 20:13:35 +00:00
|
|
|
*
|
|
|
|
* RFC 2865 - Remote Authentication Dial In User Service (RADIUS)
|
|
|
|
* RFC 2866 - RADIUS Accounting
|
|
|
|
* RFC 2867 - RADIUS Accounting Modifications for Tunnel Protocol Support
|
|
|
|
* RFC 2868 - RADIUS Attributes for Tunnel Protocol Support
|
|
|
|
* RFC 2869 - RADIUS Extensions
|
2005-07-15 21:12:27 +00:00
|
|
|
* RFC 3162 - RADIUS and IPv6
|
|
|
|
* RFC 3576 - Dynamic Authorization Extensions to RADIUS
|
2004-10-05 08:09:58 +00:00
|
|
|
*
|
|
|
|
* See also
|
|
|
|
*
|
|
|
|
* http://www.iana.org/assignments/radius-types
|
2004-10-04 20:13:35 +00:00
|
|
|
*/
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-10-04 20:13:35 +00:00
|
|
|
/*
|
2005-07-15 21:12:27 +00:00
|
|
|
TO (re)DO: (see svn rev 14786)
|
|
|
|
- dissect_3gpp_ipv6_dns_servers()
|
2004-03-31 20:57:42 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
2005-07-15 21:12:27 +00:00
|
|
|
#include <errno.h>
|
2004-03-31 20:57:42 +00:00
|
|
|
#include <epan/packet.h>
|
2005-07-15 21:12:27 +00:00
|
|
|
#include <epan/prefs.h>
|
|
|
|
#include <epan/report_err.h>
|
2004-09-30 18:26:35 +00:00
|
|
|
#include <epan/prefs.h>
|
|
|
|
#include <epan/crypt-md5.h>
|
2004-09-30 20:27:47 +00:00
|
|
|
#include <epan/sminmpec.h>
|
2005-07-15 21:12:27 +00:00
|
|
|
#include <epan/filesystem.h>
|
2005-07-24 02:53:09 +00:00
|
|
|
#include <epan/emem.h>
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
#include "packet-radius.h"
|
2004-08-25 05:14:17 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
typedef struct _e_radiushdr {
|
|
|
|
guint8 rh_code;
|
|
|
|
guint8 rh_ident;
|
|
|
|
guint16 rh_pktlength;
|
|
|
|
} e_radiushdr;
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
typedef struct {
|
|
|
|
GArray* hf;
|
|
|
|
GArray* ett;
|
|
|
|
GArray* vend_vs;
|
|
|
|
} hfett_t;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
#define AUTHENTICATOR_LENGTH 16
|
|
|
|
#define RD_HDR_LENGTH 4
|
|
|
|
#define MAX_RADIUS_PACKET_SIZE 4096
|
2004-03-31 20:57:42 +00:00
|
|
|
|
|
|
|
#define UDP_PORT_RADIUS 1645
|
|
|
|
#define UDP_PORT_RADIUS_NEW 1812
|
|
|
|
#define UDP_PORT_RADACCT 1646
|
|
|
|
#define UDP_PORT_RADACCT_NEW 1813
|
|
|
|
|
|
|
|
#define RADIUS_ACCESS_REQUEST 1
|
|
|
|
#define RADIUS_ACCESS_ACCEPT 2
|
|
|
|
#define RADIUS_ACCESS_REJECT 3
|
|
|
|
#define RADIUS_ACCOUNTING_REQUEST 4
|
|
|
|
#define RADIUS_ACCOUNTING_RESPONSE 5
|
|
|
|
#define RADIUS_ACCOUNTING_STATUS 6
|
|
|
|
#define RADIUS_ACCESS_PASSWORD_REQUEST 7
|
|
|
|
#define RADIUS_ACCESS_PASSWORD_ACK 8
|
2005-07-15 21:12:27 +00:00
|
|
|
#define RADIUS_ACCESS_PASSWORD_REJECT 9
|
|
|
|
#define RADIUS_ACCOUNTING_MESSAGE 10
|
|
|
|
#define RADIUS_ACCESS_CHALLENGE 11
|
|
|
|
#define RADIUS_STATUS_SERVER 12
|
|
|
|
#define RADIUS_STATUS_CLIENT 13
|
2005-03-07 11:35:52 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
#define RADIUS_VENDOR_SPECIFIC_CODE 26
|
|
|
|
#define RADIUS_ASCEND_ACCESS_NEXT_CODE 29
|
|
|
|
#define RADIUS_ASCEND_ACCESS_NEW_PIN 30
|
|
|
|
#define RADIUS_ASCEND_PASSWORD_EXPIRED 32
|
|
|
|
#define RADIUS_ASCEND_ACCESS_EVENT_REQUEST 33
|
|
|
|
#define RADIUS_ASCEND_ACCESS_EVENT_RESPONSE 34
|
|
|
|
#define RADIUS_DISCONNECT_REQUEST 40
|
|
|
|
#define RADIUS_DISCONNECT_REQUEST_ACK 41
|
|
|
|
#define RADIUS_DISCONNECT_REQUEST_NAK 42
|
|
|
|
#define RADIUS_CHANGE_FILTER_REQUEST 43
|
|
|
|
#define RADIUS_CHANGE_FILTER_REQUEST_ACK 44
|
|
|
|
#define RADIUS_CHANGE_FILTER_REQUEST_NAK 45
|
|
|
|
#define RADIUS_EAP_MESSAGE_CODE 79
|
|
|
|
#define RADIUS_RESERVED 255
|
2004-10-01 07:01:53 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static radius_dictionary_t* dict = NULL;
|
2004-10-01 07:01:53 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static int proto_radius = -1;
|
|
|
|
static int hf_radius_id = -1;
|
|
|
|
static int hf_radius_code = -1;
|
|
|
|
static int hf_radius_length = -1;
|
|
|
|
static int hf_radius_authenticator = -1;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static int hf_radius_cosine_vpi = -1;
|
|
|
|
static int hf_radius_cosine_vci = -1;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static gint ett_radius = -1;
|
|
|
|
static gint ett_radius_avp = -1;
|
|
|
|
static gint ett_eap = -1;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
radius_attr_info_t no_dictionary_entry = {"Unknown-Attribute",0,FALSE,FALSE,radius_octets, NULL, NULL, -1, -1, -1, -1, -1 };
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
dissector_handle_t eap_fragment_handle;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static gchar* shared_secret = "";
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static guint8 authenticator[AUTHENTICATOR_LENGTH];
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static const value_string* radius_vendors = NULL;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static const value_string radius_vals[] =
|
2004-03-31 20:57:42 +00:00
|
|
|
{
|
2005-07-15 21:12:27 +00:00
|
|
|
{RADIUS_ACCESS_REQUEST, "Access-Request"},
|
|
|
|
{RADIUS_ACCESS_ACCEPT, "Access-Accept"},
|
|
|
|
{RADIUS_ACCESS_REJECT, "Access-Reject"},
|
|
|
|
{RADIUS_ACCOUNTING_REQUEST, "Accounting-Request"},
|
|
|
|
{RADIUS_ACCOUNTING_RESPONSE, "Accounting-Response"},
|
|
|
|
{RADIUS_ACCOUNTING_STATUS, "Accounting-Status"},
|
|
|
|
{RADIUS_ACCESS_PASSWORD_REQUEST, "Access-Password-Request"},
|
|
|
|
{RADIUS_ACCESS_PASSWORD_ACK, "Access-Password-Ack"},
|
|
|
|
{RADIUS_ACCESS_PASSWORD_REJECT, "Access-Password-Reject"},
|
|
|
|
{RADIUS_ACCOUNTING_MESSAGE, "Accounting-Message"},
|
|
|
|
{RADIUS_ACCESS_CHALLENGE, "Access-challenge"},
|
|
|
|
{RADIUS_STATUS_SERVER, "StatusServer"},
|
|
|
|
{RADIUS_STATUS_CLIENT, "StatusClient"},
|
|
|
|
{RADIUS_VENDOR_SPECIFIC_CODE, "Vendor-Specific"},
|
|
|
|
{RADIUS_ASCEND_ACCESS_NEXT_CODE, "Ascend-Access-Next-Code"},
|
|
|
|
{RADIUS_ASCEND_ACCESS_NEW_PIN, "Ascend-Access-New-Pin"},
|
|
|
|
{RADIUS_ASCEND_PASSWORD_EXPIRED, "Ascend-Password-Expired"},
|
|
|
|
{RADIUS_ASCEND_ACCESS_EVENT_REQUEST, "Ascend-Access-Event-Request"},
|
|
|
|
{RADIUS_ASCEND_ACCESS_EVENT_RESPONSE, "Ascend-Access-Event-Response"},
|
|
|
|
{RADIUS_DISCONNECT_REQUEST, "Disconnect-Request"},
|
|
|
|
{RADIUS_DISCONNECT_REQUEST_ACK, "Disconnect-Request ACK"},
|
|
|
|
{RADIUS_DISCONNECT_REQUEST_NAK, "Disconnect-Request NAK"},
|
|
|
|
{RADIUS_CHANGE_FILTER_REQUEST, "Change-Filter-Request"},
|
|
|
|
{RADIUS_CHANGE_FILTER_REQUEST_ACK, "Change-Filter-Request-ACK"},
|
|
|
|
{RADIUS_CHANGE_FILTER_REQUEST_NAK, "Change-Filter-Request-NAK"},
|
|
|
|
{RADIUS_RESERVED, "Reserved"},
|
|
|
|
{0, NULL}
|
|
|
|
};
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static gchar* dissect_cosine_vpvc(proto_tree* tree, tvbuff_t* tvb) {
|
|
|
|
guint vpi, vci;
|
|
|
|
|
|
|
|
if ( tvb_length(tvb) != 4 )
|
|
|
|
return "[Wrong Lenght for VP/VC AVP]";
|
|
|
|
|
|
|
|
vpi = tvb_get_ntohs(tvb,0);
|
|
|
|
vci = tvb_get_ntohs(tvb,2);
|
|
|
|
|
|
|
|
proto_tree_add_uint(tree,hf_radius_cosine_vpi,tvb,0,2,vpi);
|
|
|
|
proto_tree_add_uint(tree,hf_radius_cosine_vci,tvb,2,2,vci);
|
|
|
|
|
2005-07-24 02:53:09 +00:00
|
|
|
return ep_strdup_printf("%u/%u",vpi,vci);
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-07-15 21:12:27 +00:00
|
|
|
radius_decrypt_avp(gchar *dest,tvbuff_t *tvb,int offset,int length)
|
2004-03-31 20:57:42 +00:00
|
|
|
{
|
|
|
|
md5_state_t md_ctx;
|
|
|
|
md5_byte_t digest[16];
|
2004-12-22 01:51:00 +00:00
|
|
|
int i;
|
|
|
|
int totlen;
|
2004-03-31 20:57:42 +00:00
|
|
|
const guint8 *pd;
|
|
|
|
guchar c;
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
dest[0] = '"';
|
|
|
|
dest[1] = '\0';
|
|
|
|
totlen = 1;
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
md5_init(&md_ctx);
|
2005-07-15 21:12:27 +00:00
|
|
|
md5_append(&md_ctx,(guint8*)shared_secret,strlen(shared_secret));
|
|
|
|
md5_append(&md_ctx,authenticator, AUTHENTICATOR_LENGTH);
|
2004-03-31 20:57:42 +00:00
|
|
|
md5_finish(&md_ctx,digest);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
pd = tvb_get_ptr(tvb,offset,length);
|
2005-07-15 21:12:27 +00:00
|
|
|
for( i = 0 ; i < AUTHENTICATOR_LENGTH && i < length ; i++ ) {
|
|
|
|
c = pd[i] ^ digest[i];
|
|
|
|
if ( isprint(c)) {
|
|
|
|
dest[totlen] = c;
|
|
|
|
totlen++;
|
|
|
|
} else {
|
|
|
|
sprintf(&(dest[totlen]),"\\%03o",c);
|
|
|
|
totlen += strlen(&(dest[totlen]));
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
2004-12-22 01:51:00 +00:00
|
|
|
while(i<length) {
|
2005-07-15 21:12:27 +00:00
|
|
|
if ( isprint(pd[i]) ) {
|
|
|
|
dest[totlen] = (gchar)pd[i];
|
|
|
|
totlen++;
|
|
|
|
} else {
|
|
|
|
sprintf(&(dest[totlen]), "\\%03o", pd[i]);
|
|
|
|
totlen=totlen+strlen(&(dest[totlen]));
|
|
|
|
}
|
|
|
|
i++;
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
|
|
|
dest[totlen]='"';
|
|
|
|
dest[totlen+1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_integer(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
guint32 uint;
|
2004-09-19 11:39:48 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
switch (len) {
|
|
|
|
case 2:
|
|
|
|
uint = tvb_get_ntohs(tvb,offset);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
uint = tvb_get_ntoh24(tvb,offset);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
uint = tvb_get_ntohl(tvb,offset);
|
|
|
|
break;
|
|
|
|
case 8: {
|
|
|
|
guint64 uint64 = tvb_get_ntoh64(tvb,offset);
|
|
|
|
proto_tree_add_uint64(tree,a->hf64,tvb,offset,len,uint64);
|
|
|
|
proto_item_append_text(avp_item, "%" PRIu64, uint64);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
proto_item_append_text(avp_item, "[unhandled integer length(%u)]", len);
|
|
|
|
return;
|
|
|
|
}
|
2004-10-05 08:27:21 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
proto_tree_add_uint(tree,a->hf,tvb,offset,len,uint);
|
2004-09-19 11:39:48 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
if (a->vs) {
|
|
|
|
proto_item_append_text(avp_item, "%s(%u)", val_to_str(uint, a->vs, "Unknown"),uint);
|
|
|
|
} else {
|
|
|
|
proto_item_append_text(avp_item, "%u", uint);
|
|
|
|
}
|
2004-09-19 11:39:48 +00:00
|
|
|
}
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_string(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
if (a->encrypt) {
|
|
|
|
if (*shared_secret == '\0') {
|
|
|
|
proto_item_append_text(avp_item, "Encrypted");
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
} else {
|
|
|
|
gchar buffer[1024]; /* an AVP value can be at most 253 bytes */
|
|
|
|
radius_decrypt_avp(buffer,tvb,offset,len);
|
|
|
|
proto_item_append_text(avp_item, "Decrypted: %s", buffer);
|
|
|
|
proto_tree_add_string(tree, a->hf, tvb, offset, len, buffer);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
proto_item_append_text(avp_item, "%s", tvb_format_text(tvb, offset, len));
|
|
|
|
}
|
2004-12-22 00:23:55 +00:00
|
|
|
}
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_octets(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
proto_item_append_text(avp_item, "%s", tvb_bytes_to_str(tvb, offset, len));
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_ipaddr(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
guint32 uint;
|
|
|
|
gchar buf[16];
|
|
|
|
|
|
|
|
if (len != 4) {
|
|
|
|
proto_item_append_text(avp_item, "[wrong lenght for IP address]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint = tvb_get_ntohl(tvb,offset);
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
ip_to_str_buf((guint8*)&uint, buf);
|
|
|
|
proto_item_append_text(avp_item, "%s", buf);
|
|
|
|
}
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_ipv6addr(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
guint8 ipv6_buff[64];
|
|
|
|
gchar txtbuf[256];
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
/* XXX ??? */
|
|
|
|
if (len != 16) {
|
|
|
|
proto_item_append_text(avp_item, "[wrong lenght for IPv6 address]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
|
|
|
|
tvb_memcpy(tvb, ipv6_buff, offset, len);
|
|
|
|
ip6_to_str_buf((struct e_in6_addr *)ipv6_buff, txtbuf);
|
|
|
|
proto_item_append_text(avp_item, "%s", txtbuf);
|
|
|
|
}
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_date(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
nstime_t time_ptr;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
if (len != 4) {
|
|
|
|
proto_item_append_text(avp_item, "[wrong lenght for timestamp]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
time_ptr.secs = tvb_get_ntohl(tvb,offset);
|
|
|
|
time_ptr.nsecs = 0;
|
|
|
|
|
|
|
|
proto_tree_add_time(tree, a->hf, tvb, offset, len, &time_ptr);
|
|
|
|
proto_item_append_text(avp_item, "%s", abs_time_to_str(&time_ptr));
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_abinary(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
proto_item_append_text(avp_item, "%s", tvb_bytes_to_str(tvb, offset, len));
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
void radius_ifid(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
|
|
|
|
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
|
|
|
|
proto_item_append_text(avp_item, "%s", tvb_bytes_to_str(tvb, offset, len));
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static void dissect_attribute_value_pairs(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int length) {
|
|
|
|
gboolean last_eap = FALSE;
|
2005-07-24 02:53:09 +00:00
|
|
|
guint8* eap_buffer = NULL;
|
2005-07-15 21:12:27 +00:00
|
|
|
guint eap_seg_num = 0;
|
|
|
|
guint eap_tot_len = 0;
|
|
|
|
proto_tree* eap_tree = NULL;
|
|
|
|
tvbuff_t* eap_tvb = NULL;
|
2004-12-22 01:42:54 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
if (length == 0) {
|
|
|
|
proto_tree_add_text(tree, tvb,offset,0,"No Attribute Value Pairs Found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
radius_attr_info_t* dictionary_entry = NULL;
|
|
|
|
radius_vendor_info_t* vendor = NULL;
|
|
|
|
guint32 avp_type = tvb_get_guint8(tvb,offset);
|
|
|
|
guint32 avp_length = tvb_get_guint8(tvb,offset+1);
|
|
|
|
guint32 vendor_id = 0;
|
|
|
|
guint32 avp_vsa_type = 0;
|
|
|
|
guint32 avp_vsa_len = 0;
|
2005-07-24 02:53:09 +00:00
|
|
|
proto_item* avp_item = proto_tree_add_text(tree,tvb,offset,avp_length,"AVP: l=%u ",avp_length);
|
2005-07-15 21:12:27 +00:00
|
|
|
proto_item* avp_len_item;
|
|
|
|
proto_tree* avp_tree;
|
|
|
|
|
2005-07-24 02:53:09 +00:00
|
|
|
tvb_ensure_length_remaining(tvb, offset + avp_length - 1);
|
|
|
|
|
|
|
|
length -= avp_length;
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
if (avp_length < 3) {
|
2005-07-24 02:53:09 +00:00
|
|
|
proto_item_append_text(avp_item, "[AVP TOO SHORT]");
|
2005-07-15 21:12:27 +00:00
|
|
|
return;
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
avp_item = proto_tree_add_text(tree,tvb,offset,avp_length,"AVP: l=%u ",avp_length);
|
|
|
|
|
|
|
|
if (avp_type == RADIUS_VENDOR_SPECIFIC_CODE) {
|
2005-07-24 02:53:09 +00:00
|
|
|
/* XXX TODO: handle 2 byte codes for USR */
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
vendor_id = tvb_get_ntohl(tvb,offset+2);
|
|
|
|
avp_vsa_type = tvb_get_guint8(tvb,offset+6);
|
|
|
|
avp_vsa_len = tvb_get_guint8(tvb,offset+7);
|
|
|
|
|
|
|
|
vendor = g_hash_table_lookup(dict->vendors_by_id,GUINT_TO_POINTER(vendor_id));
|
|
|
|
|
|
|
|
if (vendor) {
|
|
|
|
proto_item_append_text(avp_item, "v=%s(%u)", vendor->name,vendor_id);
|
|
|
|
|
|
|
|
dictionary_entry = g_hash_table_lookup(vendor->attrs_by_id,GUINT_TO_POINTER(avp_vsa_type));
|
|
|
|
} else {
|
|
|
|
proto_item_append_text(avp_item, "v=Unknown(%u)", vendor_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! dictionary_entry ) {
|
|
|
|
dictionary_entry = &no_dictionary_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item_append_text(avp_item, " t=%s(%u)", dictionary_entry->name,avp_vsa_type);
|
|
|
|
|
|
|
|
avp_length -= 8;
|
|
|
|
offset += 8;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
} else if (avp_type == RADIUS_EAP_MESSAGE_CODE) {
|
|
|
|
guint eap_seg_len = avp_length - 2;
|
|
|
|
|
2005-07-24 02:53:09 +00:00
|
|
|
if (! eap_buffer) eap_buffer = ep_alloc(MAX_RADIUS_PACKET_SIZE);
|
|
|
|
|
|
|
|
if (eap_tot_len + eap_seg_len > MAX_RADIUS_PACKET_SIZE) {
|
2005-07-15 21:12:27 +00:00
|
|
|
proto_tree_add_text(tree, tvb,offset,0,"[Eap-Message longer than maximum radius packet size]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tvb_memcpy(tvb,eap_buffer + eap_tot_len, offset+2, eap_seg_len);
|
|
|
|
eap_tot_len += eap_seg_len;
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
eap_seg_num++;
|
|
|
|
|
|
|
|
if ( tvb_bytes_exist(tvb, offset, avp_length + 3) ) {
|
|
|
|
guint8 next_type = tvb_get_guint8(tvb, offset + avp_length);
|
|
|
|
|
|
|
|
if ( next_type != RADIUS_EAP_MESSAGE_CODE ) {
|
|
|
|
last_eap = TRUE;
|
2004-09-19 11:39:48 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
} else {
|
|
|
|
last_eap = TRUE;
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
if (last_eap) {
|
|
|
|
|
|
|
|
proto_item_append_text(avp_item, "t=EAP-Message(79) Last Segment[%u]",eap_seg_num);
|
|
|
|
|
|
|
|
eap_tree = proto_item_add_subtree(avp_item,ett_eap);
|
|
|
|
|
|
|
|
eap_tvb = tvb_new_real_data(eap_buffer, eap_tot_len, eap_tot_len);
|
|
|
|
tvb_set_child_real_data_tvbuff(tvb, eap_tvb);
|
|
|
|
add_new_data_source(pinfo, eap_tvb, "Reassembled EAP");
|
|
|
|
|
2004-12-22 01:42:54 +00:00
|
|
|
} else {
|
2005-07-15 21:12:27 +00:00
|
|
|
proto_item_append_text(avp_item, "t=EAP-Message(79) Segment[%u]",eap_seg_num);
|
2004-12-22 01:42:54 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
offset += avp_length;
|
|
|
|
continue;
|
2004-12-22 01:42:54 +00:00
|
|
|
} else {
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
dictionary_entry = g_hash_table_lookup(dict->attrs_by_id,GUINT_TO_POINTER(avp_type));
|
|
|
|
|
|
|
|
if (! dictionary_entry ) {
|
|
|
|
dictionary_entry = &no_dictionary_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_item_append_text(avp_item, " t=%s(%u)", dictionary_entry->name, avp_type);
|
|
|
|
|
|
|
|
avp_length -= 2;
|
|
|
|
offset += 2;
|
2004-12-22 01:42:54 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
avp_tree = proto_item_add_subtree(avp_item,dictionary_entry->ett);
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
avp_len_item = proto_tree_add_uint(avp_tree,
|
|
|
|
dictionary_entry->hf_len,
|
|
|
|
tvb,0,0,avp_length);
|
|
|
|
PROTO_ITEM_SET_GENERATED(avp_len_item);
|
|
|
|
|
|
|
|
if (dictionary_entry->tagged) {
|
|
|
|
|
|
|
|
guint tag = tvb_get_guint8(tvb,offset);
|
|
|
|
|
|
|
|
if (tag <= 0x1f) {
|
|
|
|
|
|
|
|
proto_tree_add_uint(avp_tree,dictionary_entry->hf_tag,tvb,offset,1,tag);
|
|
|
|
|
|
|
|
proto_item_append_text(avp_item, " Tag=0x%.2x", tag);
|
|
|
|
|
|
|
|
offset++;
|
|
|
|
avp_length--;
|
2004-10-04 20:13:35 +00:00
|
|
|
}
|
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
if ( dictionary_entry->dissector ) {
|
|
|
|
tvbuff_t* tvb_value;
|
|
|
|
gchar* str;
|
|
|
|
|
|
|
|
tvb_value = tvb_new_subset(tvb, offset, (gint) avp_length, (gint) avp_length);
|
|
|
|
|
|
|
|
str = dictionary_entry->dissector(avp_tree,tvb_value);
|
|
|
|
|
|
|
|
proto_item_append_text(avp_item, ": %s",str);
|
|
|
|
} else {
|
|
|
|
proto_item_append_text(avp_item, ": ");
|
|
|
|
|
|
|
|
dictionary_entry->type(dictionary_entry,avp_tree,pinfo,tvb,offset,avp_length,avp_item);
|
2004-10-04 20:13:35 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
offset += avp_length;
|
|
|
|
|
|
|
|
} while (length > 0);
|
|
|
|
|
|
|
|
/* dulcis in fundo we call the EAP dissector */
|
|
|
|
if (eap_tree && eap_tvb )
|
|
|
|
call_dissector(eap_fragment_handle, eap_tvb, pinfo, eap_tree);
|
2004-10-04 20:13:35 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
2005-07-15 21:12:27 +00:00
|
|
|
proto_tree *radius_tree = NULL;
|
|
|
|
proto_tree *avptree = NULL;
|
|
|
|
proto_item *ti;
|
|
|
|
proto_item *avptf;
|
|
|
|
guint rhlength;
|
|
|
|
guint rhcode;
|
|
|
|
guint rhident;
|
|
|
|
gint avplength,hdrlength;
|
|
|
|
e_radiushdr rh;
|
|
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
2004-03-31 20:57:42 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "RADIUS");
|
2005-07-15 21:12:27 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
2004-03-31 20:57:42 +00:00
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
tvb_memcpy(tvb,(guint8 *)&rh,0,sizeof(e_radiushdr));
|
|
|
|
|
|
|
|
rhcode = rh.rh_code;
|
|
|
|
rhident = rh.rh_ident;
|
|
|
|
rhlength = g_ntohs(rh.rh_pktlength);
|
|
|
|
hdrlength = RD_HDR_LENGTH + AUTHENTICATOR_LENGTH;
|
|
|
|
avplength = rhlength - hdrlength;
|
|
|
|
/* XXX Check for valid length value:
|
|
|
|
* Length
|
|
|
|
*
|
|
|
|
* The Length field is two octets. It indicates the length of the
|
|
|
|
* packet including the Code, Identifier, Length, Authenticator and
|
|
|
|
* Attribute fields. Octets outside the range of the Length field
|
|
|
|
* MUST be treated as padding and ignored on reception. If the
|
|
|
|
* packet is shorter than the Length field indicates, it MUST be
|
|
|
|
* silently discarded. The minimum length is 20 and maximum length
|
|
|
|
* is 4096.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
{
|
2004-03-31 20:57:42 +00:00
|
|
|
col_add_fstr(pinfo->cinfo,COL_INFO,"%s(%d) (id=%d, l=%d)",
|
2005-07-15 21:12:27 +00:00
|
|
|
val_to_str(rhcode,radius_vals,"Unknown Packet"),
|
|
|
|
rhcode, rhident, rhlength);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree)
|
|
|
|
{
|
2004-03-31 20:57:42 +00:00
|
|
|
ti = proto_tree_add_item(tree,proto_radius, tvb, 0, rhlength, FALSE);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
radius_tree = proto_item_add_subtree(ti, ett_radius);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
proto_tree_add_uint(radius_tree,hf_radius_code, tvb, 0, 1, rh.rh_code);
|
|
|
|
|
|
|
|
proto_tree_add_uint_format(radius_tree,hf_radius_id, tvb, 1, 1, rh.rh_ident,
|
|
|
|
"Packet identifier: 0x%01x (%d)", rhident,rhident);
|
|
|
|
|
|
|
|
if (avplength >= 0) {
|
|
|
|
proto_tree_add_uint(radius_tree, hf_radius_length, tvb,
|
|
|
|
2, 2, rhlength);
|
|
|
|
} else {
|
|
|
|
proto_tree_add_text(radius_tree, tvb, 2, 2, "Bogus header length: %d",
|
|
|
|
rhlength);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree_add_item(radius_tree, hf_radius_authenticator, tvb, 4,AUTHENTICATOR_LENGTH,FALSE);
|
|
|
|
tvb_memcpy(tvb,authenticator,0,AUTHENTICATOR_LENGTH);
|
|
|
|
|
|
|
|
if (avplength > 0) {
|
|
|
|
/* list the attribute value pairs */
|
|
|
|
avptf = proto_tree_add_text(radius_tree, tvb,hdrlength,avplength,"Attribute Value Pairs");
|
|
|
|
avptree = proto_item_add_subtree(avptf, ett_radius_avp);
|
|
|
|
|
|
|
|
dissect_attribute_value_pairs(avptree, pinfo, tvb, hdrlength, avplength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static void register_attrs(gpointer k _U_, gpointer v, gpointer p) {
|
|
|
|
radius_attr_info_t* a = v;
|
|
|
|
int i;
|
|
|
|
gint* ett = &(a->ett);
|
|
|
|
gchar* abbrev = g_strdup_printf("radius.%s",a->name);
|
|
|
|
hf_register_info hfri[] = {
|
|
|
|
{ NULL, { NULL,NULL, FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
|
|
{ NULL, { NULL,NULL, FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ NULL, { NULL,NULL, FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
|
|
{ NULL, { NULL,NULL, FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}
|
|
|
|
};
|
|
|
|
guint len_hf = 2;
|
|
|
|
hfett_t* ri = p;
|
|
|
|
|
|
|
|
for(i=0; abbrev[i]; i++) {
|
|
|
|
if(abbrev[i] == '-') abbrev[i] = '_';
|
2004-12-08 15:19:10 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
hfri[0].p_id = &(a->hf);
|
|
|
|
hfri[1].p_id = &(a->hf_len);
|
|
|
|
|
|
|
|
hfri[0].hfinfo.name = a->name;
|
|
|
|
hfri[0].hfinfo.abbrev = abbrev;
|
|
|
|
|
|
|
|
hfri[1].hfinfo.name = "Length";
|
|
|
|
hfri[1].hfinfo.abbrev = g_strdup_printf("%s.len",abbrev);
|
|
|
|
hfri[1].hfinfo.blurb = g_strdup_printf("%s Length",a->name);
|
|
|
|
|
|
|
|
if (a->type == radius_integer) {
|
|
|
|
hfri[0].hfinfo.type = FT_UINT32;
|
|
|
|
hfri[0].hfinfo.display = BASE_DEC;
|
|
|
|
|
|
|
|
hfri[2].p_id = &(a->hf64);
|
|
|
|
hfri[2].hfinfo.name = g_strdup(a->name);
|
|
|
|
hfri[2].hfinfo.abbrev = abbrev;
|
|
|
|
hfri[2].hfinfo.type = FT_UINT64;
|
|
|
|
hfri[2].hfinfo.display = BASE_DEC;
|
|
|
|
|
|
|
|
if (a->vs) {
|
|
|
|
hfri[0].hfinfo.strings = VALS(a->vs);
|
|
|
|
}
|
|
|
|
|
|
|
|
len_hf++;
|
|
|
|
|
|
|
|
} else if (a->type == radius_string) {
|
|
|
|
hfri[0].hfinfo.type = FT_STRING;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
|
|
|
} else if (a->type == radius_octets) {
|
|
|
|
hfri[0].hfinfo.type = FT_BYTES;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
|
|
|
} else if (a->type == radius_ipaddr) {
|
|
|
|
hfri[0].hfinfo.type = FT_IPv4;
|
|
|
|
hfri[0].hfinfo.display = BASE_DEC;
|
|
|
|
} else if (a->type == radius_ipv6addr) {
|
|
|
|
hfri[0].hfinfo.type = FT_IPv6;
|
|
|
|
hfri[0].hfinfo.display = BASE_HEX;
|
|
|
|
} else if (a->type == radius_date) {
|
|
|
|
hfri[0].hfinfo.type = FT_ABSOLUTE_TIME;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
|
|
|
} else if (a->type == radius_abinary) {
|
|
|
|
hfri[0].hfinfo.type = FT_BYTES;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
|
|
|
} else if (a->type == radius_ifid) {
|
|
|
|
hfri[0].hfinfo.type = FT_BYTES;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
|
|
|
} else {
|
|
|
|
hfri[0].hfinfo.type = FT_BYTES;
|
|
|
|
hfri[0].hfinfo.display = BASE_NONE;
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
if (a->tagged) {
|
|
|
|
hfri[len_hf].p_id = &(a->hf_tag);
|
|
|
|
hfri[len_hf].hfinfo.name = "Tag";
|
|
|
|
hfri[len_hf].hfinfo.abbrev = g_strdup_printf("%s.tag",abbrev);
|
|
|
|
hfri[len_hf].hfinfo.blurb = g_strdup_printf("%s Tag",a->name);
|
|
|
|
hfri[len_hf].hfinfo.type = FT_UINT8;
|
|
|
|
hfri[len_hf].hfinfo.display = BASE_HEX;
|
|
|
|
len_hf++;
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
g_array_append_vals(ri->hf,hfri,len_hf);
|
|
|
|
g_array_append_val(ri->ett,ett);
|
|
|
|
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
static void register_vendors(gpointer k _U_, gpointer v, gpointer p) {
|
|
|
|
radius_vendor_info_t* vnd = v;
|
|
|
|
hfett_t* ri = p;
|
|
|
|
value_string vnd_vs;
|
|
|
|
|
|
|
|
vnd_vs.value = vnd->code;
|
|
|
|
vnd_vs.strptr = vnd->name;
|
|
|
|
|
|
|
|
g_array_append_val(ri->vend_vs,vnd_vs);
|
|
|
|
|
|
|
|
g_hash_table_foreach(vnd->attrs_by_id,register_attrs,ri);
|
|
|
|
}
|
2004-03-31 20:57:42 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
extern void radius_register_avp_dissector(guint32 vendor_id, guint32 attribute_id, radius_avp_dissector_t radius_avp_dissector) {
|
|
|
|
radius_vendor_info_t* vendor;
|
|
|
|
radius_attr_info_t* dictionary_entry;
|
|
|
|
GHashTable* by_id;
|
|
|
|
|
|
|
|
g_assert(radius_avp_dissector != NULL);
|
|
|
|
|
|
|
|
if (vendor_id) {
|
|
|
|
vendor = g_hash_table_lookup(dict->vendors_by_id,GUINT_TO_POINTER(vendor_id));
|
|
|
|
|
|
|
|
if ( ! vendor ) {
|
|
|
|
vendor = g_malloc(sizeof(radius_vendor_info_t));
|
|
|
|
|
|
|
|
vendor->name = g_strdup_printf("Unknown-Vendor-%u",vendor_id);
|
|
|
|
vendor->code = vendor_id;
|
|
|
|
vendor->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
|
|
|
|
|
|
|
|
g_hash_table_insert(dict->vendors_by_id,GUINT_TO_POINTER(vendor->code),vendor);
|
|
|
|
g_hash_table_insert(dict->vendors_by_name,vendor->name,vendor);
|
|
|
|
}
|
|
|
|
|
|
|
|
dictionary_entry = g_hash_table_lookup(vendor->attrs_by_id,GUINT_TO_POINTER(attribute_id));
|
|
|
|
by_id = vendor->attrs_by_id;
|
|
|
|
} else {
|
|
|
|
dictionary_entry = g_hash_table_lookup(dict->attrs_by_id,GUINT_TO_POINTER(attribute_id));
|
|
|
|
by_id = dict->attrs_by_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dictionary_entry) {
|
|
|
|
dictionary_entry = g_malloc(sizeof(radius_attr_info_t));;
|
|
|
|
|
|
|
|
dictionary_entry->name = g_strdup_printf("Unknown-Attribute-%u",attribute_id);
|
|
|
|
dictionary_entry->code = attribute_id;
|
|
|
|
dictionary_entry->encrypt = FALSE;
|
|
|
|
dictionary_entry->type = NULL;
|
|
|
|
dictionary_entry->vs = NULL;
|
|
|
|
dictionary_entry->hf = no_dictionary_entry.hf;
|
|
|
|
dictionary_entry->hf_len = no_dictionary_entry.hf_len;
|
|
|
|
dictionary_entry->ett = no_dictionary_entry.ett;
|
|
|
|
|
|
|
|
g_hash_table_insert(by_id,GUINT_TO_POINTER(dictionary_entry->code),dictionary_entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
dictionary_entry->dissector = radius_avp_dissector;
|
2004-03-31 20:57:42 +00:00
|
|
|
|
|
|
|
}
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
void
|
|
|
|
proto_register_radius(void)
|
|
|
|
{
|
2005-07-15 21:12:27 +00:00
|
|
|
hf_register_info base_hf[] = {
|
|
|
|
{ &hf_radius_code,
|
|
|
|
{ "Code","radius.code", FT_UINT8, BASE_DEC, VALS(radius_vals), 0x0,
|
|
|
|
"", HFILL }},
|
2005-02-08 18:51:27 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &hf_radius_id,
|
|
|
|
{ "Identifier", "radius.id", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2005-02-08 18:51:27 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &hf_radius_authenticator,
|
|
|
|
{ "Authenticator", "radius.authenticator", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2005-02-08 18:51:27 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &hf_radius_length,
|
|
|
|
{ "Length","radius.length", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2005-02-08 18:51:27 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &(no_dictionary_entry.hf),
|
|
|
|
{ "Unknown-Attribute","radius.Unknown_Attribute", FT_BYTES, BASE_HEX, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &(no_dictionary_entry.hf_len),
|
|
|
|
{ "Unknown-Attribute Length","radius.Unknown_Attribute.length", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_radius_cosine_vpi,
|
|
|
|
{ "Cosine-VPI","radius.Cosine-Vpi", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
{ &hf_radius_cosine_vci,
|
|
|
|
{ "Cosine-VCI","radius.Cosine-Vci", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-10-04 20:13:35 +00:00
|
|
|
};
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
gint *base_ett[] = {
|
2004-03-31 20:57:42 +00:00
|
|
|
&ett_radius,
|
|
|
|
&ett_radius_avp,
|
2005-07-15 21:12:27 +00:00
|
|
|
&ett_eap,
|
|
|
|
&(no_dictionary_entry.ett),
|
2004-03-31 20:57:42 +00:00
|
|
|
};
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
module_t *radius_module;
|
2005-07-15 21:12:27 +00:00
|
|
|
hfett_t ri;
|
|
|
|
char* dir = NULL;
|
|
|
|
gchar* dict_err_str = NULL;
|
|
|
|
|
|
|
|
ri.hf = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
|
2005-07-17 22:16:59 +00:00
|
|
|
ri.ett = g_array_new(FALSE,TRUE,sizeof(gint *));
|
2005-07-15 21:12:27 +00:00
|
|
|
ri.vend_vs = g_array_new(TRUE,TRUE,sizeof(value_string));
|
|
|
|
|
|
|
|
g_array_append_vals(ri.hf, base_hf, array_length(base_hf));
|
2005-07-17 22:30:56 +00:00
|
|
|
g_array_append_vals(ri.ett, base_ett, array_length(base_ett));
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
dir = get_persconffile_path("radius", FALSE);
|
|
|
|
|
|
|
|
if (test_for_directory(dir) != EISDIR) {
|
|
|
|
|
|
|
|
dir = get_datafile_path("radius");
|
|
|
|
|
|
|
|
if (test_for_directory(dir) != EISDIR) {
|
|
|
|
dir = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir) {
|
|
|
|
dict = radius_load_dictionary(dir,"dictionary",&dict_err_str);
|
|
|
|
} else {
|
|
|
|
dict = NULL;
|
2005-07-16 01:55:58 +00:00
|
|
|
dict_err_str = g_strdup("Could not find the radius directory");
|
2005-07-15 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dict_err_str) {
|
2005-07-24 02:53:09 +00:00
|
|
|
g_warning("radius: %s",dict_err_str);
|
2005-07-16 01:55:58 +00:00
|
|
|
g_free(dict_err_str);
|
2005-07-15 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dict) {
|
|
|
|
g_hash_table_foreach(dict->attrs_by_id,register_attrs,&ri);
|
|
|
|
g_hash_table_foreach(dict->vendors_by_id,register_vendors,&ri);
|
|
|
|
} else {
|
2005-07-24 02:53:09 +00:00
|
|
|
/* XXX: TODO load a default dictionary */
|
2005-07-15 21:12:27 +00:00
|
|
|
dict = g_malloc(sizeof(radius_dictionary_t));
|
|
|
|
|
|
|
|
dict->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
|
|
|
|
dict->attrs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
|
|
|
|
dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
|
2005-07-24 02:53:09 +00:00
|
|
|
dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
|
2005-07-15 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
radius_vendors = (value_string*) ri.vend_vs->data;
|
|
|
|
|
2005-07-24 02:53:09 +00:00
|
|
|
proto_radius = proto_register_protocol("Radius Protocol", "RADIUS", "radius");
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
proto_register_field_array(proto_radius,(hf_register_info*)(ri.hf->data),ri.hf->len);
|
|
|
|
proto_register_subtree_array((gint**)(ri.ett->data), ri.ett->len);
|
2004-10-04 20:13:35 +00:00
|
|
|
|
2005-07-15 21:12:27 +00:00
|
|
|
g_array_free(ri.hf,FALSE);
|
|
|
|
g_array_free(ri.ett,FALSE);
|
|
|
|
g_array_free(ri.vend_vs,FALSE);
|
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
radius_module = prefs_register_protocol(proto_radius,NULL);
|
|
|
|
prefs_register_string_preference(radius_module,"shared_secret","Shared Secret",
|
|
|
|
"Shared secret used to decode User Passwords",
|
|
|
|
&shared_secret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_radius(void)
|
|
|
|
{
|
|
|
|
dissector_handle_t radius_handle;
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
eap_fragment_handle = find_dissector("eap_fragment");
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
radius_handle = create_dissector_handle(dissect_radius, proto_radius);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
dissector_add("udp.port", UDP_PORT_RADIUS, radius_handle);
|
|
|
|
dissector_add("udp.port", UDP_PORT_RADIUS_NEW, radius_handle);
|
|
|
|
dissector_add("udp.port", UDP_PORT_RADACCT, radius_handle);
|
|
|
|
dissector_add("udp.port", UDP_PORT_RADACCT_NEW, radius_handle);
|
2005-07-15 21:12:27 +00:00
|
|
|
|
|
|
|
radius_register_avp_dissector(VENDOR_COSINE,5,dissect_cosine_vpvc);
|
|
|
|
|
2004-03-31 20:57:42 +00:00
|
|
|
}
|