wireshark/epan/dissectors/packet-radius.c

1192 lines
38 KiB
C
Raw Normal View History

/* 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)
* Changed 07/2005 Luis Ontanon <luis.ontanon@gmail.com> - use FreeRADIUS' dictionary
*
* $Id$
*
* 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.
*
* References:
*
* 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
* RFC 3162 - RADIUS and IPv6
* RFC 3576 - Dynamic Authorization Extensions to RADIUS
*
* See also
*
* http://www.iana.org/assignments/radius-types
*/
/*
TO (re)DO: (see svn rev 14786)
- dissect_3gpp_ipv6_dns_servers()
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/report_err.h>
#include <epan/prefs.h>
#include <epan/crypt-md5.h>
#include <epan/sminmpec.h>
#include <epan/filesystem.h>
#include <epan/addr_resolv.h>
#include <epan/emem.h>
#include "packet-radius.h"
typedef struct _e_radiushdr {
guint8 rh_code;
guint8 rh_ident;
guint16 rh_pktlength;
} e_radiushdr;
typedef struct {
GArray* hf;
GArray* ett;
GArray* vend_vs;
} hfett_t;
#define AUTHENTICATOR_LENGTH 16
#define RD_HDR_LENGTH 4
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
#define HDR_LENGTH (RD_HDR_LENGTH + AUTHENTICATOR_LENGTH)
#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
#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
#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
static radius_dictionary_t* dict = NULL;
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;
static int hf_radius_framed_ip_address = -1;
static int hf_radius_login_ip_host = -1;
static int hf_radius_framed_ipx_network = -1;
static int hf_radius_cosine_vpi = -1;
static int hf_radius_cosine_vci = -1;
static gint ett_radius = -1;
static gint ett_radius_avp = -1;
static gint ett_eap = -1;
radius_vendor_info_t no_vendor = {"Unknown Vendor",0,NULL,-1};
radius_attr_info_t no_dictionary_entry = {"Unknown-Attribute",0,FALSE,FALSE,radius_octets, NULL, NULL, -1, -1, -1, -1, -1 };
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
dissector_handle_t eap_handle;
dissector_handle_t radius_handle;
static const gchar* shared_secret = "";
static gboolean show_length = FALSE;
static guint alt_port = 0;
static guint alt_port_pref = 0;
static guint8 authenticator[AUTHENTICATOR_LENGTH];
static const value_string* radius_vendors = NULL;
static const value_string radius_vals[] =
{
{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}
};
static const gchar *dissect_framed_ip_address(proto_tree* tree, tvbuff_t* tvb) {
int len;
guint32 ip;
guint32 ip_h;
const gchar *str;
len = tvb_length(tvb);
if (len != 4)
return "[wrong length for IP address]";
ip=tvb_get_ipv4(tvb,0);
ip_h=g_ntohl(ip);
if (ip_h == 0xFFFFFFFF) {
str = "Negotiated";
proto_tree_add_ipv4_format(tree, hf_radius_framed_ip_address,
tvb, 0, len, ip, "Framed-IP-Address: %s", str);
} else if (ip_h == 0xFFFFFFFE) {
str = "Assigned";
proto_tree_add_ipv4_format(tree, hf_radius_framed_ip_address,
tvb, 0, len, ip, "Framed-IP-Address: %s", str);
} else {
str = ip_to_str((guint8 *)&ip);
proto_tree_add_ipv4_format(tree, hf_radius_framed_ip_address,
tvb, 0, len, ip, "Framed-IP-Address: %s (%s)",
get_hostname(ip), str);
}
return str;
}
static const gchar *dissect_login_ip_host(proto_tree* tree, tvbuff_t* tvb) {
int len;
guint32 ip;
guint32 ip_h;
const gchar *str;
len = tvb_length(tvb);
if (len != 4)
return "[wrong length for IP address]";
ip=tvb_get_ipv4(tvb,0);
ip_h=g_ntohl(ip);
if (ip_h == 0xFFFFFFFF) {
str = "User-selected";
proto_tree_add_ipv4_format(tree, hf_radius_login_ip_host,
tvb, 0, len, ip, "Login-IP-Host: %s", str);
} else if (ip_h == 0) {
str = "NAS-selected";
proto_tree_add_ipv4_format(tree, hf_radius_login_ip_host,
tvb, 0, len, ip, "Login-IP-Host: %s", str);
} else {
str = ip_to_str((guint8 *)&ip);
proto_tree_add_ipv4_format(tree, hf_radius_framed_ip_address,
tvb, 0, len, ip, "Login-IP-Host: %s (%s)",
get_hostname(ip), str);
}
return str;
}
static const gchar *dissect_framed_ipx_network(proto_tree* tree, tvbuff_t* tvb) {
int len;
guint32 net;
const gchar *str;
len = tvb_length(tvb);
if (len != 4)
return "[wrong length for IPX network]";
net=tvb_get_ntohl(tvb,0);
if (net == 0xFFFFFFFE)
str = "NAS-selected";
else
str = ep_strdup_printf("0x%08X", net);
proto_tree_add_ipxnet_format(tree, hf_radius_framed_ipx_network, tvb, 0,
len, net, "Framed-IPX-Network: %s", str);
return str;
}
static const gchar* dissect_cosine_vpvc(proto_tree* tree, tvbuff_t* tvb) {
guint vpi, vci;
if ( tvb_length(tvb) != 4 )
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
return "[Wrong Length 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);
return ep_strdup_printf("%u/%u",vpi,vci);
}
static void
radius_decrypt_avp(gchar *dest,int dest_len,tvbuff_t *tvb,int offset,int length)
{
md5_state_t md_ctx;
md5_byte_t digest[16];
int i;
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
size_t totlen, returned_length;
const guint8 *pd;
guchar c;
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
DISSECTOR_ASSERT(dest_len > 2); /* \"\"\0 */
dest[0] = '"';
dest[1] = '\0';
totlen = 1;
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
dest_len -= 1; /* Need to add trailing \" */
md5_init(&md_ctx);
md5_append(&md_ctx,(const guint8*)shared_secret,strlen(shared_secret));
md5_append(&md_ctx,authenticator, AUTHENTICATOR_LENGTH);
md5_finish(&md_ctx,digest);
pd = tvb_get_ptr(tvb,offset,length);
for( i = 0 ; i < AUTHENTICATOR_LENGTH && i < length ; i++ ) {
c = pd[i] ^ digest[i];
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
if ( isprint(c) ) {
returned_length = g_snprintf(&dest[totlen], dest_len-totlen,
"%c",c);
totlen += MIN(returned_length, dest_len-totlen-1);
} else {
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
returned_length = g_snprintf(&dest[totlen], dest_len-totlen,
"\\%03o",c);
totlen += MIN(returned_length, dest_len-totlen-1);
}
}
while(i<length) {
if ( isprint(pd[i]) ) {
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
returned_length = g_snprintf(&dest[totlen], dest_len-totlen,
"%c", pd[i]);
totlen += MIN(returned_length, dest_len-totlen-1);
} else {
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
returned_length = g_snprintf(&dest[totlen], dest_len-totlen,
"\\%03o", pd[i]);
totlen += MIN(returned_length, dest_len-totlen-1);
}
i++;
}
done: packet-ntp.c: Rather confused and incorrect use of g_snprintf return value packet-pim.c: whitespace change packet-icmpv6.c: g_snprintf takes trailing \0 into account, fix off by 1 error packet-clnp.c: Fix incorrect use of g_snprintf return value packet-isakmp.c: g_snprintf takes trailing \0 into account packet-tr.c: Fix incorrect use of g_snprintf return value packet-radius.c: Fix incorrect use of g_snprintf return value packet-radius.h: constify a string variable packet-ldap.c: The return value isn't needed, so don't use it incorrectly packet-tcp.c: Fix incorrect use of g_snprintf return value packet-windows-common.c: Remove unneeded DISSECTOR_ASSERT packet-smb-sidsnooping.c: g_snprintf takes trailing \0 into account packet-pvfs2.c: g_snprintf takes trailing \0 into account packet-ptp.c: Remove #include snprintf packet-ppp.c: Fix incorrect use of g_snprintf return value packet-ospf.c: Fix incorrect use of g_snprintf return value packet-mip6.c: snprintf -> g_snprintf packet-bootp.c: Remove a commented out bad use of g_snprintf packet-ber.c: snprintf -> g_snprintf, g_snprintf takes trailing \0 into account 2do: 52 packet-ieee80211.c: 2DO 2 packet-nfs.c: 2DO - too many side effects 33 packet-bgp.c: 2DO 18 packet-dns.c: 2DO 14 packet-dcm.c: 2DO 13 packet-x11.c: 2DO 11 packet-kerberos.c: 2DO 10 packet-diameter.c: 2DO 9 packet-snmp.c: 2DO 9 packet-pgm.c: 2DO 7 packet-nbns.c: 2DO 6 packet-fcswils.c: 2DO 5 packet-wccp.c: 2DO 5 packet-cops.c: 2DO 4 packet-wtp.c: 2DO svn path=/trunk/; revision=17038
2006-01-16 07:59:44 +00:00
g_snprintf(&dest[totlen], dest_len+1-totlen, "%c", '"');
}
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;
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;
}
proto_tree_add_uint(tree,a->hf,tvb,offset,len,uint);
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);
}
}
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;
buffer=ep_alloc(1024); /* an AVP value can be at most 253 bytes */
radius_decrypt_avp(buffer,1024,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));
}
}
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));
}
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 ip;
gchar buf[16];
if (len != 4) {
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
proto_item_append_text(avp_item, "[wrong length for IP address]");
return;
}
ip=tvb_get_ipv4(tvb,offset);
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
ip_to_str_buf((guint8 *)&ip, buf);
proto_item_append_text(avp_item, "%s", buf);
}
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) {
struct e_in6_addr ipv6_buff;
gchar txtbuf[256];
if (len != 16) {
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
proto_item_append_text(avp_item, "[wrong length for IPv6 address]");
return;
}
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
tvb_get_ipv6(tvb, offset, &ipv6_buff);
ip6_to_str_buf(&ipv6_buff, txtbuf);
proto_item_append_text(avp_item, "%s", txtbuf);
}
void radius_ipxnet(radius_attr_info_t* a, proto_tree* tree, packet_info *pinfo _U_, tvbuff_t* tvb, int offset, int len, proto_item* avp_item) {
guint32 net;
if (len != 4) {
proto_item_append_text(avp_item, "[wrong length for IPX network]");
return;
}
net=tvb_get_ntohl(tvb,offset);
proto_tree_add_item(tree, a->hf, tvb, offset, len, FALSE);
proto_item_append_text(avp_item, "0x%08X", net);
}
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;
if (len != 4) {
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
proto_item_append_text(avp_item, "[wrong length 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));
}
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));
}
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));
}
static void add_avp_to_tree(proto_tree* avp_tree, proto_item* avp_item, packet_info* pinfo, tvbuff_t* tvb, radius_attr_info_t* dictionary_entry, guint32 avp_length, guint32 offset) {
proto_item* pi;
if (dictionary_entry->tagged) {
guint tag;
if (avp_length < 3) {
pi = proto_tree_add_text(avp_tree, tvb, offset,
0, "AVP too short for tag");
PROTO_ITEM_SET_GENERATED(pi);
return;
}
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--;
}
}
if ( dictionary_entry->dissector ) {
tvbuff_t* tvb_value;
const gchar* str;
tvb_value = tvb_new_subset(tvb, offset, 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);
}
}
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
static void dissect_attribute_value_pairs(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, guint length) {
proto_item* item;
gboolean last_eap = FALSE;
guint8* eap_buffer = NULL;
guint eap_seg_num = 0;
guint eap_tot_len_captured = 0;
guint eap_tot_len = 0;
proto_tree* eap_tree = NULL;
tvbuff_t* eap_tvb = NULL;
/*
* In case we throw an exception, clean up whatever stuff we've
* allocated (if any).
*/
CLEANUP_PUSH(g_free, eap_buffer);
while (length > 0) {
radius_attr_info_t* dictionary_entry = NULL;
gint tvb_len;
guint32 avp_type;
guint32 avp_length;
guint32 vendor_id;
proto_item* avp_item;
proto_item* avp_len_item;
proto_tree* avp_tree;
if (length < 2) {
item = proto_tree_add_text(tree, tvb, offset, 0,
"Not enough room in packet for AVP header");
PROTO_ITEM_SET_GENERATED(item);
return;
}
avp_type = tvb_get_guint8(tvb,offset);
avp_length = tvb_get_guint8(tvb,offset+1);
if (avp_length < 2) {
item = proto_tree_add_text(tree, tvb, offset, 0,
"AVP too short: length %u < 2", avp_length);
PROTO_ITEM_SET_GENERATED(item);
return;
}
if (length < avp_length) {
item = proto_tree_add_text(tree, tvb, offset, 0,
"Not enough room in packet for AVP");
PROTO_ITEM_SET_GENERATED(item);
return;
}
length -= avp_length;
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +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;
}
avp_item = proto_tree_add_text(tree, tvb, offset, avp_length,
"AVP: l=%u t=%s(%u)", avp_length,
dictionary_entry->name, avp_type);
avp_length -= 2;
offset += 2;
if (avp_type == RADIUS_VENDOR_SPECIFIC_CODE) {
radius_vendor_info_t* vendor;
proto_tree* vendor_tree;
gint max_offset = offset + avp_length;
const gchar* vendor_str;
/* XXX TODO: handle 2 byte codes for USR */
if (avp_length < 4) {
proto_item_append_text(avp_item, " [AVP too short; no room for vendor ID]");
offset += avp_length;
continue;
}
vendor_id = tvb_get_ntohl(tvb,offset);
avp_length -= 4;
offset += 4;
vendor = g_hash_table_lookup(dict->vendors_by_id,GUINT_TO_POINTER(vendor_id));
if (vendor) {
vendor_str = vendor->name;
} else {
vendor_str = val_to_str(vendor_id, sminmpec_values, "Unknown");
vendor = &no_vendor;
}
proto_item_append_text(avp_item, " v=%s(%u)", vendor_str,
vendor_id);
vendor_tree = proto_item_add_subtree(avp_item,vendor->ett);
while (offset < max_offset) {
guint32 avp_vsa_type = tvb_get_guint8(tvb,offset++);
guint32 avp_vsa_len = tvb_get_guint8(tvb,offset++);
if (avp_vsa_len < 2) {
proto_tree_add_text(tree, tvb, offset+1, 1,
"[VSA too short]");
return;
}
avp_vsa_len -= 2;
dictionary_entry = g_hash_table_lookup(vendor->attrs_by_id,GUINT_TO_POINTER(avp_vsa_type));
if ( !dictionary_entry ) {
dictionary_entry = &no_dictionary_entry;
}
avp_item = proto_tree_add_text(vendor_tree,tvb,offset-2,avp_vsa_len+2,
"VSA: l=%u t=%s(%u)",
avp_vsa_len+2, dictionary_entry->name, avp_vsa_type);
avp_tree = proto_item_add_subtree(avp_item,dictionary_entry->ett);
if (show_length) {
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);
}
add_avp_to_tree(avp_tree, avp_item, pinfo, tvb, dictionary_entry, avp_vsa_len, offset);
offset += avp_vsa_len;
};
continue;
}
avp_tree = proto_item_add_subtree(avp_item,dictionary_entry->ett);
if (show_length) {
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);
}
tvb_len = tvb_length_remaining(tvb, offset);
if ((gint)avp_length < tvb_len)
tvb_len = avp_length;
if (avp_type == RADIUS_EAP_MESSAGE_CODE) {
eap_seg_num++;
/* Show this as an EAP fragment. */
if (tree)
proto_tree_add_text(avp_tree, tvb, offset, tvb_len,
"EAP fragment");
if (eap_tvb != NULL) {
/*
* Oops, a non-consecutive EAP-Message
* attribute.
*/
proto_item_append_text(avp_item, " (non-consecutive)");
} else {
/*
* RFC 2869 says, in section 5.13, describing
* the EAP-Message attribute:
*
* The NAS places EAP messages received
* from the authenticating peer into one
* or more EAP-Message attributes and
* forwards them to the RADIUS Server
* within an Access-Request message.
* If multiple EAP-Messages are
* contained within an Access-Request or
* Access-Challenge packet, they MUST be
* in order and they MUST be consecutive
* attributes in the Access-Request or
* Access-Challenge packet.
*
* ...
*
* The String field contains EAP packets,
* as defined in [3]. If multiple
* EAP-Message attributes are present
* in a packet their values should be
* concatenated; this allows EAP packets
* longer than 253 octets to be passed
* by RADIUS.
*
* Do reassembly of EAP-Message attributes.
* We just concatenate all the attributes,
* and when we see either the end of the
* attribute list or a non-EAP-Message
* attribute, we know we're done.
*/
if (eap_buffer == NULL)
eap_buffer = g_malloc(eap_tot_len_captured + tvb_len);
else
eap_buffer = g_realloc(eap_buffer,
eap_tot_len_captured + tvb_len);
tvb_memcpy(tvb, eap_buffer + eap_tot_len_captured, offset,
tvb_len);
eap_tot_len_captured += tvb_len;
eap_tot_len += avp_length;
if ( tvb_bytes_exist(tvb, offset + avp_length + 1, 1) ) {
guint8 next_type = tvb_get_guint8(tvb, offset + avp_length);
if ( next_type != RADIUS_EAP_MESSAGE_CODE ) {
/* Non-EAP-Message attribute */
last_eap = TRUE;
}
} else {
/*
* No more attributes, either because
* we're at the end of the packet or
* because we're at the end of the
* captured packet data.
*/
last_eap = TRUE;
}
if (last_eap && eap_buffer) {
gboolean save_writable;
proto_item_append_text(avp_item, " 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_captured,
eap_tot_len);
tvb_set_free_cb(eap_tvb, g_free);
tvb_set_child_real_data_tvbuff(tvb, eap_tvb);
add_new_data_source(pinfo, eap_tvb, "Reassembled EAP");
/*
* Don't free this when we're done -
* it's associated with a tvbuff.
*/
eap_buffer = NULL;
/*
* Set the columns non-writable,
* so that the packet list shows
* this as an RADIUS packet, not
* as an EAP packet.
*/
save_writable = col_get_writable(pinfo->cinfo);
col_set_writable(pinfo->cinfo, FALSE);
call_dissector(eap_handle, eap_tvb, pinfo, eap_tree);
col_set_writable(pinfo->cinfo, save_writable);
} else {
proto_item_append_text(avp_item, " Segment[%u]",
eap_seg_num);
}
}
offset += avp_length;
} else {
add_avp_to_tree(avp_tree, avp_item, pinfo, tvb, dictionary_entry,
avp_length, offset);
offset += avp_length;
}
}
/*
* Call the cleanup handler to free any reassembled data we haven't
* attached to a tvbuff, and pop the handler.
*/
CLEANUP_CALL_AND_POP;
}
static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *radius_tree = NULL;
proto_tree *avptree = NULL;
proto_item *ti;
proto_item *avptf;
guint rhlength;
guint rhcode;
guint rhident;
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
guint avplength;
e_radiushdr rh;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
col_set_str(pinfo->cinfo, COL_PROTOCOL, "RADIUS");
if (check_col(pinfo->cinfo, COL_INFO))
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
col_clear(pinfo->cinfo, COL_INFO);
tvb_memcpy(tvb,(guint8 *)&rh,0,sizeof(e_radiushdr));
rhcode = rh.rh_code;
rhident = rh.rh_ident;
rhlength = g_ntohs(rh.rh_pktlength);
/* 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))
{
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
col_add_fstr(pinfo->cinfo,COL_INFO,"%s(%d) (id=%d, l=%d)",
val_to_str(rhcode,radius_vals,"Unknown Packet"),
rhcode, rhident, rhlength);
}
if (tree)
{
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
ti = proto_tree_add_item(tree,proto_radius, tvb, 0, rhlength, FALSE);
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
radius_tree = proto_item_add_subtree(ti, ett_radius);
proto_tree_add_uint(radius_tree,hf_radius_code, tvb, 0, 1, rh.rh_code);
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
proto_tree_add_uint_format(radius_tree,hf_radius_id, tvb, 1, 1, rh.rh_ident,
"Packet identifier: 0x%01x (%d)", rhident,rhident);
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
}
/*
* Make sure the length is sane.
*/
if (rhlength < HDR_LENGTH)
{
if (tree)
{
proto_tree_add_uint_format(radius_tree, hf_radius_length,
tvb, 2, 2, rhlength,
"Length: %u (bogus, < %u)",
rhlength, HDR_LENGTH);
}
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
return;
}
avplength = rhlength - HDR_LENGTH;
if (tree)
{
proto_tree_add_uint(radius_tree, hf_radius_length, tvb,
2, 2, rhlength);
proto_tree_add_item(radius_tree, hf_radius_authenticator, tvb, 4,AUTHENTICATOR_LENGTH,FALSE);
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
}
tvb_memcpy(tvb,authenticator,4,AUTHENTICATOR_LENGTH);
if (tree && avplength > 0) {
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
/* list the attribute value pairs */
avptf = proto_tree_add_text(radius_tree, tvb, HDR_LENGTH,
avplength, "Attribute Value Pairs");
avptree = proto_item_add_subtree(avptf, ett_radius_avp);
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
dissect_attribute_value_pairs(avptree, pinfo, tvb, HDR_LENGTH,
avplength);
}
}
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] = '_';
if(abbrev[i] == '/') abbrev[i] = '_';
}
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_NONE;
} else if (a->type == radius_ipv6addr) {
hfri[0].hfinfo.type = FT_IPv6;
hfri[0].hfinfo.display = BASE_NONE;
} else if (a->type == radius_ipxnet) {
hfri[0].hfinfo.type = FT_IPXNET;
hfri[0].hfinfo.display = BASE_NONE;
} 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;
}
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++;
}
g_array_append_vals(ri->hf,hfri,len_hf);
g_array_append_val(ri->ett,ett);
}
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;
gint* ett_p = &(vnd->ett);
vnd_vs.value = vnd->code;
vnd_vs.strptr = vnd->name;
g_array_append_val(ri->vend_vs,vnd_vs);
g_array_append_val(ri->ett,ett_p);
g_hash_table_foreach(vnd->attrs_by_id,register_attrs,ri);
}
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("%s-%u",val_to_str(vendor_id, sminmpec_values, "Unknown"),vendor_id);
vendor->code = vendor_id;
vendor->attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
vendor->ett = no_vendor.ett;
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;
}
static void reinit_radius(void) {
if ( alt_port_pref != alt_port ) {
if (alt_port)
dissector_delete("udp.port", alt_port, radius_handle);
if (alt_port_pref)
dissector_add("udp.port", alt_port_pref, radius_handle);
alt_port = alt_port_pref;
}
}
void
proto_register_radius(void)
{
hf_register_info base_hf[] = {
{ &hf_radius_code,
{ "Code","radius.code", FT_UINT8, BASE_DEC, VALS(radius_vals), 0x0,
"", HFILL }},
{ &hf_radius_id,
{ "Identifier", "radius.id", FT_UINT8, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &hf_radius_authenticator,
{ "Authenticator", "radius.authenticator", FT_BYTES, BASE_HEX, NULL, 0x0,
"", HFILL }},
{ &hf_radius_length,
{ "Length","radius.length", FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &(no_dictionary_entry.hf),
{ "Unknown-Attribute","radius.Unknown_Attribute", FT_BYTES, BASE_HEX, NULL, 0x0,
"", HFILL }},
{ &(no_dictionary_entry.hf_len),
{ "Unknown-Attribute Length","radius.Unknown_Attribute.length", FT_UINT8, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &hf_radius_framed_ip_address,
{ "Framed-IP-Address","radius.Framed-IP-Address", FT_IPv4, BASE_NONE, NULL, 0x0,
"", HFILL }},
{ &hf_radius_login_ip_host,
{ "Login-IP-Host","radius.Login-IP-Host", FT_IPv4, BASE_NONE, NULL, 0x0,
"", HFILL }},
{ &hf_radius_framed_ipx_network,
{ "Framed-IPX-Network","radius.Framed-IPX-Network", FT_IPXNET, BASE_NONE, NULL, 0x0,
"", HFILL }},
{ &hf_radius_cosine_vpi,
{ "Cosine-VPI","radius.Cosine-Vpi", FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &hf_radius_cosine_vci,
{ "Cosine-VCI","radius.Cosine-Vci", FT_UINT16, BASE_DEC, NULL, 0x0,
"", HFILL }},
};
gint *base_ett[] = {
&ett_radius,
&ett_radius_avp,
&ett_eap,
&(no_dictionary_entry.ett),
&(no_vendor.ett),
};
module_t *radius_module;
hfett_t ri;
char* dir = NULL;
gchar* dict_err_str = NULL;
ri.hf = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
ri.ett = g_array_new(FALSE,TRUE,sizeof(gint *));
ri.vend_vs = g_array_new(TRUE,TRUE,sizeof(value_string));
g_array_append_vals(ri.hf, base_hf, array_length(base_hf));
g_array_append_vals(ri.ett, base_ett, array_length(base_ett));
dir = get_persconffile_path("radius", FALSE);
if (test_for_directory(dir) != EISDIR) {
/* Although dir isn't a directory it may still use memory */
g_free(dir);
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;
dict_err_str = g_strdup("Could not find the radius directory");
}
g_free(dir);
if (dict_err_str) {
g_warning("radius: %s",dict_err_str);
g_free(dict_err_str);
}
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 {
/* XXX: TODO load a default dictionary */
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);
dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
}
radius_vendors = (value_string*) ri.vend_vs->data;
proto_radius = proto_register_protocol("Radius Protocol", "RADIUS", "radius");
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);
g_array_free(ri.hf,FALSE);
g_array_free(ri.ett,FALSE);
g_array_free(ri.vend_vs,FALSE);
radius_module = prefs_register_protocol(proto_radius,reinit_radius);
prefs_register_string_preference(radius_module,"shared_secret","Shared Secret",
"Shared secret used to decode User Passwords",
&shared_secret);
prefs_register_bool_preference(radius_module,"show_length","Show AVP Lengths",
"Whether to add or not to the tree the AVP's payload length",
&show_length);
prefs_register_uint_preference(radius_module, "alternate_port","Alternate Port",
"An alternate UDP port to decode as RADIUS", 10, &alt_port_pref);
no_vendor.attrs_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
}
void
proto_reg_handoff_radius(void)
{
Fix some typoes. Call "dissect_attribute_value_pairs()" regardless of whether we're building a protocol tree, so the EAP subdissector is always called. "dissect_attribute_value_pairs()" is only called when the length of AVPs in the packet is non-zero; don't bother checking for a zero length. Don't put two items in for each AVP - one is sufficient. Add some more length checks when processing AVPs. Don't require AVPs to be at least 3 bytes long - they might have just a type and length; let an exception be thrown if that's a problem. Don't require that the entire AVP be available in the tvbuff before processing it; let an exception be thrown as we're processing the AVP if we don't have all the data, so the stuff before the end is processed. Give the tvbuff for the AVP data a length that reflects the length of data left in the tvbuff, so that the appropriate exception is thrown if the packet was cut short by a snapshot length. Don't have a fixed-length buffer for reassembled EAP messages; grow it as necessary. Don't special-case the initial part of the processing of EAP messages; put in the standard length item, as well as, for fragments, an item for the fragment data. Check for non-consecutive EAP-Message attributes. Set the columns non-writable while dissecting the EAP message, so Protocol and Info reflect the RADIUS packet. Doing the reassembly by gluing together all the consecutive EAP-Message attributes means we don't need help from the EAP dissector, returning the total length of the EAP message. Get rid of the no-longer-needed eap_fragment dissector; just call the regular EAP dissector. svn path=/trunk/; revision=15046
2005-07-24 20:39:19 +00:00
eap_handle = find_dissector("eap");
radius_handle = create_dissector_handle(dissect_radius, proto_radius);
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);
radius_register_avp_dissector(0,8,dissect_framed_ip_address);
radius_register_avp_dissector(0,14,dissect_login_ip_host);
radius_register_avp_dissector(0,23,dissect_framed_ipx_network);
radius_register_avp_dissector(VENDOR_COSINE,5,dissect_cosine_vpvc);
}