2005-12-04 21:45:38 +00:00
/* packet-snmp.c
* Routines for SNMP ( simple network management protocol )
* Copyright ( C ) 1998 Didier Jorand
*
* See RFC 1157 for SNMPv1 .
*
* See RFCs 1901 , 1905 , and 1906 for SNMPv2c .
*
* See RFCs 1905 , 1906 , 1909 , and 1910 for SNMPv2u [ historic ] .
*
* See RFCs 2570 - 2576 for SNMPv3
2006-05-23 15:17:14 +00:00
* Updated to use the asn2wrs compiler made by Tomas Kukosa
2006-03-15 06:20:23 +00:00
* Copyright ( C ) 2005 - 2006 Anders Broman [ AT ] ericsson . com
2005-12-04 21:45:38 +00:00
*
2007-01-09 18:38:55 +00:00
* See RFC 3414 for User - based Security Model for SNMPv3
2007-01-10 02:30:22 +00:00
* See RFC 3826 for ( AES ) Cipher Algorithm in the SNMP USM
2007-01-09 18:38:55 +00:00
* Copyright ( C ) 2007 Luis E . Garcia Ontanon < luis . ontanon @ gmail . com >
2005-12-04 21:45:38 +00:00
*
* $ Id $
*
2006-05-21 05:12:17 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2005-12-04 21:45:38 +00:00
* Copyright 1998 Gerald Combs
*
* Some stuff from :
*
* GXSNMP - - An snmp mangament application
* Copyright ( C ) 1998 Gregory McLean & Jochen Friedrich
* Beholder RMON ethernet network monitor , Copyright ( C ) 1993 DNPAP group
*
* 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 .
*/
2007-08-21 21:32:00 +00:00
# define D(args) do {printf args; fflush(stdout); } while(0)
2005-12-04 21:45:38 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <string.h>
2006-06-14 08:08:51 +00:00
# include <ctype.h>
2005-12-04 21:45:38 +00:00
# include <glib.h>
# include <epan/packet.h>
2006-03-15 06:20:23 +00:00
# include <epan/strutil.h>
2005-12-04 21:45:38 +00:00
# include <epan/conversation.h>
# include "etypes.h"
# include <epan/prefs.h>
# include <epan/sminmpec.h>
# include <epan/emem.h>
2006-06-13 13:21:12 +00:00
# include <epan/next_tvb.h>
2007-02-07 14:54:35 +00:00
# include <epan/uat.h>
2007-05-13 20:58:29 +00:00
# include <epan/asn1.h>
2005-12-04 21:45:38 +00:00
# include "packet-ipx.h"
# include "packet-hpext.h"
# include "packet-ber.h"
# include "packet-snmp.h"
# include "format-oid.h"
2007-01-12 00:33:32 +00:00
# include <epan/crypt/crypt-sha1.h>
2007-01-09 20:22:48 +00:00
# include <epan/crypt/crypt-md5.h>
# include <epan/expert.h>
# include <epan/report_err.h>
2007-08-19 23:00:47 +00:00
# include <epan/oids.h>
2007-01-09 20:22:48 +00:00
2007-01-10 01:15:18 +00:00
# ifdef _WIN32
# include <winposixtype.h>
# endif /* _WIN32 */
2007-01-09 18:38:55 +00:00
# ifdef HAVE_LIBGCRYPT
# include <gcrypt.h>
# endif
2006-03-15 06:20:23 +00:00
/* Take a pointer that may be null and return a pointer that's not null
by turning null pointers into pointers to the above null string ,
and , if the argument pointer wasn ' t null , make sure we handle
non - printable characters in the string by escaping them . */
# define SAFE_STRING(s, l) (((s) != NULL) ? format_text((s), (l)) : "")
2005-12-04 21:45:38 +00:00
# define PNAME "Simple Network Management Protocol"
# define PSNAME "SNMP"
# define PFNAME "snmp"
# define UDP_PORT_SNMP 161
# define UDP_PORT_SNMP_TRAP 162
# define TCP_PORT_SNMP 161
# define TCP_PORT_SNMP_TRAP 162
# define TCP_PORT_SMUX 199
/* Initialize the protocol and registered fields */
static int proto_snmp = - 1 ;
static int proto_smux = - 1 ;
/* Default MIB modules to load */
/*
* XXX - According to Wes Hardaker , we shouldn ' t do this :
* http : //www.ethereal.com/lists/ethereal-dev/200412/msg00222.html
*/
# ifdef _WIN32
# define DEF_MIB_MODULES "IP-MIB;IF-MIB;TCP-MIB;UDP-MIB;SNMPv2-MIB;RFC1213-MIB;UCD-SNMP-MIB"
# define IMPORT_SEPARATOR ":"
# else
# define DEF_MIB_MODULES "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB"
# define IMPORT_SEPARATOR ";"
# endif /* _WIN32 */
static gboolean display_oid = TRUE ;
2007-02-07 14:54:35 +00:00
static gboolean snmp_usm_auth_md5 ( snmp_usm_params_t * p , guint8 * * , guint * , gchar const * * ) ;
static gboolean snmp_usm_auth_sha1 ( snmp_usm_params_t * p , guint8 * * , guint * , gchar const * * ) ;
static tvbuff_t * snmp_usm_priv_des ( snmp_usm_params_t * , tvbuff_t * , gchar const * * ) ;
static tvbuff_t * snmp_usm_priv_aes ( snmp_usm_params_t * , tvbuff_t * , gchar const * * ) ;
static void snmp_usm_password_to_key_md5 ( const guint8 * password , guint passwordlen , const guint8 * engineID , guint engineLength , guint8 * key ) ;
static void snmp_usm_password_to_key_sha1 ( const guint8 * password , guint passwordlen , const guint8 * engineID , guint engineLength , guint8 * key ) ;
static snmp_usm_auth_model_t model_md5 = { snmp_usm_password_to_key_md5 , snmp_usm_auth_md5 , 16 } ;
static snmp_usm_auth_model_t model_sha1 = { snmp_usm_password_to_key_sha1 , snmp_usm_auth_sha1 , 20 } ;
static value_string auth_types [ ] = {
{ 0 , " MD5 " } ,
{ 1 , " SHA1 " } ,
{ 0 , NULL }
} ;
static snmp_usm_auth_model_t * auth_models [ ] = { & model_md5 , & model_sha1 } ;
static value_string priv_types [ ] = {
{ 0 , " DES " } ,
{ 1 , " AES " } ,
{ 0 , NULL }
} ;
static snmp_usm_decoder_t priv_protos [ ] = { snmp_usm_priv_des , snmp_usm_priv_aes } ;
static snmp_ue_assoc_t * ueas = NULL ;
static guint num_ueas = 0 ;
static uat_t * assocs_uat = NULL ;
2007-01-11 00:29:50 +00:00
static snmp_ue_assoc_t * localized_ues = NULL ;
static snmp_ue_assoc_t * unlocalized_ues = NULL ;
2007-02-07 14:54:35 +00:00
/****/
2007-01-11 00:29:50 +00:00
static snmp_usm_params_t usm_p = { FALSE , FALSE , 0 , 0 , 0 , 0 , NULL , NULL , NULL , NULL , NULL , NULL , NULL , FALSE } ;
2007-01-09 18:38:55 +00:00
2005-12-04 21:45:38 +00:00
# define TH_AUTH 0x01
# define TH_CRYPT 0x02
# define TH_REPORT 0x04
/* desegmentation of SNMP-over-TCP */
static gboolean snmp_desegment = TRUE ;
/* Global variables */
guint32 MsgSecurityModel ;
2006-03-15 06:20:23 +00:00
tvbuff_t * oid_tvb = NULL ;
2006-06-13 13:21:12 +00:00
tvbuff_t * value_tvb = NULL ;
2005-12-04 21:45:38 +00:00
static dissector_handle_t snmp_handle ;
static dissector_handle_t data_handle ;
2006-06-13 13:21:12 +00:00
static next_tvb_list_t var_list ;
2005-12-04 21:45:38 +00:00
static int hf_snmp_v3_flags_auth = - 1 ;
static int hf_snmp_v3_flags_crypt = - 1 ;
static int hf_snmp_v3_flags_report = - 1 ;
static int hf_snmp_engineid_conform = - 1 ;
static int hf_snmp_engineid_enterprise = - 1 ;
static int hf_snmp_engineid_format = - 1 ;
static int hf_snmp_engineid_ipv4 = - 1 ;
static int hf_snmp_engineid_ipv6 = - 1 ;
static int hf_snmp_engineid_mac = - 1 ;
static int hf_snmp_engineid_text = - 1 ;
static int hf_snmp_engineid_time = - 1 ;
static int hf_snmp_engineid_data = - 1 ;
2007-01-09 18:38:55 +00:00
static int hf_snmp_decryptedPDU = - 1 ;
static int hf_snmp_msgAuthentication = - 1 ;
2007-08-19 23:00:47 +00:00
2007-08-23 19:45:31 +00:00
static int hf_snmp_noSuchObject = - 1 ;
static int hf_snmp_noSuchInstance = - 1 ;
static int hf_snmp_endOfMibView = - 1 ;
static int hf_snmp_unSpecified = - 1 ;
2007-08-19 23:00:47 +00:00
static int hf_snmp_integer32_value = - 1 ;
static int hf_snmp_octestring_value = - 1 ;
static int hf_snmp_oid_value = - 1 ;
static int hf_snmp_null_value = - 1 ;
static int hf_snmp_ipv4_value = - 1 ;
static int hf_snmp_ipv6_value = - 1 ;
static int hf_snmp_anyaddress_value = - 1 ;
static int hf_snmp_unsigned32_value = - 1 ;
static int hf_snmp_unknown_value = - 1 ;
static int hf_snmp_opaque_value = - 1 ;
static int hf_snmp_nsap_value = - 1 ;
static int hf_snmp_counter_value = - 1 ;
static int hf_snmp_timeticks_value = - 1 ;
static int hf_snmp_big_counter_value = - 1 ;
static int hf_snmp_gauge32_value = - 1 ;
2007-08-23 19:45:31 +00:00
2007-08-19 23:00:47 +00:00
static int hf_snmp_objectname = - 1 ;
2007-08-23 19:45:31 +00:00
static int hf_snmp_scalar_instance_index = - 1 ;
2006-03-15 06:20:23 +00:00
2005-12-04 21:45:38 +00:00
# include "packet-snmp-hf.c"
static int hf_smux_version = - 1 ;
static int hf_smux_pdutype = - 1 ;
/* Initialize the subtree pointers */
static gint ett_smux = - 1 ;
static gint ett_snmp = - 1 ;
static gint ett_engineid = - 1 ;
static gint ett_msgFlags = - 1 ;
2007-01-09 18:38:55 +00:00
static gint ett_encryptedPDU = - 1 ;
static gint ett_decrypted = - 1 ;
static gint ett_authParameters = - 1 ;
2007-04-05 22:16:12 +00:00
static gint ett_internet = - 1 ;
2007-08-19 23:00:47 +00:00
static gint ett_varbind = - 1 ;
2007-08-23 19:45:31 +00:00
static gint ett_name = - 1 ;
2007-08-19 23:00:47 +00:00
static gint ett_decoding_error = - 1 ;
2005-12-04 21:45:38 +00:00
# include "packet-snmp-ett.c"
2007-01-09 18:38:55 +00:00
static const true_false_string auth_flags = {
" OK " ,
" Failed "
} ;
2006-03-15 06:20:23 +00:00
/* defined in net-SNMP; include/net-snmp/library/snmp.h */
# undef SNMP_MSG_GET
# undef SNMP_MSG_SET
# undef SNMP_MSG_GETNEXT
# undef SNMP_MSG_RESPONSE
# undef SNMP_MSG_TRAP
# undef SNMP_MSG_GETBULK
# undef SNMP_MSG_INFORM
# undef SNMP_MSG_TRAP2
# undef SNMP_MSG_REPORT
# undef SNMP_NOSUCHOBJECT
# undef SNMP_NOSUCHINSTANCE
# undef SNMP_ENDOFMIBVIEW
2005-12-04 21:45:38 +00:00
/* Security Models */
# define SNMP_SEC_ANY 0
# define SNMP_SEC_V1 1
# define SNMP_SEC_V2C 2
# define SNMP_SEC_USM 3
static const value_string sec_models [ ] = {
{ SNMP_SEC_ANY , " Any " } ,
{ SNMP_SEC_V1 , " V1 " } ,
{ SNMP_SEC_V2C , " V2C " } ,
{ SNMP_SEC_USM , " USM " } ,
{ 0 , NULL }
} ;
/* SMUX PDU types */
# define SMUX_MSG_OPEN 0
# define SMUX_MSG_CLOSE 1
# define SMUX_MSG_RREQ 2
# define SMUX_MSG_RRSP 3
# define SMUX_MSG_SOUT 4
static const value_string smux_types [ ] = {
{ SMUX_MSG_OPEN , " Open " } ,
{ SMUX_MSG_CLOSE , " Close " } ,
{ SMUX_MSG_RREQ , " Registration Request " } ,
{ SMUX_MSG_RRSP , " Registration Response " } ,
{ SMUX_MSG_SOUT , " Commit Or Rollback " } ,
{ 0 , NULL }
} ;
2006-03-15 06:20:23 +00:00
# define SNMP_IPA 0 /* IP Address */
# define SNMP_CNT 1 /* Counter (Counter32) */
# define SNMP_GGE 2 /* Gauge (Gauge32) */
# define SNMP_TIT 3 /* TimeTicks */
# define SNMP_OPQ 4 /* Opaque */
# define SNMP_NSP 5 /* NsapAddress */
# define SNMP_C64 6 /* Counter64 */
# define SNMP_U32 7 /* Uinteger32 */
# define SERR_NSO 0
# define SERR_NSI 1
# define SERR_EOM 2
2007-08-23 19:45:31 +00:00
/*
* dissect_snmp_VarBind
* this routine dissects variable bindings , looking for the oid information in our oid reporsitory
* to format and add the value adequatelly .
*
* The choice to handwrite this code instead of using the asn compiler is to avoid having tons
* of uses of global variables distributed in very different parts of the code .
* Other than that there ' s a cosmetic thing : the tree from ASN generated code would be so
* convoluted due to the nesting of CHOICEs in the definition of VarBind / value .
*
* XXX : the length of this function ( ~ 400 lines ) is an aberration !
* oid_key_t : key_type could become a series of callbacks instead of an enum
* the ( ! oid_info_is_ok ) switch could be made into an array ( would be slower )
*
NetworkAddress : : = CHOICE { internet IpAddress }
IpAddress : : = [ APPLICATION 0 ] IMPLICIT OCTET STRING ( SIZE ( 4 ) )
TimeTicks : : = [ APPLICATION 3 ] IMPLICIT INTEGER ( 0. .4294967295 )
Integer32 : : = INTEGER ( - 2147483648. .2147483647 )
ObjectName : : = OBJECT IDENTIFIER
Counter32 : : = [ APPLICATION 1 ] IMPLICIT INTEGER ( 0. .4294967295 )
Gauge32 : : = [ APPLICATION 2 ] IMPLICIT INTEGER ( 0. .4294967295 )
Unsigned32 : : = [ APPLICATION 2 ] IMPLICIT INTEGER ( 0. .4294967295 )
Integer - value : : = INTEGER ( - 2147483648. .2147483647 )
Integer32 : : = INTEGER ( - 2147483648. .2147483647 )
ObjectID - value : : = OBJECT IDENTIFIER
Empty : : = NULL
TimeTicks : : = [ APPLICATION 3 ] IMPLICIT INTEGER ( 0. .4294967295 )
Opaque : : = [ APPLICATION 4 ] IMPLICIT OCTET STRING
Counter64 : : = [ APPLICATION 6 ] IMPLICIT INTEGER ( 0. .18446744073709551615 )
ObjectSyntax : : = CHOICE {
simple SimpleSyntax ,
application - wide ApplicationSyntax
}
SimpleSyntax : : = CHOICE {
integer - value Integer - value ,
string - value String - value ,
objectID - value ObjectID - value ,
empty Empty
}
ApplicationSyntax : : = CHOICE {
ipAddress - value IpAddress ,
counter - value Counter32 ,
timeticks - value TimeTicks ,
arbitrary - value Opaque ,
big - counter - value Counter64 ,
unsigned - integer - value Unsigned32
}
ValueType : : = CHOICE {
value ObjectSyntax ,
unSpecified NULL ,
noSuchObject [ 0 ] IMPLICIT NULL ,
noSuchInstance [ 1 ] IMPLICIT NULL ,
endOfMibView [ 2 ] IMPLICIT NULL
}
VarBind : : = SEQUENCE {
name ObjectName ,
valueType ValueType
}
*/
extern int dissect_snmp_VarBind ( gboolean implicit_tag _U_ ,
2007-08-19 23:00:47 +00:00
tvbuff_t * tvb ,
int offset ,
asn1_ctx_t * actx ,
proto_tree * tree ,
int hf_index _U_ ) {
int seq_offset , name_offset , value_offset , value_start ;
guint32 seq_len , name_len , value_len ;
gint8 ber_class ;
gboolean pc ;
gint32 tag ;
gboolean ind ;
2007-08-21 21:32:00 +00:00
guint32 * subids ;
2007-08-19 23:00:47 +00:00
guint8 * oid_bytes ;
oid_info_t * oid_info ;
guint oid_matched , oid_left ;
2007-08-23 19:45:31 +00:00
proto_item * pi_name , * pi_varbind , * pi_value = NULL ;
proto_tree * pt , * pt_varbind , * pt_name ;
2007-08-21 21:32:00 +00:00
char label [ ITEM_LABEL_LENGTH ] ;
char * repr = NULL ;
char * valstr ;
2007-08-19 23:00:47 +00:00
int hfid = - 1 ;
int min_len = 0 , max_len = 0 ;
2007-08-23 19:45:31 +00:00
gboolean oid_info_is_ok ;
2007-08-19 23:00:47 +00:00
seq_offset = offset ;
2007-08-23 19:45:31 +00:00
/* first have the VarBind's sequence header */
2007-08-19 23:00:47 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
offset = get_ber_length ( NULL , tvb , offset , & seq_len , & ind ) ;
seq_len + = offset - seq_offset ;
if ( ! pc & & ber_class = = BER_CLASS_UNI & & tag = = BER_UNI_TAG_SEQUENCE ) {
proto_item * pi = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " VarBind must be an universal class sequence " ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " VarBind is not an universal class sequence " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , seq_offset , pt ) ;
2005-12-04 21:45:38 +00:00
}
2007-08-19 23:00:47 +00:00
if ( ind ) {
proto_item * pi = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " Indicator must be clear in VarBind " ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " VarBind has indicator set " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , seq_offset , pt ) ;
2006-07-09 22:12:02 +00:00
}
2007-08-19 23:00:47 +00:00
2007-08-23 19:45:31 +00:00
/* then we have the ObjectName's header */
2007-08-19 23:00:47 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
name_offset = offset = get_ber_length ( NULL , tvb , offset , & name_len , & ind ) ;
if ( ! ( ! pc & & ber_class = = BER_CLASS_UNI & & tag = = BER_UNI_TAG_OID ) ) {
proto_item * pi = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " ObjectName must be an OID in primitive encoding " ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " ObjectName not an OID " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , seq_offset , pt ) ;
2005-12-04 21:45:38 +00:00
}
2007-08-19 23:00:47 +00:00
if ( ind ) {
proto_item * pi = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " Indicator must be clear in ObjectName " ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " ObjectName has indicator set " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , seq_offset , pt ) ;
2005-12-04 21:45:38 +00:00
}
2007-08-19 23:00:47 +00:00
offset + = name_len ;
value_start = offset ;
2007-08-23 19:45:31 +00:00
/* then we have the value's header */
2007-08-19 23:00:47 +00:00
offset = get_ber_identifier ( tvb , offset , & ber_class , & pc , & tag ) ;
value_offset = offset = get_ber_length ( NULL , tvb , offset , & value_len , & ind ) ;
if ( ! ( ! pc ) ) {
proto_item * pi = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " the value must be in primitive encoding " ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " value not in primitive encoding " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , seq_offset , pt ) ;
2006-03-15 06:20:23 +00:00
}
2007-08-23 19:45:31 +00:00
/* Now, we know where everithing is */
2007-08-19 23:00:47 +00:00
2007-08-23 19:45:31 +00:00
/* fetch ObjectName and its relative oid_info */
2007-08-19 23:00:47 +00:00
oid_bytes = ep_tvb_memdup ( tvb , name_offset , name_len ) ;
2007-08-21 21:32:00 +00:00
oid_info = oid_get_from_encoded ( oid_bytes , name_len , & subids , & oid_matched , & oid_left ) ;
2007-08-23 19:45:31 +00:00
/* we add the varbind tree root with a dummy label we'll fill later on */
pi_varbind = proto_tree_add_text ( tree , tvb , seq_offset , seq_len , " VarBind " ) ;
pt_varbind = proto_item_add_subtree ( pi_varbind , ett_varbind ) ;
2007-08-21 21:32:00 +00:00
* label = ' \0 ' ;
2007-08-23 19:45:31 +00:00
pi_name = proto_tree_add_item ( pt_varbind , hf_snmp_objectname , tvb , name_offset , name_len , FALSE ) ;
pt_name = proto_item_add_subtree ( pi_name , ett_name ) ;
2007-08-19 23:00:47 +00:00
if ( ber_class = = BER_CLASS_CON ) {
2007-08-23 19:45:31 +00:00
/* if we have an error value just add it and get out the way ASAP */
proto_item * pi ;
const char * note ;
2007-08-19 23:00:47 +00:00
if ( value_len ! = 0 )
goto expected_other_size ;
2007-08-23 19:45:31 +00:00
2007-08-19 23:00:47 +00:00
switch ( tag ) {
case SERR_NSO :
2007-08-23 19:45:31 +00:00
hfid = hf_snmp_noSuchObject ;
note = " noSuchObject " ;
2007-08-19 23:00:47 +00:00
break ;
case SERR_NSI :
2007-08-23 19:45:31 +00:00
hfid = hf_snmp_noSuchInstance ;
note = " noSuchInstance " ;
2007-08-19 23:00:47 +00:00
break ;
case SERR_EOM :
2007-08-23 19:45:31 +00:00
hfid = hf_snmp_endOfMibView ;
note = " endOfMibView " ;
2007-08-19 23:00:47 +00:00
break ;
default : {
2007-08-23 19:45:31 +00:00
pi = proto_tree_add_text ( pt_varbind , tvb , 0 , 0 , " Wrong tag for Error Value: expected 0, 1, or 2 but got: %d " , tag ) ;
2007-08-19 23:00:47 +00:00
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " Wrong tag for SNMP VarBind error value " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , value_start , tree ) ;
}
}
2007-08-23 19:45:31 +00:00
pi = proto_tree_add_item ( pt_varbind , hfid , tvb , value_offset , value_len , FALSE ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_RESPONSE_CODE , PI_NOTE , " %s " , note ) ;
2007-08-24 00:26:30 +00:00
goto set_label ;
2007-08-23 19:45:31 +00:00
}
/* now we'll try to figure out which are the indexing sub-oids and whether the oid we know about is the one oid we have to use */
switch ( oid_info - > kind ) {
case OID_KIND_SCALAR :
if ( oid_left = = 1 ) {
/* OK: we got the instance sub-id */
proto_tree_add_uint64 ( pt_name , hf_snmp_scalar_instance_index , tvb , name_offset , name_len , subids [ oid_matched ] ) ;
oid_info_is_ok = TRUE ;
goto indexing_done ;
} else if ( oid_left = = 0 ) {
if ( ber_class = = BER_CLASS_UNI & & tag = = BER_UNI_TAG_NULL ) {
/* unSpecified does not require an instance sub-id add the new value and get off the way! */
2007-08-24 00:26:30 +00:00
pi_value = proto_tree_add_item ( pt_varbind , hf_snmp_unSpecified , tvb , value_offset , value_len , FALSE ) ;
goto set_label ;
2007-08-23 19:45:31 +00:00
} else {
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " A scalar should have one instance sub-id this one has none " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " No instance sub-id in scalar value " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
} else {
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " A scalar should have only one instance sub-id this has: %d " , oid_left ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " Wrong number of instance sub-ids in scalar value " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
break ;
case OID_KIND_COLUMN :
if ( oid_info - > parent - > kind = = OID_KIND_ROW ) {
oid_key_t * k = oid_info - > parent - > key ;
guint key_start = oid_matched ;
guint key_len = oid_left ;
oid_info_is_ok = TRUE ;
2007-08-24 00:33:35 +00:00
if ( key_len = = 0 & & ber_class = = BER_CLASS_UNI & & tag = = BER_UNI_TAG_NULL ) {
2007-08-24 00:26:30 +00:00
/* unSpecified does not require an instance sub-id add the new value and get off the way! */
pi_value = proto_tree_add_item ( pt_varbind , hf_snmp_unSpecified , tvb , value_offset , value_len , FALSE ) ;
goto set_label ;
}
2007-08-23 19:45:31 +00:00
if ( k ) {
for ( ; k ; k = k - > next ) {
2007-08-24 00:26:30 +00:00
if ( key_start > = oid_matched + oid_left ) {
2007-08-23 19:45:31 +00:00
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " index sub-oid shorter than expected " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " index sub-oid shorter than expected " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
switch ( k - > key_type ) {
case OID_KEY_TYPE_WRONG : {
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " OID instaces not handled, if you want this implemented please contact the wireshark developpers " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_UNDECODED , PI_WARN , " Unimplemented instance index " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
case OID_KEY_TYPE_INTEGER : {
proto_tree_add_int ( pt_name , k - > hfid , tvb , name_offset , name_len , ( guint ) subids [ key_start ] ) ;
key_start + + ;
key_len - - ;
continue ; /* k->next*/
}
case OID_KEY_TYPE_OID : {
guint suboid_len = subids [ key_start + + ] ;
guint32 * suboid = & ( subids [ key_start ] ) ;
guint8 * suboid_buf ;
guint suboid_buf_len ;
if ( suboid_len < key_len - 1 ) {
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " index sub-oid should be longer than remaining oid size " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " index sub-oid longer than remaining oid size " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
suboid_buf_len = oid_subid2encoded ( suboid_len , suboid , & suboid_buf ) ;
proto_tree_add_oid ( pt_name , k - > hfid , tvb , name_offset , suboid_buf_len , suboid_buf ) ;
key_start + = suboid_len ;
key_len - = suboid_len + 1 ;
continue ; /* k->next*/
}
default : {
guint8 * buf ;
guint buf_len = k - > num_subids ;
guint32 * suboid = & ( subids [ key_start ] ) ;
guint i ;
if ( ! buf_len ) {
buf_len = * suboid ;
suboid + + ;
}
if ( key_len < buf_len ) {
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " index sub-oid should not be longer than remaining oid size " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " index sub-oid longer than remaining oid size " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
buf = ep_alloc ( buf_len + 1 ) ;
for ( i = 0 ; i < buf_len ; i + + )
buf [ i ] = ( guint8 ) suboid [ i ] ;
buf [ i ] = ' \0 ' ;
switch ( k - > key_type ) {
case OID_KEY_TYPE_STRING :
case OID_KEY_TYPE_FIXED_STRING :
proto_tree_add_string ( pt_name , k - > hfid , tvb , name_offset , buf_len , buf ) ;
break ;
case OID_KEY_TYPE_BYTES :
case OID_KEY_TYPE_NSAP :
case OID_KEY_TYPE_FIXED_BYTES :
proto_tree_add_bytes ( pt_name , k - > hfid , tvb , name_offset , buf_len , buf ) ;
break ;
case OID_KEY_TYPE_IPADDR : {
guint32 * ipv4_p = ( void * ) buf ;
proto_tree_add_ipv4 ( pt_name , k - > hfid , tvb , name_offset , buf_len , * ipv4_p ) ;
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
}
}
key_start + = buf_len ;
key_len - = buf_len ;
continue ; /* k->next*/
}
}
}
goto indexing_done ;
} else {
2007-08-24 00:26:30 +00:00
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " we do not know how to handle this OID, if you want this implemented please contact the wireshark developers " ) ;
2007-08-23 19:45:31 +00:00
expert_add_info_format ( actx - > pinfo , pi , PI_UNDECODED , PI_WARN , " Unimplemented instance index " ) ;
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
} else {
2007-08-24 00:26:30 +00:00
proto_item * pi = proto_tree_add_text ( pt_name , tvb , 0 , 0 , " The COLUMS's parent is not a ROW. This is a BUG! please contact the wireshark developers. " ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_ERROR , " COLUMS's parent is not a ROW " ) ;
2007-08-23 19:45:31 +00:00
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
default : {
/* proto_item* pi = proto_tree_add_text(pt_name,tvb,0,0,"This kind OID should have no value");
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " This kind OID should have no value " ) ; */
oid_info_is_ok = FALSE ;
goto indexing_done ;
}
}
indexing_done :
if ( oid_info_is_ok ) {
if ( ber_class = = BER_CLASS_UNI & & tag = = BER_UNI_TAG_NULL ) {
pi_value = proto_tree_add_item ( pt_varbind , hf_snmp_unSpecified , tvb , value_offset , value_len , FALSE ) ;
} else {
if ( ( oid_info - > value_type - > ber_class ! = BER_CLASS_ANY ) & &
( ber_class ! = oid_info - > value_type - > ber_class ) )
goto expected_different ;
if ( ( oid_info - > value_type - > ber_tag ! = BER_TAG_ANY ) & &
( tag ! = oid_info - > value_type - > ber_tag ) )
goto expected_different ;
max_len = oid_info - > value_type - > max_len = = - 1 ? 0xffffff : oid_info - > value_type - > max_len ;
min_len = oid_info - > value_type - > min_len ;
if ( ( int ) value_len < min_len | | ( int ) value_len > max_len )
goto expected_other_size ;
pi_value = proto_tree_add_item ( pt_varbind , oid_info - > value_hfid , tvb , value_offset , value_len , FALSE ) ;
}
} else {
2007-08-19 23:00:47 +00:00
switch ( ber_class | ( tag < < 4 ) ) {
case BER_CLASS_UNI | ( BER_UNI_TAG_INTEGER < < 4 ) :
max_len = 4 ; min_len = 1 ;
if ( value_len > ( guint ) max_len & & value_len < ( guint ) min_len ) goto expected_other_size ;
hfid = hf_snmp_integer32_value ;
break ;
case BER_CLASS_UNI | ( BER_UNI_TAG_OCTETSTRING < < 4 ) :
hfid = hf_snmp_octestring_value ;
break ;
case BER_CLASS_UNI | ( BER_UNI_TAG_OID < < 4 ) :
max_len = - 1 ; min_len = 2 ;
if ( value_len < ( guint ) min_len ) goto expected_other_size ;
hfid = hf_snmp_oid_value ;
break ;
case BER_CLASS_UNI | ( BER_UNI_TAG_NULL < < 4 ) :
max_len = 0 ; min_len = 0 ;
if ( value_len ! = 0 ) goto expected_other_size ;
hfid = hf_snmp_null_value ;
break ;
case BER_CLASS_APP : /* | (SNMP_IPA<<4)*/
switch ( value_len ) {
case 4 : hfid = hf_snmp_ipv4_value ; break ;
case 16 : hfid = hf_snmp_ipv6_value ; break ;
default : hfid = hf_snmp_anyaddress_value ; break ;
}
break ;
case BER_CLASS_APP | ( SNMP_U32 < < 4 ) :
hfid = hf_snmp_unsigned32_value ;
break ;
case BER_CLASS_APP | ( SNMP_GGE < < 4 ) :
hfid = hf_snmp_gauge32_value ;
break ;
case BER_CLASS_APP | ( SNMP_CNT < < 4 ) :
hfid = hf_snmp_counter_value ;
break ;
case BER_CLASS_APP | ( SNMP_TIT < < 4 ) :
hfid = hf_snmp_timeticks_value ;
break ;
case BER_CLASS_APP | ( SNMP_OPQ < < 4 ) :
hfid = hf_snmp_opaque_value ;
break ;
case BER_CLASS_APP | ( SNMP_NSP < < 4 ) :
hfid = hf_snmp_nsap_value ;
break ;
case BER_CLASS_APP | ( SNMP_C64 < < 4 ) :
hfid = hf_snmp_big_counter_value ;
break ;
default :
hfid = hf_snmp_unknown_value ;
break ;
}
2007-08-23 19:45:31 +00:00
pi_value = proto_tree_add_item ( pt_varbind , hfid , tvb , value_offset , value_len , FALSE ) ;
2007-08-24 00:26:30 +00:00
expert_add_info_format ( actx - > pinfo , pi_value , PI_UNDECODED , PI_NOTE , " Unresolved value, Missing MIB " ) ;
oid_info_is_ok = FALSE ;
2007-08-19 23:00:47 +00:00
}
2006-03-15 06:20:23 +00:00
2007-08-24 00:26:30 +00:00
set_label :
2007-08-24 00:41:43 +00:00
if ( pi_value ) proto_item_fill_label ( pi_value - > finfo , label ) ;
2007-08-21 21:32:00 +00:00
if ( oid_info - > name ) {
if ( oid_left > = 1 ) {
repr = ep_strdup_printf ( " %s.%s (%s) " ,
oid_info - > name ,
oid_subid2string ( & ( subids [ oid_matched ] ) , oid_left ) ,
oid_subid2string ( subids , oid_matched + oid_left ) ) ;
} else {
repr = ep_strdup_printf ( " %s (%s) " ,
oid_info - > name ,
oid_subid2string ( subids , oid_matched ) ) ;
}
} else {
repr = ep_strdup_printf ( " %s " , oid_subid2string ( subids , oid_matched + oid_left ) ) ;
}
valstr = strstr ( label , " : " ) ;
2007-08-24 00:26:30 +00:00
valstr = valstr ? valstr + 2 : label ;
2007-08-21 21:32:00 +00:00
proto_item_set_text ( pi_varbind , " %s: %s " , repr , valstr ) ;
2007-08-19 23:00:47 +00:00
return seq_offset + seq_len ;
2006-03-15 06:20:23 +00:00
2007-08-19 23:00:47 +00:00
expected_other_size : {
proto_item * pi = proto_tree_add_text ( tree , tvb , 0 , 0 , " Wrong value length: %u expecting: %u <= len <= %u " ,
value_len ,
min_len ,
max_len = = - 1 ? 0xFFFFFF : max_len ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " Wrong length for SNMP VarBind/value " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , value_start , pt ) ;
}
2006-03-15 06:20:23 +00:00
2007-08-19 23:00:47 +00:00
expected_different : {
proto_item * pi = proto_tree_add_text ( tree , tvb , 0 , 0 , " Wrong class/tag for Value expected: %d,%d got: %d,%d " ,
oid_info - > value_type - > ber_class ,
oid_info - > value_type - > ber_tag ,
ber_class ,
tag ) ;
pt = proto_item_add_subtree ( pi , ett_decoding_error ) ;
expert_add_info_format ( actx - > pinfo , pi , PI_MALFORMED , PI_WARN , " Wrong class/tag for SNMP VarBind/value " ) ;
return dissect_unknown_ber ( actx - > pinfo , tvb , value_start , tree ) ;
}
2006-03-15 06:20:23 +00:00
2007-08-19 23:00:47 +00:00
}
2006-03-15 06:20:23 +00:00
2007-08-19 23:00:47 +00:00
gchar * format_oid ( subid_t * oid , guint oid_length ) {
return ( void * ) oid_resolved ( oid_length , oid ) ;
}
2006-03-15 06:20:23 +00:00
2007-08-19 23:00:47 +00:00
void new_format_oid ( subid_t * oid , guint oid_length , gchar * * non_decoded , gchar * * decoded ) {
* decoded = ( void * ) oid_resolved ( oid_length , oid ) ;
* non_decoded = ( void * ) oid_subid2string ( oid , oid_length ) ;
2006-03-15 06:20:23 +00:00
}
2005-12-04 21:45:38 +00:00
# define F_SNMP_ENGINEID_CONFORM 0x80
# define SNMP_ENGINEID_RFC1910 0x00
# define SNMP_ENGINEID_RFC3411 0x01
static const true_false_string tfs_snmp_engineid_conform = {
" RFC3411 (SNMPv3) " ,
" RFC1910 (Non-SNMPv3) "
} ;
# define SNMP_ENGINEID_FORMAT_IPV4 0x01
# define SNMP_ENGINEID_FORMAT_IPV6 0x02
# define SNMP_ENGINEID_FORMAT_MACADDRESS 0x03
# define SNMP_ENGINEID_FORMAT_TEXT 0x04
# define SNMP_ENGINEID_FORMAT_OCTETS 0x05
static const value_string snmp_engineid_format_vals [ ] = {
{ SNMP_ENGINEID_FORMAT_IPV4 , " IPv4 address " } ,
{ SNMP_ENGINEID_FORMAT_IPV6 , " IPv6 address " } ,
{ SNMP_ENGINEID_FORMAT_MACADDRESS , " MAC address " } ,
{ SNMP_ENGINEID_FORMAT_TEXT , " Text, administratively assigned " } ,
{ SNMP_ENGINEID_FORMAT_OCTETS , " Octets, administratively assigned " } ,
{ 0 , NULL }
} ;
2006-01-18 20:02:19 +00:00
/*
2005-12-04 21:45:38 +00:00
* SNMP Engine ID dissection according to RFC 3411 ( SnmpEngineID TC )
* or historic RFC 1910 ( AgentID )
*/
int
dissect_snmp_engineid ( proto_tree * tree , tvbuff_t * tvb , int offset , int len )
{
proto_item * item = NULL ;
guint8 conformance , format ;
guint32 enterpriseid , seconds ;
nstime_t ts ;
int len_remain = len ;
/* first bit: engine id conformance */
if ( len_remain < 4 ) return offset ;
conformance = ( ( tvb_get_guint8 ( tvb , offset ) > > 7 ) & & 0x01 ) ;
proto_tree_add_item ( tree , hf_snmp_engineid_conform , tvb , offset , 1 , FALSE ) ;
/* 4-byte enterprise number/name */
if ( len_remain < 4 ) return offset ;
enterpriseid = tvb_get_ntohl ( tvb , offset ) ;
2006-01-18 20:02:19 +00:00
if ( conformance )
2005-12-04 21:45:38 +00:00
enterpriseid - = 0x80000000 ; /* ignore first bit */
proto_tree_add_uint ( tree , hf_snmp_engineid_enterprise , tvb , offset , 4 , enterpriseid ) ;
offset + = 4 ;
len_remain - = 4 ;
switch ( conformance ) {
case SNMP_ENGINEID_RFC1910 :
/* 12-byte AgentID w/ 8-byte trailer */
if ( len_remain = = 8 ) {
proto_tree_add_text ( tree , tvb , offset , 8 , " AgentID Trailer: 0x%s " ,
tvb_bytes_to_str ( tvb , offset , 8 ) ) ;
offset + = 8 ;
len_remain - = 8 ;
} else {
proto_tree_add_text ( tree , tvb , offset , len_remain , " <Data not conforming to RFC1910> " ) ;
return offset ;
}
break ;
case SNMP_ENGINEID_RFC3411 : /* variable length: 5..32 */
/* 1-byte format specifier */
if ( len_remain < 1 ) return offset ;
format = tvb_get_guint8 ( tvb , offset ) ;
item = proto_tree_add_uint_format ( tree , hf_snmp_engineid_format , tvb , offset , 1 , format , " Engine ID Format: %s (%d) " ,
val_to_str ( format , snmp_engineid_format_vals , " Reserved/Enterprise-specific " ) , format ) ;
offset + = 1 ;
len_remain - = 1 ;
switch ( format ) {
case SNMP_ENGINEID_FORMAT_IPV4 :
/* 4-byte IPv4 address */
if ( len_remain = = 4 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_ipv4 , tvb , offset , 4 , FALSE ) ;
offset + = 4 ;
len_remain = 0 ;
}
break ;
case SNMP_ENGINEID_FORMAT_IPV6 :
/* 16-byte IPv6 address */
if ( len_remain = = 16 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_ipv6 , tvb , offset , 16 , FALSE ) ;
offset + = 16 ;
len_remain = 0 ;
}
break ;
case SNMP_ENGINEID_FORMAT_MACADDRESS :
/* 6-byte MAC address */
if ( len_remain = = 6 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_mac , tvb , offset , 6 , FALSE ) ;
offset + = 6 ;
len_remain = 0 ;
}
break ;
case SNMP_ENGINEID_FORMAT_TEXT :
/* max. 27-byte string, administratively assigned */
if ( len_remain < = 27 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_text , tvb , offset , len_remain , FALSE ) ;
offset + = len_remain ;
len_remain = 0 ;
}
break ;
case 128 :
/* most common enterprise-specific format: (ucd|net)-snmp random */
if ( ( enterpriseid = = 2021 ) | | ( enterpriseid = = 8072 ) ) {
2006-01-18 20:02:19 +00:00
proto_item_append_text ( item , ( enterpriseid = = 2021 ) ? " : UCD-SNMP Random " : " : Net-SNMP Random " ) ;
2005-12-04 21:45:38 +00:00
/* demystify: 4B random, 4B epoch seconds */
if ( len_remain = = 8 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_data , tvb , offset , 4 , FALSE ) ;
seconds = tvb_get_letohl ( tvb , offset + 4 ) ;
ts . secs = seconds ;
2006-01-18 20:02:19 +00:00
proto_tree_add_time_format ( tree , hf_snmp_engineid_time , tvb , offset + 4 , 4 ,
2005-12-04 21:45:38 +00:00
& ts , " Engine ID Data: Creation Time: %s " ,
abs_time_secs_to_str ( seconds ) ) ;
offset + = 8 ;
len_remain = 0 ;
}
}
break ;
case SNMP_ENGINEID_FORMAT_OCTETS :
default :
/* max. 27 bytes, administratively assigned or unknown format */
if ( len_remain < = 27 ) {
proto_tree_add_item ( tree , hf_snmp_engineid_data , tvb , offset , len_remain , FALSE ) ;
offset + = len_remain ;
len_remain = 0 ;
}
break ;
}
}
if ( len_remain > 0 ) {
proto_tree_add_text ( tree , tvb , offset , len_remain , " <Data not conforming to RFC3411> " ) ;
offset + = len_remain ;
}
return offset ;
}
2007-01-10 01:15:18 +00:00
2007-02-07 14:54:35 +00:00
static void set_ue_keys ( snmp_ue_assoc_t * n ) {
guint key_size = n - > user . authModel - > key_size ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
n - > user . authKey . data = se_alloc ( key_size ) ;
n - > user . authKey . len = key_size ;
n - > user . authModel - > pass2key ( n - > user . authPassword . data ,
n - > user . authPassword . len ,
n - > engine . data ,
n - > engine . len ,
n - > user . authKey . data ) ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
n - > user . privKey . data = se_alloc ( key_size ) ;
n - > user . privKey . len = key_size ;
n - > user . authModel - > pass2key ( n - > user . privPassword . data ,
n - > user . privPassword . len ,
n - > engine . data ,
n - > engine . len ,
n - > user . privKey . data ) ;
}
static snmp_ue_assoc_t * ue_se_dup ( snmp_ue_assoc_t * o ) {
snmp_ue_assoc_t * d = se_memdup ( o , sizeof ( snmp_ue_assoc_t ) ) ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . authModel = o - > user . authModel ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . privProtocol = o - > user . privProtocol ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . userName . data = se_memdup ( o - > user . userName . data , o - > user . userName . len ) ;
d - > user . userName . len = o - > user . userName . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . authPassword . data = o - > user . authPassword . data ? se_memdup ( o - > user . authPassword . data , o - > user . authPassword . len ) : NULL ;
d - > user . authPassword . len = o - > user . authPassword . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . privPassword . data = o - > user . privPassword . data ? se_memdup ( o - > user . privPassword . data , o - > user . privPassword . len ) : NULL ;
d - > user . privPassword . len = o - > user . privPassword . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > engine . len = o - > engine . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
if ( d - > engine . len ) {
d - > engine . data = se_memdup ( o - > engine . data , o - > engine . len ) ;
set_ue_keys ( d ) ;
}
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
return d ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
}
2007-01-10 01:15:18 +00:00
2007-01-11 00:29:50 +00:00
# define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
2007-01-11 17:39:16 +00:00
static void renew_ue_cache ( void ) {
2007-02-07 14:54:35 +00:00
if ( num_ueas ) {
guint i ;
2007-07-19 13:43:36 +00:00
2007-01-11 00:29:50 +00:00
localized_ues = NULL ;
unlocalized_ues = NULL ;
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
for ( i = 0 ; i < num_ueas ; i + + ) {
snmp_ue_assoc_t * a = ue_se_dup ( & ( ueas [ i ] ) ) ;
if ( a - > engine . len ) {
2007-01-11 00:29:50 +00:00
CACHE_INSERT ( localized_ues , a ) ;
2007-07-19 13:43:36 +00:00
2007-01-11 00:29:50 +00:00
} else {
CACHE_INSERT ( unlocalized_ues , a ) ;
}
2007-01-12 00:33:32 +00:00
2007-01-11 00:29:50 +00:00
}
2007-02-07 14:54:35 +00:00
} else {
localized_ues = NULL ;
unlocalized_ues = NULL ;
2007-01-11 00:29:50 +00:00
}
}
static snmp_ue_assoc_t * localize_ue ( snmp_ue_assoc_t * o , const guint8 * engine , guint engine_len ) {
snmp_ue_assoc_t * n = se_memdup ( o , sizeof ( snmp_ue_assoc_t ) ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 00:29:50 +00:00
n - > engine . data = se_memdup ( engine , engine_len ) ;
n - > engine . len = engine_len ;
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
set_ue_keys ( n ) ;
2007-07-19 13:43:36 +00:00
2007-01-11 00:29:50 +00:00
return n ;
}
# define localized_match(a,u,ul,e,el) \
( a - > user . userName . len = = ul \
& & a - > engine . len = = el \
& & memcmp ( a - > user . userName . data , u , ( a - > user . userName . len < ul ) ? a - > user . userName . len : ul ) = = 0 \
& & memcmp ( a - > engine . data , e , ( a - > engine . len < el ) ? a - > engine . len : el ) = = 0 )
# define unlocalized_match(a,u,l) \
( a - > user . userName . len = = l & & memcmp ( a - > user . userName . data , u , a - > user . userName . len < l ? a - > user . userName . len : l ) = = 0 )
2007-01-10 01:15:18 +00:00
2007-01-09 18:38:55 +00:00
static snmp_ue_assoc_t * get_user_assoc ( tvbuff_t * engine_tvb , tvbuff_t * user_tvb ) {
static snmp_ue_assoc_t * a ;
guint given_username_len ;
guint8 * given_username ;
guint given_engine_len ;
guint8 * given_engine ;
2007-01-12 00:33:32 +00:00
2007-01-11 00:29:50 +00:00
if ( ! ( localized_ues | | unlocalized_ues ) ) return NULL ;
2007-01-09 18:38:55 +00:00
if ( ! ( user_tvb & & engine_tvb ) ) return NULL ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
given_username_len = tvb_length_remaining ( user_tvb , 0 ) ;
given_username = ep_tvb_memdup ( user_tvb , 0 , - 1 ) ;
given_engine_len = tvb_length_remaining ( engine_tvb , 0 ) ;
given_engine = ep_tvb_memdup ( engine_tvb , 0 , - 1 ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 00:29:50 +00:00
for ( a = localized_ues ; a ; a = a - > next ) {
if ( localized_match ( a , given_username , given_username_len , given_engine , given_engine_len ) ) {
return a ;
}
}
2007-01-12 00:33:32 +00:00
2007-01-11 00:29:50 +00:00
for ( a = unlocalized_ues ; a ; a = a - > next ) {
if ( unlocalized_match ( a , given_username , given_username_len ) ) {
snmp_ue_assoc_t * n = localize_ue ( a , given_engine , given_engine_len ) ;
CACHE_INSERT ( localized_ues , n ) ;
return n ;
2007-01-09 18:38:55 +00:00
}
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
return NULL ;
}
2007-02-07 14:54:35 +00:00
static gboolean snmp_usm_auth_md5 ( snmp_usm_params_t * p , guint8 * * calc_auth_p , guint * calc_auth_len_p , gchar const * * error ) {
2007-01-09 18:38:55 +00:00
guint msg_len ;
guint8 * msg ;
guint auth_len ;
guint8 * auth ;
guint8 * key ;
guint key_len ;
guint8 calc_auth [ 16 ] ;
guint start ;
guint end ;
guint i ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
if ( ! p - > auth_tvb ) {
* error = " No Authenticator " ;
2007-01-12 00:33:32 +00:00
return FALSE ;
2007-01-09 18:38:55 +00:00
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
key = p - > user_assoc - > user . authKey . data ;
key_len = p - > user_assoc - > user . authKey . len ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
if ( ! key ) {
* error = " User has no authKey " ;
return FALSE ;
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
auth_len = tvb_length_remaining ( p - > auth_tvb , 0 ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
if ( auth_len ! = 12 ) {
* error = " Authenticator length wrong " ;
return FALSE ;
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
msg_len = tvb_length_remaining ( p - > msg_tvb , 0 ) ;
msg = ep_tvb_memdup ( p - > msg_tvb , 0 , msg_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
auth = ep_tvb_memdup ( p - > auth_tvb , 0 , auth_len ) ;
start = p - > auth_offset - p - > start_offset ;
end = start + auth_len ;
/* fill the authenticator with zeros */
for ( i = start ; i < end ; i + + ) {
msg [ i ] = ' \0 ' ;
}
md5_hmac ( msg , msg_len , key , key_len , calc_auth ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( calc_auth_p ) * calc_auth_p = calc_auth ;
if ( calc_auth_len_p ) * calc_auth_len_p = 12 ;
2007-01-09 18:38:55 +00:00
return ( memcmp ( auth , calc_auth , 12 ) ! = 0 ) ? FALSE : TRUE ;
}
2007-02-07 14:54:35 +00:00
static gboolean snmp_usm_auth_sha1 ( snmp_usm_params_t * p _U_ , guint8 * * calc_auth_p , guint * calc_auth_len_p , gchar const * * error _U_ ) {
2007-01-10 01:15:18 +00:00
guint msg_len ;
guint8 * msg ;
guint auth_len ;
guint8 * auth ;
guint8 * key ;
guint key_len ;
guint8 calc_auth [ 20 ] ;
guint start ;
guint end ;
guint i ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
if ( ! p - > auth_tvb ) {
* error = " No Authenticator " ;
2007-01-12 00:33:32 +00:00
return FALSE ;
2007-01-10 01:15:18 +00:00
}
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
key = p - > user_assoc - > user . authKey . data ;
key_len = p - > user_assoc - > user . authKey . len ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
if ( ! key ) {
* error = " User has no authKey " ;
return FALSE ;
}
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
auth_len = tvb_length_remaining ( p - > auth_tvb , 0 ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
if ( auth_len ! = 12 ) {
* error = " Authenticator length wrong " ;
return FALSE ;
}
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
msg_len = tvb_length_remaining ( p - > msg_tvb , 0 ) ;
msg = ep_tvb_memdup ( p - > msg_tvb , 0 , msg_len ) ;
auth = ep_tvb_memdup ( p - > auth_tvb , 0 , auth_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
start = p - > auth_offset - p - > start_offset ;
end = start + auth_len ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
/* fill the authenticator with zeros */
for ( i = start ; i < end ; i + + ) {
msg [ i ] = ' \0 ' ;
}
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
sha1_hmac ( key , key_len , msg , msg_len , calc_auth ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( calc_auth_p ) * calc_auth_p = calc_auth ;
if ( calc_auth_len_p ) * calc_auth_len_p = 12 ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
return ( memcmp ( auth , calc_auth , 12 ) ! = 0 ) ? FALSE : TRUE ;
2007-01-09 18:38:55 +00:00
}
2007-02-07 14:54:35 +00:00
static tvbuff_t * snmp_usm_priv_des ( snmp_usm_params_t * p _U_ , tvbuff_t * encryptedData _U_ , gchar const * * error _U_ ) {
2007-01-09 18:38:55 +00:00
# ifdef HAVE_LIBGCRYPT
gcry_error_t err ;
gcry_cipher_hd_t hd = NULL ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
guint8 * cleartext ;
guint8 * des_key = p - > user_assoc - > user . privKey . data ; /* first 8 bytes */
guint8 * pre_iv = & ( p - > user_assoc - > user . privKey . data [ 8 ] ) ; /* last 8 bytes */
guint8 * salt ;
gint salt_len ;
gint cryptgrm_len ;
guint8 * cryptgrm ;
tvbuff_t * clear_tvb ;
2007-01-10 01:15:18 +00:00
guint8 iv [ 8 ] ;
2007-01-09 18:38:55 +00:00
guint i ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
salt_len = tvb_length_remaining ( p - > priv_tvb , 0 ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
if ( salt_len ! = 8 ) {
2007-07-19 13:43:36 +00:00
* error = " decryptionError: msgPrivacyParameters length != 8 " ;
2007-01-09 18:38:55 +00:00
return NULL ;
2007-01-12 00:33:32 +00:00
}
2007-01-09 18:38:55 +00:00
salt = ep_tvb_memdup ( p - > priv_tvb , 0 , salt_len ) ;
/*
The resulting " salt " is XOR - ed with the pre - IV to obtain the IV .
*/
for ( i = 0 ; i < 8 ; i + + ) {
iv [ i ] = pre_iv [ i ] ^ salt [ i ] ;
}
cryptgrm_len = tvb_length_remaining ( encryptedData , 0 ) ;
if ( cryptgrm_len % 8 ) {
2007-01-10 02:30:22 +00:00
* error = " decryptionError: the length of the encrypted data is not a mutiple of 8 octets " ;
2007-01-09 18:38:55 +00:00
return NULL ;
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
cryptgrm = ep_tvb_memdup ( encryptedData , 0 , - 1 ) ;
cleartext = ep_alloc ( cryptgrm_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
err = gcry_cipher_open ( & hd , GCRY_CIPHER_DES , GCRY_CIPHER_MODE_CBC , 0 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
err = gcry_cipher_setiv ( hd , iv , 8 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
err = gcry_cipher_setkey ( hd , des_key , 8 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
err = gcry_cipher_decrypt ( hd , cleartext , cryptgrm_len , cryptgrm , cryptgrm_len ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
gcry_cipher_close ( hd ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
clear_tvb = tvb_new_real_data ( cleartext , cryptgrm_len , cryptgrm_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
return clear_tvb ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
on_gcry_error :
* error = ( void * ) gpg_strerror ( err ) ;
if ( hd ) gcry_cipher_close ( hd ) ;
return NULL ;
# else
* error = " libgcrypt not present, cannot decrypt " ;
return NULL ;
# endif
}
2007-02-07 14:54:35 +00:00
static tvbuff_t * snmp_usm_priv_aes ( snmp_usm_params_t * p _U_ , tvbuff_t * encryptedData _U_ , gchar const * * error _U_ ) {
2007-01-09 18:38:55 +00:00
# ifdef HAVE_LIBGCRYPT
2007-01-10 02:30:22 +00:00
gcry_error_t err ;
gcry_cipher_hd_t hd = NULL ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
guint8 * cleartext ;
guint8 * aes_key = p - > user_assoc - > user . privKey . data ; /* first 16 bytes */
2007-01-11 17:39:16 +00:00
guint8 iv [ 16 ] ;
gint priv_len ;
2007-01-10 02:30:22 +00:00
gint cryptgrm_len ;
guint8 * cryptgrm ;
tvbuff_t * clear_tvb ;
2007-01-11 17:39:16 +00:00
priv_len = tvb_length_remaining ( p - > priv_tvb , 0 ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( priv_len ! = 8 ) {
2007-07-19 13:43:36 +00:00
* error = " decryptionError: msgPrivacyParameters length != 8 " ;
2007-01-10 02:30:22 +00:00
return NULL ;
2007-01-12 00:33:32 +00:00
}
2007-01-10 02:30:22 +00:00
iv [ 0 ] = ( p - > boots & 0xff000000 ) > > 24 ;
iv [ 1 ] = ( p - > boots & 0x00ff0000 ) > > 16 ;
iv [ 2 ] = ( p - > boots & 0x0000ff00 ) > > 8 ;
iv [ 3 ] = ( p - > boots & 0x000000ff ) ;
iv [ 4 ] = ( p - > time & 0xff000000 ) > > 24 ;
iv [ 5 ] = ( p - > time & 0x00ff0000 ) > > 16 ;
iv [ 6 ] = ( p - > time & 0x0000ff00 ) > > 8 ;
iv [ 7 ] = ( p - > time & 0x000000ff ) ;
tvb_memcpy ( p - > priv_tvb , & ( iv [ 8 ] ) , 0 , 8 ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
cryptgrm_len = tvb_length_remaining ( encryptedData , 0 ) ;
cryptgrm = ep_tvb_memdup ( encryptedData , 0 , - 1 ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
cleartext = ep_alloc ( cryptgrm_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
err = gcry_cipher_open ( & hd , GCRY_CIPHER_AES , GCRY_CIPHER_MODE_CFB , 0 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
err = gcry_cipher_setiv ( hd , iv , 16 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
err = gcry_cipher_setkey ( hd , aes_key , 16 ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
err = gcry_cipher_decrypt ( hd , cleartext , cryptgrm_len , cryptgrm , cryptgrm_len ) ;
if ( err ! = GPG_ERR_NO_ERROR ) goto on_gcry_error ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
gcry_cipher_close ( hd ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
clear_tvb = tvb_new_real_data ( cleartext , cryptgrm_len , cryptgrm_len ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
return clear_tvb ;
2007-01-12 00:33:32 +00:00
2007-01-10 02:30:22 +00:00
on_gcry_error :
2007-01-11 17:39:16 +00:00
* error = ( void * ) gpg_strerror ( err ) ;
2007-01-10 02:30:22 +00:00
if ( hd ) gcry_cipher_close ( hd ) ;
2007-01-09 18:38:55 +00:00
return NULL ;
# else
* error = " libgcrypt not present, cannot decrypt " ;
return NULL ;
# endif
}
2007-01-10 01:15:18 +00:00
2007-01-11 17:39:16 +00:00
gboolean check_ScopedPdu ( tvbuff_t * tvb ) {
int offset ;
gint8 class ;
gboolean pc ;
gint32 tag ;
int hoffset , eoffset ;
guint32 len ;
offset = get_ber_identifier ( tvb , 0 , & class , & pc , & tag ) ;
offset = get_ber_length ( NULL , tvb , offset , NULL , NULL ) ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( ! ( ( ( class ! = BER_CLASS_APP ) & & ( class ! = BER_CLASS_PRI ) )
& & ( ( ! pc ) | | ( class ! = BER_CLASS_UNI ) | | ( tag ! = BER_UNI_TAG_ENUMERATED ) )
) ) return FALSE ;
if ( ( tvb_get_guint8 ( tvb , offset ) = = 0 ) & & ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) )
return TRUE ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
hoffset = offset ;
2007-01-10 01:15:18 +00:00
2007-01-11 17:39:16 +00:00
offset = get_ber_identifier ( tvb , offset , & class , & pc , & tag ) ;
offset = get_ber_length ( NULL , tvb , offset , & len , NULL ) ;
eoffset = offset + len ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( eoffset < = hoffset ) return FALSE ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
if ( ( class ! = BER_CLASS_APP ) & & ( class ! = BER_CLASS_PRI ) )
if ( ( class ! = BER_CLASS_UNI )
| | ( ( tag < BER_UNI_TAG_NumericString ) & & ( tag ! = BER_UNI_TAG_OCTETSTRING ) & & ( tag ! = BER_UNI_TAG_UTF8String ) ) )
return FALSE ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
return TRUE ;
2007-01-12 00:33:32 +00:00
2007-01-11 17:39:16 +00:00
}
2007-01-10 01:15:18 +00:00
2005-12-04 21:45:38 +00:00
# include "packet-snmp-fn.c"
2007-01-09 18:38:55 +00:00
2005-12-04 21:45:38 +00:00
guint
dissect_snmp_pdu ( tvbuff_t * tvb , int offset , packet_info * pinfo ,
proto_tree * tree , int proto , gint ett , gboolean is_tcp )
{
guint length_remaining ;
gint8 class ;
gboolean pc , ind = 0 ;
gint32 tag ;
guint32 len ;
guint message_length ;
int start_offset = offset ;
guint32 version = 0 ;
proto_tree * snmp_tree = NULL ;
proto_item * item = NULL ;
2007-05-13 20:58:29 +00:00
asn1_ctx_t asn1_ctx ;
asn1_ctx_init ( & asn1_ctx , ASN1_ENC_BER , TRUE , pinfo ) ;
2005-12-04 21:45:38 +00:00
2007-01-09 18:38:55 +00:00
usm_p . msg_tvb = tvb ;
usm_p . start_offset = offset_from_real_beginning ( tvb , 0 ) ;
usm_p . engine_tvb = NULL ;
usm_p . user_tvb = NULL ;
usm_p . auth_item = NULL ;
usm_p . auth_tvb = NULL ;
usm_p . auth_offset = 0 ;
usm_p . priv_tvb = NULL ;
usm_p . user_assoc = NULL ;
usm_p . authenticated = FALSE ;
usm_p . encrypted = FALSE ;
2007-01-10 02:30:22 +00:00
usm_p . boots = 0 ;
usm_p . time = 0 ;
2007-01-11 00:29:50 +00:00
usm_p . authOK = FALSE ;
2007-01-12 00:33:32 +00:00
2005-12-04 21:45:38 +00:00
/*
* This will throw an exception if we don ' t have any data left .
* That ' s what we want . ( See " tcp_dissect_pdus() " , which is
* similar , but doesn ' t have to deal with ASN .1 .
* XXX - can we make " tcp_dissect_pdus() " provide enough
* information to the " get_pdu_len " routine so that we could
* have that routine deal with ASN .1 , and just use
* " tcp_dissect_pdus() " ? )
*/
length_remaining = tvb_ensure_length_remaining ( tvb , offset ) ;
/* NOTE: we have to parse the message piece by piece, since the
* capture length may be less than the message length : a ' global '
* parsing is likely to fail .
*/
/*
* If this is SNMP - over - TCP , we might have to do reassembly
* in order to read the " Sequence Of " header .
*/
if ( is_tcp & & snmp_desegment & & pinfo - > can_desegment ) {
/*
* This is TCP , and we should , and can , do reassembly .
*
* Is the " Sequence Of " header split across segment
* boundaries ? We requre at least 6 bytes for the
* header , which allows for a 4 - byte length ( ASN .1
* BER ) .
*/
if ( length_remaining < 6 ) {
pinfo - > desegment_offset = offset ;
pinfo - > desegment_len = 6 - length_remaining ;
/*
* Return 0 , which means " I didn't dissect anything
* because I don ' t have enough data - we need
* to desegment " .
*/
return 0 ;
}
}
/*
* OK , try to read the " Sequence Of " header ; this gets the total
* length of the SNMP message .
*/
/* Set tree to 0 to not display internakl BER fields if option used.*/
offset = dissect_ber_identifier ( pinfo , 0 , tvb , offset , & class , & pc , & tag ) ;
offset = dissect_ber_length ( pinfo , 0 , tvb , offset , & len , & ind ) ;
message_length = len + 2 ;
2007-05-15 05:49:43 +00:00
offset = dissect_ber_integer ( FALSE , & asn1_ctx , 0 , tvb , offset , - 1 , & version ) ;
2005-12-04 21:45:38 +00:00
/*
* If this is SNMP - over - TCP , we might have to do reassembly
* to get all of this message .
*/
if ( is_tcp & & snmp_desegment & & pinfo - > can_desegment ) {
/*
* Yes - is the message split across segment boundaries ?
*/
if ( length_remaining < message_length ) {
/*
* Yes . Tell the TCP dissector where the data
* for this message starts in the data it handed
* us , and how many more bytes we need , and
* return .
*/
pinfo - > desegment_offset = start_offset ;
pinfo - > desegment_len =
message_length - length_remaining ;
/*
* Return 0 , which means " I didn't dissect anything
* because I don ' t have enough data - we need
* to desegment " .
*/
return 0 ;
}
}
2006-06-13 13:21:12 +00:00
next_tvb_init ( & var_list ) ;
2005-12-04 21:45:38 +00:00
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) ) {
col_set_str ( pinfo - > cinfo , COL_PROTOCOL ,
proto_get_protocol_short_name ( find_protocol_by_id ( proto ) ) ) ;
}
if ( tree ) {
item = proto_tree_add_item ( tree , proto , tvb , offset ,
message_length , FALSE ) ;
snmp_tree = proto_item_add_subtree ( item , ett ) ;
}
switch ( version ) {
case 0 : /* v1 */
case 1 : /* v2c */
2007-05-13 20:58:29 +00:00
offset = dissect_snmp_Message ( FALSE , tvb , start_offset , & asn1_ctx , snmp_tree , - 1 ) ;
2005-12-04 21:45:38 +00:00
break ;
case 2 : /* v2u */
2007-05-13 20:58:29 +00:00
offset = dissect_snmp_Messagev2u ( FALSE , tvb , start_offset , & asn1_ctx , snmp_tree , - 1 ) ;
2005-12-04 21:45:38 +00:00
break ;
/* v3 */
case 3 :
2007-05-13 20:58:29 +00:00
offset = dissect_snmp_SNMPv3Message ( FALSE , tvb , start_offset , & asn1_ctx , snmp_tree , - 1 ) ;
2005-12-04 21:45:38 +00:00
break ;
default :
/*
* Return the length remaining in the tvbuff , so
* if this is SNMP - over - TCP , our caller thinks there ' s
* nothing left to dissect .
*/
proto_tree_add_text ( snmp_tree , tvb , offset , - 1 , " Unknown version " ) ;
return length_remaining ;
break ;
}
2006-06-13 13:21:12 +00:00
next_tvb_call ( & var_list , pinfo , tree , NULL , data_handle ) ;
2005-12-04 21:45:38 +00:00
2006-06-13 13:21:12 +00:00
return offset ;
2005-12-04 21:45:38 +00:00
}
static gint
dissect_snmp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
conversation_t * conversation ;
int offset ;
gint8 tmp_class ;
gboolean tmp_pc ;
gint32 tmp_tag ;
guint32 tmp_length ;
gboolean tmp_ind ;
2006-01-18 20:02:19 +00:00
/*
* See if this looks like SNMP or not . if not , return 0 so
2006-05-23 15:17:14 +00:00
* wireshark can try som other dissector instead .
2005-12-04 21:45:38 +00:00
*/
/* All SNMP packets are BER encoded and consist of a SEQUENCE
* that spans the entire PDU . The first item is an INTEGER that
* has the values 0 - 2 ( version 1 - 3 ) .
* if not it is not snmp .
*/
/* SNMP starts with a SEQUENCE */
offset = get_ber_identifier ( tvb , 0 , & tmp_class , & tmp_pc , & tmp_tag ) ;
if ( ( tmp_class ! = BER_CLASS_UNI ) | | ( tmp_tag ! = BER_UNI_TAG_SEQUENCE ) ) {
return 0 ;
}
/* then comes a length which spans the rest of the tvb */
offset = get_ber_length ( NULL , tvb , offset , & tmp_length , & tmp_ind ) ;
if ( tmp_length ! = ( guint32 ) tvb_reported_length_remaining ( tvb , offset ) ) {
return 0 ;
}
/* then comes an INTEGER (version)*/
offset = get_ber_identifier ( tvb , offset , & tmp_class , & tmp_pc , & tmp_tag ) ;
if ( ( tmp_class ! = BER_CLASS_UNI ) | | ( tmp_tag ! = BER_UNI_TAG_INTEGER ) ) {
return 0 ;
}
/* do we need to test that version is 0 - 2 (version1-3) ? */
/*
* The first SNMP packet goes to the SNMP port ; the second one
* may come from some * other * port , but goes back to the same
* IP address and port as the ones from which the first packet
* came ; all subsequent packets presumably go between those two
* IP addresses and ports .
*
* If this packet went to the SNMP port , we check to see if
* there ' s already a conversation with one address / port pair
* matching the source IP address and port of this packet ,
* the other address matching the destination IP address of this
* packet , and any destination port .
*
* If not , we create one , with its address 1 / port 1 pair being
* the source address / port of this packet , its address 2 being
* the destination address of this packet , and its port 2 being
* wildcarded , and give it the SNMP dissector as a dissector .
*/
if ( pinfo - > destport = = UDP_PORT_SNMP ) {
conversation = find_conversation ( pinfo - > fd - > num , & pinfo - > src , & pinfo - > dst , PT_UDP ,
pinfo - > srcport , 0 , NO_PORT_B ) ;
if ( ( conversation = = NULL ) | | ( conversation - > dissector_handle ! = snmp_handle ) ) {
conversation = conversation_new ( pinfo - > fd - > num , & pinfo - > src , & pinfo - > dst , PT_UDP ,
pinfo - > srcport , 0 , NO_PORT2 ) ;
conversation_set_dissector ( conversation , snmp_handle ) ;
}
}
return dissect_snmp_pdu ( tvb , 0 , pinfo , tree , proto_snmp , ett_snmp , FALSE ) ;
}
static void
dissect_snmp_tcp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
int offset = 0 ;
guint message_len ;
while ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
message_len = dissect_snmp_pdu ( tvb , 0 , pinfo , tree ,
proto_snmp , ett_snmp , TRUE ) ;
if ( message_len = = 0 ) {
/*
* We don ' t have all the data for that message ,
* so we need to do desegmentation ;
* " dissect_snmp_pdu() " has set that up .
*/
break ;
}
offset + = message_len ;
}
}
2006-03-15 06:20:23 +00:00
2005-12-04 21:45:38 +00:00
static void
dissect_smux ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
2006-03-15 06:20:23 +00:00
proto_tree * smux_tree = NULL ;
proto_item * item = NULL ;
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) )
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " SMUX " ) ;
if ( tree ) {
item = proto_tree_add_item ( tree , proto_smux , tvb , 0 , - 1 , FALSE ) ;
smux_tree = proto_item_add_subtree ( item , ett_smux ) ;
}
dissect_SMUX_PDUs_PDU ( tvb , pinfo , tree ) ;
2005-12-04 21:45:38 +00:00
}
2006-03-15 06:20:23 +00:00
2007-01-09 18:38:55 +00:00
/*
MD5 Password to Key Algorithm
2007-01-12 00:33:32 +00:00
from RFC 3414 A .2 .1
2007-01-09 18:38:55 +00:00
*/
2007-02-07 14:54:35 +00:00
static void snmp_usm_password_to_key_md5 ( const guint8 * password ,
2007-01-11 00:29:50 +00:00
guint passwordlen ,
const guint8 * engineID ,
guint engineLength ,
guint8 * key ) {
2007-01-09 18:38:55 +00:00
md5_state_t MD ;
guint8 * cp , password_buf [ 64 ] ;
guint32 password_index = 0 ;
guint32 count = 0 , i ;
guint8 key1 [ 16 ] ;
md5_init ( & MD ) ; /* initialize MD5 */
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/**********************************************/
/* Use while loop until we've done 1 Megabyte */
/**********************************************/
while ( count < 1048576 ) {
cp = password_buf ;
for ( i = 0 ; i < 64 ; i + + ) {
/*************************************************/
/* Take the next octet of the password, wrapping */
/* to the beginning of the password as necessary.*/
/*************************************************/
* cp + + = password [ password_index + + % passwordlen ] ;
}
md5_append ( & MD , password_buf , 64 ) ;
count + = 64 ;
}
md5_finish ( & MD , key1 ) ; /* tell MD5 we're done */
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/*****************************************************/
/* Now localize the key with the engineID and pass */
/* through MD5 to produce final key */
/* May want to ensure that engineLength <= 32, */
/* otherwise need to use a buffer larger than 64 */
/*****************************************************/
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
md5_init ( & MD ) ;
md5_append ( & MD , key1 , 16 ) ;
md5_append ( & MD , engineID , engineLength ) ;
md5_append ( & MD , key1 , 16 ) ;
md5_finish ( & MD , key ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
return ;
}
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/*
SHA1 Password to Key Algorithm COPIED from RFC 3414 A .2 .2
*/
2007-02-07 14:54:35 +00:00
static void snmp_usm_password_to_key_sha1 ( const guint8 * password ,
2007-01-11 00:29:50 +00:00
guint passwordlen ,
const guint8 * engineID ,
guint engineLength ,
guint8 * key ) {
2007-01-10 01:15:18 +00:00
sha1_context SH ;
2007-01-09 18:38:55 +00:00
guint8 * cp , password_buf [ 72 ] ;
guint32 password_index = 0 ;
guint32 count = 0 , i ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
sha1_starts ( & SH ) ; /* initialize SHA */
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/**********************************************/
/* Use while loop until we've done 1 Megabyte */
/**********************************************/
while ( count < 1048576 ) {
cp = password_buf ;
for ( i = 0 ; i < 64 ; i + + ) {
/*************************************************/
/* Take the next octet of the password, wrapping */
/* to the beginning of the password as necessary.*/
/*************************************************/
* cp + + = password [ password_index + + % passwordlen ] ;
}
2007-01-10 01:15:18 +00:00
sha1_update ( & SH , password_buf , 64 ) ;
2007-01-09 18:38:55 +00:00
count + = 64 ;
}
2007-01-10 01:15:18 +00:00
sha1_finish ( & SH , key ) ;
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/*****************************************************/
/* Now localize the key with the engineID and pass */
/* through SHA to produce final key */
/* May want to ensure that engineLength <= 32, */
/* otherwise need to use a buffer larger than 72 */
/*****************************************************/
memcpy ( password_buf , key , 20 ) ;
memcpy ( password_buf + 20 , engineID , engineLength ) ;
memcpy ( password_buf + 20 + engineLength , key , 20 ) ;
2007-01-12 00:33:32 +00:00
2007-01-10 01:15:18 +00:00
sha1_starts ( & SH ) ;
sha1_update ( & SH , password_buf , 40 + engineLength ) ;
sha1_finish ( & SH , key ) ;
2007-01-09 18:38:55 +00:00
return ;
}
2007-01-12 00:33:32 +00:00
2007-08-19 23:00:47 +00:00
static void process_prefs ( void ) { }
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
static void * snmp_users_copy_cb ( void * dest , const void * orig , unsigned len _U_ ) {
const snmp_ue_assoc_t * o = orig ;
snmp_ue_assoc_t * d = dest ;
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
d - > auth_model = o - > auth_model ;
d - > user . authModel = auth_models [ o - > auth_model ] ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > priv_proto = o - > priv_proto ;
d - > user . privProtocol = priv_protos [ o - > priv_proto ] ;
d - > user . userName . data = g_memdup ( o - > user . userName . data , o - > user . userName . len ) ;
d - > user . userName . len = o - > user . userName . len ;
d - > user . authPassword . data = o - > user . authPassword . data ? g_memdup ( o - > user . authPassword . data , o - > user . authPassword . len ) : NULL ;
d - > user . authPassword . len = o - > user . authPassword . len ;
d - > user . privPassword . data = o - > user . privPassword . data ? g_memdup ( o - > user . privPassword . data , o - > user . privPassword . len ) : NULL ;
d - > user . privPassword . len = o - > user . privPassword . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > engine . len = o - > engine . len ;
if ( o - > engine . data ) {
d - > engine . data = g_memdup ( o - > engine . data , o - > engine . len ) ;
}
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
d - > user . authKey . data = o - > user . authKey . data ? g_memdup ( o - > user . authKey . data , o - > user . authKey . len ) : NULL ;
d - > user . authKey . len = o - > user . authKey . len ;
d - > user . privKey . data = o - > user . privKey . data ? g_memdup ( o - > user . privKey . data , o - > user . privKey . len ) : NULL ;
d - > user . privKey . len = o - > user . privKey . len ;
2007-07-19 13:43:36 +00:00
2007-02-07 14:54:35 +00:00
return d ;
}
static void snmp_users_free_cb ( void * p ) {
snmp_ue_assoc_t * ue = p ;
if ( ue - > user . userName . data ) g_free ( ue - > user . userName . data ) ;
if ( ue - > user . authPassword . data ) g_free ( ue - > user . authPassword . data ) ;
if ( ue - > user . privPassword . data ) g_free ( ue - > user . privPassword . data ) ;
if ( ue - > user . authKey . data ) g_free ( ue - > user . authKey . data ) ;
if ( ue - > user . privKey . data ) g_free ( ue - > user . privKey . data ) ;
if ( ue - > engine . data ) g_free ( ue - > engine . data ) ;
}
2007-04-23 10:59:26 +00:00
static void snmp_users_update_cb ( void * p _U_ , const char * * err ) {
2007-02-07 14:54:35 +00:00
snmp_ue_assoc_t * ue = p ;
2007-02-07 18:51:44 +00:00
GString * es = g_string_new ( " " ) ;
2007-02-08 10:15:04 +00:00
* err = NULL ;
2007-02-07 18:51:44 +00:00
if ( ! ue - > user . userName . len ) g_string_append ( es , " no userName, " ) ;
if ( ue - > user . authPassword . len < 8 ) g_string_sprintfa ( es , " short authPassword (%d), " , ue - > user . authPassword . len ) ;
if ( ue - > user . privPassword . len < 8 ) g_string_sprintfa ( es , " short privPassword (%d), " , ue - > user . privPassword . len ) ;
2007-02-07 14:54:35 +00:00
2007-02-07 18:51:44 +00:00
if ( es - > len ) {
g_string_truncate ( es , es - > len - 2 ) ;
* err = ep_strdup ( es - > str ) ;
2007-01-09 18:38:55 +00:00
}
2007-07-19 13:43:36 +00:00
2007-02-07 18:51:44 +00:00
g_string_free ( es , TRUE ) ;
2007-07-19 13:43:36 +00:00
return ;
2005-12-04 21:45:38 +00:00
}
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
UAT_LSTRING_CB_DEF ( snmp_users , userName , snmp_ue_assoc_t , user . userName . data , user . userName . len )
UAT_LSTRING_CB_DEF ( snmp_users , authPassword , snmp_ue_assoc_t , user . authPassword . data , user . authPassword . len )
UAT_LSTRING_CB_DEF ( snmp_users , privPassword , snmp_ue_assoc_t , user . privPassword . data , user . privPassword . len )
UAT_BUFFER_CB_DEF ( snmp_users , engine_id , snmp_ue_assoc_t , engine . data , engine . len )
UAT_VS_DEF ( snmp_users , auth_model , snmp_ue_assoc_t , 0 , " MD5 " )
UAT_VS_DEF ( snmp_users , priv_proto , snmp_ue_assoc_t , 0 , " DES " )
2007-01-12 00:33:32 +00:00
2007-01-09 18:38:55 +00:00
/*--- proto_register_snmp -------------------------------------------*/
2007-01-12 00:33:32 +00:00
void proto_register_snmp ( void ) {
2005-12-04 21:45:38 +00:00
/* List of fields */
static hf_register_info hf [ ] = {
{ & hf_snmp_v3_flags_auth ,
{ " Authenticated " , " snmp.v3.flags.auth " , FT_BOOLEAN , 8 ,
TFS ( & flags_set_truth ) , TH_AUTH , " " , HFILL } } ,
{ & hf_snmp_v3_flags_crypt ,
{ " Encrypted " , " snmp.v3.flags.crypt " , FT_BOOLEAN , 8 ,
TFS ( & flags_set_truth ) , TH_CRYPT , " " , HFILL } } ,
{ & hf_snmp_v3_flags_report ,
{ " Reportable " , " snmp.v3.flags.report " , FT_BOOLEAN , 8 ,
TFS ( & flags_set_truth ) , TH_REPORT , " " , HFILL } } ,
{ & hf_snmp_engineid_conform , {
" Engine ID Conformance " , " snmp.engineid.conform " , FT_BOOLEAN , 8 ,
TFS ( & tfs_snmp_engineid_conform ) , F_SNMP_ENGINEID_CONFORM , " Engine ID RFC3411 Conformance " , HFILL } } ,
{ & hf_snmp_engineid_enterprise , {
" Engine Enterprise ID " , " snmp.engineid.enterprise " , FT_UINT32 , BASE_DEC ,
VALS ( sminmpec_values ) , 0 , " Engine Enterprise ID " , HFILL } } ,
{ & hf_snmp_engineid_format , {
" Engine ID Format " , " snmp.engineid.format " , FT_UINT8 , BASE_DEC ,
VALS ( snmp_engineid_format_vals ) , 0 , " Engine ID Format " , HFILL } } ,
{ & hf_snmp_engineid_ipv4 , {
" Engine ID Data: IPv4 address " , " snmp.engineid.ipv4 " , FT_IPv4 , BASE_NONE ,
NULL , 0 , " Engine ID Data: IPv4 address " , HFILL } } ,
{ & hf_snmp_engineid_ipv6 , {
" Engine ID Data: IPv6 address " , " snmp.engineid.ipv6 " , FT_IPv6 , BASE_NONE ,
NULL , 0 , " Engine ID Data: IPv6 address " , HFILL } } ,
{ & hf_snmp_engineid_mac , {
" Engine ID Data: MAC address " , " snmp.engineid.mac " , FT_ETHER , BASE_NONE ,
NULL , 0 , " Engine ID Data: MAC address " , HFILL } } ,
{ & hf_snmp_engineid_text , {
" Engine ID Data: Text " , " snmp.engineid.text " , FT_STRING , BASE_NONE ,
NULL , 0 , " Engine ID Data: Text " , HFILL } } ,
{ & hf_snmp_engineid_time , {
" Engine ID Data: Time " , " snmp.engineid.time " , FT_ABSOLUTE_TIME , BASE_NONE ,
NULL , 0 , " Engine ID Data: Time " , HFILL } } ,
{ & hf_snmp_engineid_data , {
" Engine ID Data " , " snmp.engineid.data " , FT_BYTES , BASE_HEX ,
NULL , 0 , " Engine ID Data " , HFILL } } ,
2007-01-09 18:38:55 +00:00
{ & hf_snmp_msgAuthentication ,
2007-01-11 17:39:16 +00:00
{ " Authentication " , " snmp.v3.auth " , FT_BOOLEAN , 8 ,
2007-01-09 18:38:55 +00:00
TFS ( & auth_flags ) , 0 , " " , HFILL } } ,
{ & hf_snmp_decryptedPDU , {
2007-01-10 01:15:18 +00:00
" Decrypted ScopedPDU " , " snmp.decrypted_pdu " , FT_BYTES , BASE_HEX ,
2007-01-09 18:38:55 +00:00
NULL , 0 , " Decrypted PDU " , HFILL } } ,
2007-08-23 19:45:31 +00:00
{ & hf_snmp_noSuchObject , { " noSuchObject " , " snmp.noSuchObject " , FT_NONE , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_noSuchInstance , { " noSuchInstance " , " snmp.noSuchInstance " , FT_NONE , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_endOfMibView , { " endOfMibView " , " snmp.endOfMibView " , FT_NONE , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_unSpecified , { " unSpecified " , " snmp.unSpecified " , FT_NONE , BASE_DEC , NULL , 0 , " " , HFILL } } ,
2007-08-19 23:00:47 +00:00
{ & hf_snmp_integer32_value , { " Value (Integer32) " , " snmp.value.int " , FT_INT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_octestring_value , { " Value (OctetString) " , " snmp.value.octets " , FT_BYTES , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_oid_value , { " Value (OID) " , " snmp.value.oid " , FT_OID , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_null_value , { " Value (Null) " , " snmp.value.null " , FT_NONE , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_ipv4_value , { " Value (IpAddress) " , " snmp.value.ipv4 " , FT_IPv4 , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_ipv6_value , { " Value (IpAddress) " , " snmp.value.ipv6 " , FT_IPv6 , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_anyaddress_value , { " Value (IpAddress) " , " snmp.value.addr " , FT_BYTES , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_unsigned32_value , { " Value (Unsigned32) " , " snmp.value.u32 " , FT_INT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_gauge32_value , { " Value (Gauge32) " , " snmp.value.g32 " , FT_INT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_unknown_value , { " Value (Unknown) " , " snmp.value.unk " , FT_BYTES , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_counter_value , { " Value (Counter32) " , " snmp.value.counter " , FT_UINT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_nsap_value , { " Value (NSAP) " , " snmp.value.nsap " , FT_UINT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_timeticks_value , { " Value (Timeticks) " , " snmp.value.timeticks " , FT_UINT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_opaque_value , { " Value (Opaque) " , " snmp.value.opaque " , FT_BYTES , BASE_NONE , NULL , 0 , " " , HFILL } } ,
{ & hf_snmp_objectname , { " Object Name " , " snmp.name " , FT_OID , BASE_NONE , NULL , 0 , " " , HFILL } } ,
2007-08-23 19:45:31 +00:00
{ & hf_snmp_scalar_instance_index , { " Scalar Instance Index " , " snmp.name.index " , FT_UINT64 , BASE_DEC , NULL , 0 , " " , HFILL } } ,
2005-12-04 21:45:38 +00:00
# include "packet-snmp-hfarr.c"
} ;
/* List of subtrees */
static gint * ett [ ] = {
& ett_snmp ,
& ett_engineid ,
& ett_msgFlags ,
2007-01-09 18:38:55 +00:00
& ett_encryptedPDU ,
& ett_decrypted ,
& ett_authParameters ,
2007-04-05 22:16:12 +00:00
& ett_internet ,
2007-08-19 23:00:47 +00:00
& ett_varbind ,
2007-08-23 19:45:31 +00:00
& ett_name ,
2007-08-19 23:00:47 +00:00
& ett_decoding_error ,
2005-12-04 21:45:38 +00:00
# include "packet-snmp-ettarr.c"
} ;
2007-02-07 14:54:35 +00:00
module_t * snmp_module ;
2007-08-19 23:00:47 +00:00
static uat_field_t users_fields [ ] = {
2007-02-12 19:57:41 +00:00
UAT_FLD_BUFFER ( snmp_users , engine_id , " Engine-id for this entry (empty = any) " ) ,
UAT_FLD_LSTRING ( snmp_users , userName , " The username " ) ,
UAT_FLD_VS ( snmp_users , auth_model , auth_types , " Algorithm to be used for authentication. " ) ,
UAT_FLD_LSTRING ( snmp_users , authPassword , " The password used for authenticating packets for this entry " ) ,
UAT_FLD_VS ( snmp_users , priv_proto , priv_types , " Algorithm to be used for privacy. " ) ,
UAT_FLD_LSTRING ( snmp_users , privPassword , " The password used for encrypting packets for this entry " ) ,
2007-02-07 14:54:35 +00:00
UAT_END_FIELDS
} ;
2007-08-19 23:00:47 +00:00
2007-02-07 14:54:35 +00:00
assocs_uat = uat_new ( " SNMP Users " ,
sizeof ( snmp_ue_assoc_t ) ,
" snmp_users " ,
( void * * ) & ueas ,
& num_ueas ,
UAT_CAT_CRYPTO ,
" ChSNMPUsersSection " ,
snmp_users_copy_cb ,
snmp_users_update_cb ,
snmp_users_free_cb ,
2007-08-19 23:00:47 +00:00
users_fields ) ;
2005-12-04 21:45:38 +00:00
/* Register protocol */
proto_snmp = proto_register_protocol ( PNAME , PSNAME , PFNAME ) ;
new_register_dissector ( " snmp " , dissect_snmp , proto_snmp ) ;
2006-01-18 20:02:19 +00:00
2005-12-04 21:45:38 +00:00
/* Register fields and subtrees */
proto_register_field_array ( proto_snmp , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
/* Register configuration preferences */
snmp_module = prefs_register_protocol ( proto_snmp , process_prefs ) ;
prefs_register_bool_preference ( snmp_module , " display_oid " ,
" Show SNMP OID in info column " ,
" Whether the SNMP OID should be shown in the info column " ,
& display_oid ) ;
2007-08-19 23:00:47 +00:00
prefs_register_obsolete_preference ( snmp_module , " mib_modules " ) ;
prefs_register_obsolete_preference ( snmp_module , " var_in_tree " ) ;
prefs_register_obsolete_preference ( snmp_module , " users_file " ) ;
2005-12-04 21:45:38 +00:00
prefs_register_bool_preference ( snmp_module , " desegment " ,
" Reassemble SNMP-over-TCP messages \n spanning multiple TCP segments " ,
" Whether the SNMP dissector should reassemble messages spanning multiple TCP segments. "
" To use this option, you must also enable \" Allow subdissectors to reassemble TCP streams \" in the TCP protocol settings. " ,
& snmp_desegment ) ;
2007-01-12 00:33:32 +00:00
2007-02-07 14:54:35 +00:00
prefs_register_uat_preference ( snmp_module , " users_table " ,
" Users Table " ,
" Table of engine-user associations used for authentication and decryption " ,
assocs_uat ) ;
2007-08-19 23:00:47 +00:00
2007-01-11 00:29:50 +00:00
register_init_routine ( renew_ue_cache ) ;
2005-12-04 21:45:38 +00:00
}
/*--- proto_reg_handoff_snmp ---------------------------------------*/
void proto_reg_handoff_snmp ( void ) {
dissector_handle_t snmp_tcp_handle ;
snmp_handle = find_dissector ( " snmp " ) ;
dissector_add ( " udp.port " , UDP_PORT_SNMP , snmp_handle ) ;
dissector_add ( " udp.port " , UDP_PORT_SNMP_TRAP , snmp_handle ) ;
dissector_add ( " ethertype " , ETHERTYPE_SNMP , snmp_handle ) ;
dissector_add ( " ipx.socket " , IPX_SOCKET_SNMP_AGENT , snmp_handle ) ;
dissector_add ( " ipx.socket " , IPX_SOCKET_SNMP_SINK , snmp_handle ) ;
dissector_add ( " hpext.dxsap " , HPEXT_SNMP , snmp_handle ) ;
snmp_tcp_handle = create_dissector_handle ( dissect_snmp_tcp , proto_snmp ) ;
dissector_add ( " tcp.port " , TCP_PORT_SNMP , snmp_tcp_handle ) ;
dissector_add ( " tcp.port " , TCP_PORT_SNMP_TRAP , snmp_tcp_handle ) ;
data_handle = find_dissector ( " data " ) ;
/*
* Process preference settings .
*
* We can ' t do this in the register routine , as preferences aren ' t
* read until all dissector register routines have been called ( so
* that all dissector preferences have been registered ) .
*/
process_prefs ( ) ;
}
void
proto_register_smux ( void )
{
static hf_register_info hf [ ] = {
{ & hf_smux_version ,
{ " Version " , " smux.version " , FT_UINT8 , BASE_DEC , NULL ,
0x0 , " " , HFILL } } ,
{ & hf_smux_pdutype ,
{ " PDU type " , " smux.pdutype " , FT_UINT8 , BASE_DEC , VALS ( smux_types ) ,
0x0 , " " , HFILL } } ,
} ;
static gint * ett [ ] = {
& ett_smux ,
} ;
proto_smux = proto_register_protocol ( " SNMP Multiplex Protocol " ,
" SMUX " , " smux " ) ;
proto_register_field_array ( proto_smux , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
}
void
proto_reg_handoff_smux ( void )
{
dissector_handle_t smux_handle ;
smux_handle = create_dissector_handle ( dissect_smux , proto_smux ) ;
dissector_add ( " tcp.port " , TCP_PORT_SMUX , smux_handle ) ;
}