/* 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
* Updated to use the asn2wrs compiler made by Tomas Kukosa
* Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
*
* See RFC 3414 for User-based Security Model for SNMPv3
* See RFC 3826 for (AES) Cipher Algorithm in the SNMP USM
* See RFC 2578 for Structure of Management Information Version 2 (SMIv2)
* Copyright (C) 2007 Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
*
* $Id: packet-snmp-template.c 23436 2007-11-12 18:44:29Z gerald $
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* 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.
*/
#define D(args) do {printf args; fflush(stdout); } while(0)
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/strutil.h>
#include <epan/conversation.h>
#include "etypes.h"
#include <epan/prefs.h>
#include <epan/sminmpec.h>
#include <epan/emem.h>
#include <epan/next_tvb.h>
#include <epan/uat.h>
#include <epan/asn1.h>
#include "packet-ipx.h"
#include "packet-hpext.h"
#include "packet-ber.h"
#include "packet-snmp.h"
#include <epan/crypt/crypt-sha1.h>
#include <epan/crypt/crypt-md5.h>
#include <epan/expert.h>
#include <epan/report_err.h>
#include <epan/oids.h>
#ifdef HAVE_LIBGCRYPT
#ifdef _WIN32
#include <winposixtype.h>
#endif /* _WIN32 */
#include <gcrypt.h>
#endif
/* 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)) : "")
#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
#define UDP_PORT_SNMP_PATROL 8161
/* Initialize the protocol and registered fields */
static int proto_snmp = -1;
static int proto_smux = -1;
static gboolean display_oid = TRUE;
static gboolean snmp_var_in_tree = TRUE;
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;
static snmp_ue_assoc_t* localized_ues = NULL;
static snmp_ue_assoc_t* unlocalized_ues = NULL;
/****/
static snmp_usm_params_t usm_p = {FALSE,FALSE,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,FALSE};
#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;
tvbuff_t *oid_tvb=NULL;
tvbuff_t *value_tvb=NULL;
static dissector_handle_t snmp_handle;
static dissector_handle_t data_handle;
static next_tvb_list_t var_list;
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;
static int hf_snmp_decryptedPDU = -1;
static int hf_snmp_msgAuthentication = -1;
static int hf_snmp_noSuchObject = -1;
static int hf_snmp_noSuchInstance = -1;
static int hf_snmp_endOfMibView = -1;
static int hf_snmp_unSpecified = -1;
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;
static int hf_snmp_objectname = -1;
static int hf_snmp_scalar_instance_index = -1;
#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;
static gint ett_encryptedPDU = -1;
static gint ett_decrypted = -1;
static gint ett_authParameters = -1;
static gint ett_internet = -1;
static gint ett_varbind = -1;
static gint ett_name = -1;
static gint ett_value = -1;
static gint ett_decoding_error = -1;
#include "packet-snmp-ett.c"
static const true_false_string auth_flags = {
"OK",
"Failed"
};
/* 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 }
};
#define SNMP_IPA 0 /* IP Address */
#define SNMP_CNT 1 /* Counter (Counter32) */
#define SNMP_GGE 2 /* Gauge (Gaug