1 /* packet-snmp.c
2  * Routines for SNMP (simple network management protocol)
3  * Copyright (C) 1998 Didier Jorand
4  *
5  * See RFC 1157 for SNMPv1.
6  *
7  * See RFCs 1901, 1905, and 1906 for SNMPv2c.
8  *
9  * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
10  *
11  * See RFCs 2570-2576 for SNMPv3
12  * Updated to use the asn2wrs compiler made by Tomas Kukosa
13  * Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
14  *
15  * See RFC 3414 for User-based Security Model for SNMPv3
16  * See RFC 3826 for  (AES) Cipher Algorithm in the SNMP USM
17  * See RFC 2578 for Structure of Management Information Version 2 (SMIv2)
18  * Copyright (C) 2007 Luis E. Garcia Ontanon <luis@ontanon.org>
19  *
20  * Wireshark - Network traffic analyzer
21  * By Gerald Combs <gerald@wireshark.org>
22  * Copyright 1998 Gerald Combs
23  *
24  * Some stuff from:
25  *
26  * GXSNMP -- An snmp mangament application
27  * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
28  * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
29  *
30  * SPDX-License-Identifier: GPL-2.0-or-later
31  */
32 
33 #if 0
34 #include <stdio.h>
35 #define D(args) do {printf args; fflush(stdout); } while(0)
36 #endif
37 
38 #include "config.h"
39 
40 #include <epan/packet.h>
41 #include <epan/strutil.h>
42 #include <epan/conversation.h>
43 #include <epan/etypes.h>
44 #include <epan/prefs.h>
45 #include <epan/addr_resolv.h>
46 #include <epan/next_tvb.h>
47 #include <epan/uat.h>
48 #include <epan/asn1.h>
49 #include <epan/expert.h>
50 #include <epan/oids.h>
51 #include <epan/srt_table.h>
52 #include <epan/tap.h>
53 #include "packet-ipx.h"
54 #include "packet-hpext.h"
55 #include "packet-ber.h"
56 #include "packet-snmp.h"
57 #include <wsutil/wsgcrypt.h>
58 
59 #define PNAME  "Simple Network Management Protocol"
60 #define PSNAME "SNMP"
61 #define PFNAME "snmp"
62 
63 #define UDP_PORT_SNMP		161
64 #define UDP_PORT_SNMP_TRAP	162
65 #define TCP_PORT_SNMP		161
66 #define TCP_PORT_SNMP_TRAP	162
67 #define TCP_PORT_SMUX		199
68 #define UDP_PORT_SNMP_PATROL 8161
69 #define SNMP_NUM_PROCEDURES 8
70 
71 /* Initialize the protocol and registered fields */
72 static int snmp_tap = -1;
73 static int proto_snmp = -1;
74 static int proto_smux = -1;
75 
76 static gboolean display_oid = TRUE;
77 static gboolean snmp_var_in_tree = TRUE;
78 
79 void proto_register_snmp(void);
80 void proto_reg_handoff_snmp(void);
81 void proto_register_smux(void);
82 void proto_reg_handoff_smux(void);
83 
84 static void snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password, guint passwordlen,
85 	const guint8 *engineID, guint engineLength, guint8 *key);
86 
87 static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
88 static tvbuff_t* snmp_usm_priv_aes128(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
89 static tvbuff_t* snmp_usm_priv_aes192(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
90 static tvbuff_t* snmp_usm_priv_aes256(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
91 
92 static gboolean snmp_usm_auth(const packet_info *pinfo, const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8**, guint*, gchar const**);
93 
94 static const value_string auth_types[] = {
95 	{SNMP_USM_AUTH_MD5,"MD5"},
96 	{SNMP_USM_AUTH_SHA1,"SHA1"},
97 	{SNMP_USM_AUTH_SHA2_224,"SHA2-224"},
98 	{SNMP_USM_AUTH_SHA2_256,"SHA2-256"},
99 	{SNMP_USM_AUTH_SHA2_384,"SHA2-384"},
100 	{SNMP_USM_AUTH_SHA2_512,"SHA2-512"},
101 	{0,NULL}
102 };
103 
104 static const guint auth_hash_len[] = {
105 	HASH_MD5_LENGTH,
106 	HASH_SHA1_LENGTH,
107 	HASH_SHA2_224_LENGTH,
108 	HASH_SHA2_256_LENGTH,
109 	HASH_SHA2_384_LENGTH,
110 	HASH_SHA2_512_LENGTH
111 };
112 
113 static const guint auth_tag_len[] = {
114 	12,
115 	12,
116 	16,
117 	24,
118 	32,
119 	48
120 };
121 
122 static const enum gcry_md_algos auth_hash_algo[] = {
123 	GCRY_MD_MD5,
124 	GCRY_MD_SHA1,
125 	GCRY_MD_SHA224,
126 	GCRY_MD_SHA256,
127 	GCRY_MD_SHA384,
128 	GCRY_MD_SHA512
129 };
130 
131 #define PRIV_DES	0
132 #define PRIV_AES128	1
133 #define PRIV_AES192	2
134 #define PRIV_AES256	3
135 
136 static const value_string priv_types[] = {
137 	{ PRIV_DES,    "DES" },
138 	{ PRIV_AES128, "AES" },
139 	{ PRIV_AES192, "AES192" },
140 	{ PRIV_AES256, "AES256" },
141 	{ 0, NULL}
142 };
143 static snmp_usm_decoder_t priv_protos[] = {
144 	snmp_usm_priv_des,
145 	snmp_usm_priv_aes128,
146 	snmp_usm_priv_aes192,
147 	snmp_usm_priv_aes256
148 };
149 
150 static snmp_ue_assoc_t* ueas = NULL;
151 static guint num_ueas = 0;
152 static snmp_ue_assoc_t* localized_ues = NULL;
153 static snmp_ue_assoc_t* unlocalized_ues = NULL;
154 /****/
155 
156 /* Variables used for handling enterprise specific trap types */
157 typedef struct _snmp_st_assoc_t {
158 	char *enterprise;
159 	guint trap;
160 	char *desc;
161 } snmp_st_assoc_t;
162 static guint num_specific_traps = 0;
163 static snmp_st_assoc_t *specific_traps = NULL;
164 static const char *enterprise_oid = NULL;
165 static guint generic_trap = 0;
166 static guint32 snmp_version = 0;
167 static guint32 RequestID = -1;
168 
169 static snmp_usm_params_t usm_p = {FALSE,FALSE,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,FALSE};
170 
171 #define TH_AUTH   0x01
172 #define TH_CRYPT  0x02
173 #define TH_REPORT 0x04
174 
175 /* desegmentation of SNMP-over-TCP */
176 static gboolean snmp_desegment = TRUE;
177 
178 /* Global variables */
179 
180 guint32 MsgSecurityModel;
181 tvbuff_t *oid_tvb=NULL;
182 tvbuff_t *value_tvb=NULL;
183 
184 static dissector_handle_t snmp_handle;
185 static dissector_handle_t data_handle;
186 
187 static next_tvb_list_t *var_list;
188 
189 static int hf_snmp_response_in = -1;
190 static int hf_snmp_response_to = -1;
191 static int hf_snmp_time = -1;
192 
193 static int hf_snmp_v3_flags_auth = -1;
194 static int hf_snmp_v3_flags_crypt = -1;
195 static int hf_snmp_v3_flags_report = -1;
196 
197 static int hf_snmp_engineid_conform = -1;
198 static int hf_snmp_engineid_enterprise = -1;
199 static int hf_snmp_engineid_format = -1;
200 static int hf_snmp_engineid_ipv4 = -1;
201 static int hf_snmp_engineid_ipv6 = -1;
202 static int hf_snmp_engineid_cisco_type = -1;
203 static int hf_snmp_engineid_mac = -1;
204 static int hf_snmp_engineid_text = -1;
205 static int hf_snmp_engineid_time = -1;
206 static int hf_snmp_engineid_data = -1;
207 static int hf_snmp_decryptedPDU = -1;
208 static int hf_snmp_msgAuthentication = -1;
209 
210 static int hf_snmp_noSuchObject = -1;
211 static int hf_snmp_noSuchInstance = -1;
212 static int hf_snmp_endOfMibView = -1;
213 static int hf_snmp_unSpecified = -1;
214 
215 static int hf_snmp_integer32_value = -1;
216 static int hf_snmp_octetstring_value = -1;
217 static int hf_snmp_oid_value = -1;
218 static int hf_snmp_null_value = -1;
219 static int hf_snmp_ipv4_value = -1;
220 static int hf_snmp_ipv6_value = -1;
221 static int hf_snmp_anyaddress_value = -1;
222 static int hf_snmp_unsigned32_value = -1;
223 static int hf_snmp_unknown_value = -1;
224 static int hf_snmp_opaque_value = -1;
225 static int hf_snmp_nsap_value = -1;
226 static int hf_snmp_counter_value = -1;
227 static int hf_snmp_timeticks_value = -1;
228 static int hf_snmp_big_counter_value = -1;
229 static int hf_snmp_gauge32_value = -1;
230 
231 static int hf_snmp_objectname = -1;
232 static int hf_snmp_scalar_instance_index = -1;
233 
234 static int hf_snmp_var_bind_str = -1;
235 static int hf_snmp_agentid_trailer = -1;
236 
237 #include "packet-snmp-hf.c"
238 
239 /* Initialize the subtree pointers */
240 static gint ett_smux = -1;
241 static gint ett_snmp = -1;
242 static gint ett_engineid = -1;
243 static gint ett_msgFlags = -1;
244 static gint ett_encryptedPDU = -1;
245 static gint ett_decrypted = -1;
246 static gint ett_authParameters = -1;
247 static gint ett_internet = -1;
248 static gint ett_varbind = -1;
249 static gint ett_name = -1;
250 static gint ett_value = -1;
251 static gint ett_decoding_error = -1;
252 
253 #include "packet-snmp-ett.c"
254 
255 static expert_field ei_snmp_failed_decrypted_data_pdu = EI_INIT;
256 static expert_field ei_snmp_decrypted_data_bad_formatted = EI_INIT;
257 static expert_field ei_snmp_verify_authentication_error = EI_INIT;
258 static expert_field ei_snmp_authentication_ok = EI_INIT;
259 static expert_field ei_snmp_authentication_error = EI_INIT;
260 static expert_field ei_snmp_varbind_not_uni_class_seq = EI_INIT;
261 static expert_field ei_snmp_varbind_has_indicator = EI_INIT;
262 static expert_field ei_snmp_objectname_not_oid = EI_INIT;
263 static expert_field ei_snmp_objectname_has_indicator = EI_INIT;
264 static expert_field ei_snmp_value_not_primitive_encoding = EI_INIT;
265 static expert_field ei_snmp_invalid_oid = EI_INIT;
266 static expert_field ei_snmp_varbind_wrong_tag = EI_INIT;
267 static expert_field ei_snmp_varbind_response = EI_INIT;
268 static expert_field ei_snmp_no_instance_subid = EI_INIT;
269 static expert_field ei_snmp_wrong_num_of_subids = EI_INIT;
270 static expert_field ei_snmp_index_suboid_too_short = EI_INIT;
271 static expert_field ei_snmp_unimplemented_instance_index = EI_INIT;
272 static expert_field ei_snmp_index_suboid_len0 = EI_INIT;
273 static expert_field ei_snmp_index_suboid_too_long = EI_INIT;
274 static expert_field ei_snmp_index_string_too_long = EI_INIT;
275 static expert_field ei_snmp_column_parent_not_row = EI_INIT;
276 static expert_field ei_snmp_uint_too_large = EI_INIT;
277 static expert_field ei_snmp_int_too_large = EI_INIT;
278 static expert_field ei_snmp_integral_value0 = EI_INIT;
279 static expert_field ei_snmp_missing_mib = EI_INIT;
280 static expert_field ei_snmp_varbind_wrong_length_value = EI_INIT;
281 static expert_field ei_snmp_varbind_wrong_class_tag = EI_INIT;
282 static expert_field ei_snmp_rfc1910_non_conformant = EI_INIT;
283 static expert_field ei_snmp_rfc3411_non_conformant = EI_INIT;
284 static expert_field ei_snmp_version_unknown = EI_INIT;
285 static expert_field ei_snmp_trap_pdu_obsolete = EI_INIT;
286 
287 static const true_false_string auth_flags = {
288 	"OK",
289 	"Failed"
290 };
291 
292 /* Security Models */
293 
294 #define SNMP_SEC_ANY			0
295 #define SNMP_SEC_V1			1
296 #define SNMP_SEC_V2C			2
297 #define SNMP_SEC_USM			3
298 
299 static const value_string sec_models[] = {
300 	{ SNMP_SEC_ANY,			"Any" },
301 	{ SNMP_SEC_V1,			"V1" },
302 	{ SNMP_SEC_V2C,			"V2C" },
303 	{ SNMP_SEC_USM,			"USM" },
304 	{ 0,				NULL }
305 };
306 
307 #if 0
308 /* SMUX PDU types */
309 #define SMUX_MSG_OPEN 		0
310 #define SMUX_MSG_CLOSE		1
311 #define SMUX_MSG_RREQ		2
312 #define SMUX_MSG_RRSP		3
313 #define SMUX_MSG_SOUT		4
314 
315 static const value_string smux_types[] = {
316 	{ SMUX_MSG_OPEN,	"Open" },
317 	{ SMUX_MSG_CLOSE,	"Close" },
318 	{ SMUX_MSG_RREQ,	"Registration Request" },
319 	{ SMUX_MSG_RRSP,	"Registration Response" },
320 	{ SMUX_MSG_SOUT,	"Commit Or Rollback" },
321 	{ 0,			NULL }
322 };
323 #endif
324 
325 /* Procedure names (used in Service Response Time) */
326 const value_string snmp_procedure_names[] = {
327 	{ 0,	"Get" },
328 	{ 1,	"GetNext" },
329 	{ 3,	"Set" },
330 	{ 4,	"Register" },
331 	{ 5,	"Bulk" },
332 	{ 6,	"Inform" },
333 	{ 0,	NULL }
334 };
335 
336 #define SNMP_IPA    0		/* IP Address */
337 #define SNMP_CNT    1		/* Counter (Counter32) */
338 #define SNMP_GGE    2		/* Gauge (Gauge32) */
339 #define SNMP_TIT    3		/* TimeTicks */
340 #define SNMP_OPQ    4		/* Opaque */
341 #define SNMP_NSP    5		/* NsapAddress */
342 #define SNMP_C64    6		/* Counter64 */
343 #define SNMP_U32    7		/* Uinteger32 */
344 
345 #define SERR_NSO    0
346 #define SERR_NSI    1
347 #define SERR_EOM    2
348 
349 
350 dissector_table_t value_sub_dissectors_table;
351 
352 /*
353  * Data structure attached to a conversation, request/response information
354  */
355 typedef struct snmp_conv_info_t {
356 	wmem_map_t *request_response;
357 } snmp_conv_info_t;
358 
359 static snmp_request_response_t *
snmp_get_request_response_pointer(wmem_map_t * map,guint32 requestId)360 snmp_get_request_response_pointer(wmem_map_t *map, guint32 requestId)
361 {
362 	snmp_request_response_t *srrp=(snmp_request_response_t *)wmem_map_lookup(map, &requestId);
363 	if (!srrp) {
364 		srrp=wmem_new0(wmem_file_scope(), snmp_request_response_t);
365 		srrp->requestId=requestId;
366 		wmem_map_insert(map, &(srrp->requestId), (void *)srrp);
367 	}
368 
369 	return srrp;
370 }
371 
372 static snmp_request_response_t*
snmp_match_request_response(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint requestId,guint procedure_id,snmp_conv_info_t * snmp_info)373 snmp_match_request_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint requestId, guint procedure_id, snmp_conv_info_t *snmp_info)
374 {
375 	snmp_request_response_t *srrp=NULL;
376 
377 	DISSECTOR_ASSERT_HINT(snmp_info, "No SNMP info from ASN1 context");
378 
379 	/* get or create request/response pointer based on request id */
380 	srrp=(snmp_request_response_t *)snmp_get_request_response_pointer(snmp_info->request_response, requestId);
381 
382 	// if not visited fill the request/response data
383 	if (!PINFO_FD_VISITED(pinfo)) {
384 		switch(procedure_id)
385 		{
386 			case SNMP_REQ_GET:
387 			case SNMP_REQ_GETNEXT:
388 			case SNMP_REQ_SET:
389 			case SNMP_REQ_GETBULK:
390 			case SNMP_REQ_INFORM:
391 				srrp->request_frame_id=pinfo->fd->num;
392 				srrp->response_frame_id=0;
393 				srrp->request_time=pinfo->abs_ts;
394 				srrp->request_procedure_id=procedure_id;
395 				break;
396 			case SNMP_RES_GET:
397 				srrp->response_frame_id=pinfo->fd->num;
398 				break;
399 			default:
400 				return NULL;
401 		}
402 	}
403 
404 	/* if request and response was matched */
405 	if (srrp->request_frame_id!=0 && srrp->response_frame_id!=0)
406 	{
407 		proto_item *it;
408 
409 		// if it is a request
410 		if (srrp->request_frame_id == pinfo->fd->num)
411 		{
412 			it=proto_tree_add_uint(tree, hf_snmp_response_in, tvb, 0, 0, srrp->response_frame_id);
413 			proto_item_set_generated(it);
414 		} else {
415 			nstime_t ns;
416 			it=proto_tree_add_uint(tree, hf_snmp_response_to, tvb, 0, 0, srrp->request_frame_id);
417 			proto_item_set_generated(it);
418 			nstime_delta(&ns, &pinfo->abs_ts, &srrp->request_time);
419 			it=proto_tree_add_time(tree, hf_snmp_time, tvb, 0, 0, &ns);
420 			proto_item_set_generated(it);
421 
422 			return srrp;
423 		}
424 	}
425 
426 	return NULL;
427 }
428 
429 static void
snmpstat_init(struct register_srt * srt _U_,GArray * srt_array)430 snmpstat_init(struct register_srt* srt _U_, GArray* srt_array)
431 {
432 	srt_stat_table *snmp_srt_table;
433 	guint32 i;
434 
435 	snmp_srt_table = init_srt_table("SNMP Commands", NULL, srt_array, SNMP_NUM_PROCEDURES, NULL, "snmp.data", NULL);
436 	for (i = 0; i < SNMP_NUM_PROCEDURES; i++)
437 	{
438 		init_srt_table_row(snmp_srt_table, i, val_to_str_const(i, snmp_procedure_names, "<unknown>"));
439 	}
440 }
441 
442 /* This is called only if request and response was matched -> no need to return anything than TAP_PACKET_REDRAW */
443 static tap_packet_status
snmpstat_packet(void * psnmp,packet_info * pinfo,epan_dissect_t * edt _U_,const void * psi)444 snmpstat_packet(void *psnmp, packet_info *pinfo, epan_dissect_t *edt _U_, const void *psi)
445 {
446 	guint i = 0;
447 	srt_stat_table *snmp_srt_table;
448 	const snmp_request_response_t *snmp=(const snmp_request_response_t *)psi;
449 	srt_data_t *data = (srt_data_t *)psnmp;
450 
451 	snmp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
452 
453 	add_srt_table_data(snmp_srt_table, snmp->request_procedure_id, &snmp->request_time, pinfo);
454 	return TAP_PACKET_REDRAW;
455 }
456 
457 static const gchar *
snmp_lookup_specific_trap(guint specific_trap)458 snmp_lookup_specific_trap (guint specific_trap)
459 {
460 	guint i;
461 
462 	for (i = 0; i < num_specific_traps; i++) {
463 		snmp_st_assoc_t *u = &(specific_traps[i]);
464 
465 		if ((u->trap == specific_trap) &&
466 		    (strcmp (u->enterprise, enterprise_oid) == 0))
467 		{
468 			return u->desc;
469 		}
470 	}
471 
472 	return NULL;
473 }
474 
475 static int
dissect_snmp_variable_string(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)476 dissect_snmp_variable_string(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
477 {
478 
479 	proto_tree_add_item(tree, hf_snmp_var_bind_str, tvb, 0, -1, ENC_ASCII|ENC_NA);
480 
481 	return tvb_captured_length(tvb);
482 }
483 
484 /*
485 DateAndTime ::= TEXTUAL-CONVENTION
486     DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
487     STATUS       current
488     DESCRIPTION
489             "A date-time specification.
490 
491             field  octets  contents                  range
492             -----  ------  --------                  -----
493               1      1-2   year*                     0..65536
494               2       3    month                     1..12
495               3       4    day                       1..31
496               4       5    hour                      0..23
497               5       6    minutes                   0..59
498               6       7    seconds                   0..60
499                            (use 60 for leap-second)
500               7       8    deci-seconds              0..9
501               8       9    direction from UTC        '+' / '-'
502               9      10    hours from UTC*           0..13
503              10      11    minutes from UTC          0..59
504 
505             * Notes:
506             - the value of year is in network-byte order
507             - daylight saving time in New Zealand is +13
508 
509             For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
510             displayed as:
511 
512                              1992-5-26,13:30:15.0,-4:0
513 
514             Note that if only local time is known, then timezone
515             information (fields 8-10) is not present."
516     SYNTAX       OCTET STRING (SIZE (8 | 11))
517 */
518 static proto_item *
dissect_snmp_variable_date_and_time(proto_tree * tree,packet_info * pinfo,int hfid,tvbuff_t * tvb,int offset,int length)519 dissect_snmp_variable_date_and_time(proto_tree *tree, packet_info *pinfo, int hfid, tvbuff_t *tvb, int offset, int length)
520 {
521 	guint16 year;
522 	guint8 month;
523 	guint8 day;
524 	guint8 hour;
525 	guint8 minutes;
526 	guint8 seconds;
527 	guint8 deci_seconds;
528 	guint8 hour_from_utc;
529 	guint8 min_from_utc;
530 	gchar *str;
531 
532 	year			= tvb_get_ntohs(tvb,offset);
533 	month			= tvb_get_guint8(tvb,offset+2);
534 	day			= tvb_get_guint8(tvb,offset+3);
535 	hour			= tvb_get_guint8(tvb,offset+4);
536 	minutes			= tvb_get_guint8(tvb,offset+5);
537 	seconds			= tvb_get_guint8(tvb,offset+6);
538 	deci_seconds		= tvb_get_guint8(tvb,offset+7);
539 	if(length > 8){
540 		hour_from_utc	= tvb_get_guint8(tvb,offset+9);
541 		min_from_utc	= tvb_get_guint8(tvb,offset+10);
542 
543 		str = wmem_strdup_printf(pinfo->pool,
544 			 "%u-%u-%u, %u:%u:%u.%u UTC %s%u:%u",
545 			 year,
546 			 month,
547 			 day,
548 			 hour,
549 			 minutes,
550 			 seconds,
551 			 deci_seconds,
552 			 tvb_get_string_enc(pinfo->pool,tvb,offset+8,1,ENC_ASCII|ENC_NA),
553 			 hour_from_utc,
554 			 min_from_utc);
555 	}else{
556 		 str = wmem_strdup_printf(pinfo->pool,
557 			 "%u-%u-%u, %u:%u:%u.%u",
558 			 year,
559 			 month,
560 			 day,
561 			 hour,
562 			 minutes,
563 			 seconds,
564 			 deci_seconds);
565 	}
566 
567 	return proto_tree_add_string(tree, hfid, tvb, offset, length, str);
568 
569 }
570 
571 /*
572  *  dissect_snmp_VarBind
573  *  this routine dissects variable bindings, looking for the oid information in our oid reporsitory
574  *  to format and add the value adequatelly.
575  *
576  * The choice to handwrite this code instead of using the asn compiler is to avoid having tons
577  * of uses of global variables distributed in very different parts of the code.
578  * Other than that there's a cosmetic thing: the tree from ASN generated code would be so
579  * convoluted due to the nesting of CHOICEs in the definition of VarBind/value.
580  *
581  * XXX: the length of this function (~400 lines) is an aberration!
582  *  oid_key_t:key_type could become a series of callbacks instead of an enum
583  *  the (! oid_info_is_ok) switch could be made into an array (would be slower)
584  *
585 
586 	NetworkAddress ::=  CHOICE { internet IpAddress }
587 	IpAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4))
588 	TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
589 	Integer32 ::= INTEGER (-2147483648..2147483647)
590 	ObjectName ::= OBJECT IDENTIFIER
591 	Counter32 ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
592 	Gauge32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
593 	Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
594 	Integer-value ::=  INTEGER (-2147483648..2147483647)
595 	Integer32 ::= INTEGER (-2147483648..2147483647)
596 	ObjectID-value ::= OBJECT IDENTIFIER
597 	Empty ::= NULL
598 	TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
599 	Opaque ::= [APPLICATION 4] IMPLICIT OCTET STRING
600 	Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615)
601 
602 	ObjectSyntax ::= CHOICE {
603 		 simple SimpleSyntax,
604 		 application-wide ApplicationSyntax
605 	}
606 
607 	SimpleSyntax ::= CHOICE {
608 	   integer-value Integer-value,
609 	   string-value String-value,
610 	   objectID-value ObjectID-value,
611 	   empty  Empty
612 	}
613 
614 	ApplicationSyntax ::= CHOICE {
615 	   ipAddress-value IpAddress,
616 	   counter-value Counter32,
617 	   timeticks-value TimeTicks,
618 	   arbitrary-value Opaque,
619 	   big-counter-value Counter64,
620 	   unsigned-integer-value Unsigned32
621 	}
622 
623 	ValueType ::=  CHOICE {
624 	   value ObjectSyntax,
625 	   unSpecified NULL,
626 	   noSuchObject[0] IMPLICIT NULL,
627 	   noSuchInstance[1] IMPLICIT NULL,
628 	   endOfMibView[2] IMPLICIT NULL
629 	}
630 
631 	VarBind ::= SEQUENCE {
632 	   name ObjectName,
633 	   valueType ValueType
634 	}
635 
636  */
637 
638 static int
dissect_snmp_VarBind(gboolean implicit_tag _U_,tvbuff_t * tvb,int offset,asn1_ctx_t * actx,proto_tree * tree,int hf_index _U_)639 dissect_snmp_VarBind(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset,
640 		     asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
641 {
642 	int seq_offset, name_offset, value_offset, value_start;
643 	guint32 seq_len, name_len, value_len;
644 	gint8 ber_class;
645 	gboolean pc;
646 	gint32 tag;
647 	gboolean ind;
648 	guint32* subids;
649 	guint8* oid_bytes;
650 	oid_info_t* oid_info = NULL;
651 	guint oid_matched, oid_left;
652 	proto_item *pi_name, *pi_varbind, *pi_value = NULL;
653 	proto_tree *pt, *pt_varbind, *pt_name, *pt_value;
654 	char label[ITEM_LABEL_LENGTH];
655 	const char* repr = NULL;
656 	const char* info_oid = NULL;
657 	char* valstr;
658 	int hfid = -1;
659 	int min_len = 0, max_len = 0;
660 	gboolean oid_info_is_ok;
661 	const char* oid_string = NULL;
662 	enum {BER_NO_ERROR, BER_WRONG_LENGTH, BER_WRONG_TAG} format_error = BER_NO_ERROR;
663 
664 	seq_offset = offset;
665 
666 	/* first have the VarBind's sequence header */
667 	offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag);
668 	offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &seq_len, &ind);
669 
670 	if (!pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_SEQUENCE) {
671 		proto_item* pi;
672 		pt = proto_tree_add_subtree(tree, tvb, seq_offset, seq_len + (offset - seq_offset),
673 				ett_decoding_error, &pi, "VarBind must be an universal class sequence");
674 		expert_add_info(actx->pinfo, pi, &ei_snmp_varbind_not_uni_class_seq);
675 		return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
676 	}
677 
678 	if (ind) {
679 		proto_item* pi;
680 		pt = proto_tree_add_subtree(tree, tvb, seq_offset, seq_len + (offset - seq_offset),
681 					ett_decoding_error, &pi, "Indicator must be clear in VarBind");
682 		expert_add_info(actx->pinfo, pi, &ei_snmp_varbind_has_indicator);
683 		return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
684 	}
685 
686 	/* we add the varbind tree root with a dummy label we'll fill later on */
687 	pt_varbind = proto_tree_add_subtree(tree,tvb,offset,seq_len,ett_varbind,&pi_varbind,"VarBind");
688 	*label = '\0';
689 
690 	seq_len += offset - seq_offset;
691 
692 	/* then we have the ObjectName's header */
693 
694 	offset = dissect_ber_identifier(actx->pinfo, pt_varbind, tvb, offset, &ber_class, &pc, &tag);
695 	name_offset = offset = dissect_ber_length(actx->pinfo, pt_varbind, tvb, offset, &name_len, &ind);
696 
697 	if (! ( !pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_OID) ) {
698 		proto_item* pi;
699 		pt = proto_tree_add_subtree(tree, tvb, seq_offset, seq_len,
700 				ett_decoding_error, &pi, "ObjectName must be an OID in primitive encoding");
701 		expert_add_info(actx->pinfo, pi, &ei_snmp_objectname_not_oid);
702 		return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
703 	}
704 
705 	if (ind) {
706 		proto_item* pi;
707 		pt = proto_tree_add_subtree(tree, tvb, seq_offset, seq_len,
708 				ett_decoding_error, &pi, "Indicator must be clear in ObjectName");
709 		expert_add_info(actx->pinfo, pi, &ei_snmp_objectname_has_indicator);
710 		return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt);
711 	}
712 
713 	pi_name = proto_tree_add_item(pt_varbind,hf_snmp_objectname,tvb,name_offset,name_len,ENC_NA);
714 	pt_name = proto_item_add_subtree(pi_name,ett_name);
715 
716 	offset += name_len;
717 	value_start = offset;
718 	/* then we have the value's header */
719 	offset = dissect_ber_identifier(actx->pinfo, pt_varbind, tvb, offset, &ber_class, &pc, &tag);
720 	value_offset = dissect_ber_length(actx->pinfo, pt_varbind, tvb, offset, &value_len, &ind);
721 
722 	if (! (!pc) ) {
723 		proto_item* pi;
724 		pt = proto_tree_add_subtree(pt_varbind, tvb, value_start, value_len,
725 				ett_decoding_error, &pi, "the value must be in primitive encoding");
726 		expert_add_info(actx->pinfo, pi, &ei_snmp_value_not_primitive_encoding);
727 		return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
728 	}
729 
730 	/* Now, we know where everithing is */
731 
732 	/* fetch ObjectName and its relative oid_info */
733 	oid_bytes = (guint8*)tvb_memdup(actx->pinfo->pool, tvb, name_offset, name_len);
734 	oid_info = oid_get_from_encoded(actx->pinfo->pool, oid_bytes, name_len, &subids, &oid_matched, &oid_left);
735 
736 	add_oid_debug_subtree(oid_info,pt_name);
737 
738 	if (!subids) {
739 		proto_item* pi;
740 
741 		repr = oid_encoded2string(actx->pinfo->pool, oid_bytes, name_len);
742 		pt = proto_tree_add_subtree_format(pt_name,tvb, 0, 0, ett_decoding_error, &pi, "invalid oid: %s", repr);
743 		expert_add_info_format(actx->pinfo, pi, &ei_snmp_invalid_oid, "invalid oid: %s", repr);
744 		return dissect_unknown_ber(actx->pinfo, tvb, name_offset, pt);
745 	}
746 
747 	if (oid_matched+oid_left) {
748 		oid_string = oid_subid2string(actx->pinfo->pool, subids,oid_matched+oid_left);
749 	}
750 
751 	if (ber_class == BER_CLASS_CON) {
752 		/* if we have an error value just add it and get out the way ASAP */
753 		proto_item* pi;
754 		const char* note;
755 
756 		if (value_len != 0) {
757 			min_len = max_len = 0;
758 			format_error = BER_WRONG_LENGTH;
759 		}
760 
761 		switch (tag) {
762 			case SERR_NSO:
763 				hfid = hf_snmp_noSuchObject;
764 				note = "noSuchObject";
765 				break;
766 			case SERR_NSI:
767 				hfid = hf_snmp_noSuchInstance;
768 				note = "noSuchInstance";
769 				break;
770 			case SERR_EOM:
771 				hfid = hf_snmp_endOfMibView;
772 				note = "endOfMibView";
773 				break;
774 			default: {
775 				pt = proto_tree_add_subtree_format(pt_varbind,tvb,0,0,ett_decoding_error,&pi,
776 								"Wrong tag for Error Value: expected 0, 1, or 2 but got: %d",tag);
777 				expert_add_info(actx->pinfo, pi, &ei_snmp_varbind_wrong_tag);
778 				return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
779 			}
780 		}
781 
782 		pi = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
783 		expert_add_info_format(actx->pinfo, pi, &ei_snmp_varbind_response, "%s",note);
784 		(void) g_strlcpy (label, note, ITEM_LABEL_LENGTH);
785 		goto set_label;
786 	}
787 
788 	/* 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 */
789 	switch (oid_info->kind) {
790 		case OID_KIND_SCALAR:
791 			if (oid_left == 1) {
792 				/* OK: we got the instance sub-id */
793 				proto_tree_add_uint64(pt_name,hf_snmp_scalar_instance_index,tvb,name_offset,name_len,subids[oid_matched]);
794 				oid_info_is_ok = TRUE;
795 				goto indexing_done;
796 			} else if (oid_left == 0) {
797 				if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
798 					/* unSpecified  does not require an instance sub-id add the new value and get off the way! */
799 					pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
800 					goto set_label;
801 				} else {
802 					proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_no_instance_subid,tvb,0,0);
803 					oid_info_is_ok = FALSE;
804 					goto indexing_done;
805 				}
806 			} else {
807 				proto_tree_add_expert_format(pt_name,actx->pinfo,&ei_snmp_wrong_num_of_subids,tvb,0,0,"A scalar should have only one instance sub-id this has: %d",oid_left);
808 				oid_info_is_ok = FALSE;
809 				goto indexing_done;
810 			}
811 		break;
812 		case OID_KIND_COLUMN:
813 			if ( oid_info->parent->kind == OID_KIND_ROW) {
814 				oid_key_t* k = oid_info->parent->key;
815 				guint key_start = oid_matched;
816 				guint key_len = oid_left;
817 				oid_info_is_ok = TRUE;
818 
819 				if ( key_len == 0 && ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
820 					/* unSpecified  does not require an instance sub-id add the new value and get off the way! */
821 					pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
822 					goto set_label;
823 				}
824 
825 				if (k) {
826 					for (;k;k = k->next) {
827 						guint suboid_len;
828 
829 						if (key_start >= oid_matched+oid_left) {
830 							proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_index_suboid_too_short,tvb,0,0);
831 							oid_info_is_ok = FALSE;
832 							goto indexing_done;
833 						}
834 
835 						switch(k->key_type) {
836 							case OID_KEY_TYPE_WRONG: {
837 								proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_unimplemented_instance_index,tvb,0,0);
838 								oid_info_is_ok = FALSE;
839 								goto indexing_done;
840 							}
841 							case OID_KEY_TYPE_INTEGER: {
842 								if (IS_FT_INT(k->ft_type)) {
843 									proto_tree_add_int(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
844 								} else { /* if it's not an unsigned int let proto_tree_add_uint throw a warning */
845 									proto_tree_add_uint64(pt_name,k->hfid,tvb,name_offset,name_len,(guint)subids[key_start]);
846 								}
847 								key_start++;
848 								key_len--;
849 								continue; /* k->next */
850 							}
851 							case OID_KEY_TYPE_IMPLIED_OID:
852 								suboid_len = key_len;
853 
854 								goto show_oid_index;
855 
856 							case OID_KEY_TYPE_OID: {
857 								guint8* suboid_buf;
858 								guint suboid_buf_len;
859 								guint32* suboid;
860 
861 								suboid_len = subids[key_start++];
862 								key_len--;
863 
864 show_oid_index:
865 								suboid = &(subids[key_start]);
866 
867 								if( suboid_len == 0 ) {
868 									proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_index_suboid_len0,tvb,0,0);
869 									oid_info_is_ok = FALSE;
870 									goto indexing_done;
871 								}
872 
873 								if( key_len < suboid_len ) {
874 									proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_index_suboid_too_long,tvb,0,0);
875 									oid_info_is_ok = FALSE;
876 									goto indexing_done;
877 								}
878 
879 								suboid_buf_len = oid_subid2encoded(actx->pinfo->pool, suboid_len, suboid, &suboid_buf);
880 
881 								DISSECTOR_ASSERT(suboid_buf_len);
882 
883 								proto_tree_add_oid(pt_name,k->hfid,tvb,name_offset, suboid_buf_len, suboid_buf);
884 
885 								key_start += suboid_len;
886 								key_len -= suboid_len + 1;
887 								continue; /* k->next */
888 							}
889 							default: {
890 								guint8* buf;
891 								guint buf_len;
892 								guint32* suboid;
893 								guint i;
894 
895 
896 								switch (k->key_type) {
897 									case OID_KEY_TYPE_IPADDR:
898 										suboid = &(subids[key_start]);
899 										buf_len = 4;
900 										break;
901 									case OID_KEY_TYPE_IMPLIED_STRING:
902 									case OID_KEY_TYPE_IMPLIED_BYTES:
903 									case OID_KEY_TYPE_ETHER:
904 										suboid = &(subids[key_start]);
905 										buf_len = key_len;
906 										break;
907 									default:
908 										buf_len = k->num_subids;
909 										suboid = &(subids[key_start]);
910 
911 										if(!buf_len) {
912 											buf_len = *suboid++;
913 											key_len--;
914 											key_start++;
915 										}
916 										break;
917 								}
918 
919 								if( key_len < buf_len ) {
920 									proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_index_string_too_long,tvb,0,0);
921 									oid_info_is_ok = FALSE;
922 									goto indexing_done;
923 								}
924 
925 								buf = (guint8*)wmem_alloc(actx->pinfo->pool, buf_len+1);
926 								for (i = 0; i < buf_len; i++)
927 									buf[i] = (guint8)suboid[i];
928 								buf[i] = '\0';
929 
930 								switch(k->key_type) {
931 									case OID_KEY_TYPE_STRING:
932 									case OID_KEY_TYPE_IMPLIED_STRING:
933 										proto_tree_add_string(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
934 										break;
935 									case OID_KEY_TYPE_BYTES:
936 									case OID_KEY_TYPE_NSAP:
937 									case OID_KEY_TYPE_IMPLIED_BYTES:
938 										proto_tree_add_bytes(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
939 										break;
940 									case OID_KEY_TYPE_ETHER:
941 										proto_tree_add_ether(pt_name,k->hfid,tvb,name_offset,buf_len, buf);
942 										break;
943 									case OID_KEY_TYPE_IPADDR: {
944 										guint32* ipv4_p = (guint32*)buf;
945 										proto_tree_add_ipv4(pt_name,k->hfid,tvb,name_offset,buf_len, *ipv4_p);
946 										}
947 										break;
948 									default:
949 										DISSECTOR_ASSERT_NOT_REACHED();
950 										break;
951 								}
952 
953 								key_start += buf_len;
954 								key_len -= buf_len;
955 								continue; /* k->next*/
956 							}
957 						}
958 					}
959 					goto indexing_done;
960 				} else {
961 					proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_unimplemented_instance_index,tvb,0,0);
962 					oid_info_is_ok = FALSE;
963 					goto indexing_done;
964 				}
965 			} else {
966 				proto_tree_add_expert(pt_name,actx->pinfo,&ei_snmp_column_parent_not_row,tvb,0,0);
967 				oid_info_is_ok = FALSE;
968 				goto indexing_done;
969 			}
970 		default: {
971 /*			proto_tree_add_expert (pt_name,actx->pinfo,PI_MALFORMED, PI_WARN,tvb,0,0,"This kind OID should have no value"); */
972 			oid_info_is_ok = FALSE;
973 			goto indexing_done;
974 		}
975 	}
976 indexing_done:
977 
978 	if (oid_info_is_ok && oid_info->value_type) {
979 		if (ber_class == BER_CLASS_UNI && tag == BER_UNI_TAG_NULL) {
980 			pi_value = proto_tree_add_item(pt_varbind,hf_snmp_unSpecified,tvb,value_offset,value_len,ENC_NA);
981 		} else {
982 			/* Provide a tree_item to attach errors to, if needed. */
983 			pi_value = pi_name;
984 
985 			if ((oid_info->value_type->ber_class != BER_CLASS_ANY) &&
986 				(ber_class != oid_info->value_type->ber_class))
987 				format_error = BER_WRONG_TAG;
988 			else if ((oid_info->value_type->ber_tag != BER_TAG_ANY) &&
989 				(tag != oid_info->value_type->ber_tag))
990 				format_error = BER_WRONG_TAG;
991 			else {
992 				max_len = oid_info->value_type->max_len == -1 ? 0xffffff : oid_info->value_type->max_len;
993 				min_len = oid_info->value_type->min_len;
994 
995 				if ((int)value_len < min_len || (int)value_len > max_len)
996 					format_error = BER_WRONG_LENGTH;
997 			}
998 
999 			if (format_error == BER_NO_ERROR)
1000 				pi_value = proto_tree_add_item(pt_varbind,oid_info->value_hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
1001 		}
1002 	} else {
1003 		switch(ber_class|(tag<<4)) {
1004 			case BER_CLASS_UNI|(BER_UNI_TAG_INTEGER<<4):
1005 			{
1006 				gint64 val=0;
1007 				unsigned int int_val_offset = value_offset;
1008 				unsigned int i;
1009 
1010 				max_len = 4; min_len = 1;
1011 				if (value_len > (guint)max_len || value_len < (guint)min_len) {
1012 					hfid = hf_snmp_integer32_value;
1013 					format_error = BER_WRONG_LENGTH;
1014 					break;
1015 				}
1016 
1017 				if(value_len > 0) {
1018 					/* extend sign bit */
1019 					if(tvb_get_guint8(tvb, int_val_offset)&0x80) {
1020 						val=-1;
1021 					}
1022 					for(i=0;i<value_len;i++) {
1023 						val=(val<<8)|tvb_get_guint8(tvb, int_val_offset);
1024 						int_val_offset++;
1025 					}
1026 				}
1027 				pi_value = proto_tree_add_int64(pt_varbind, hf_snmp_integer32_value, tvb,value_offset,value_len, val);
1028 
1029 				goto already_added;
1030 			}
1031 			case BER_CLASS_UNI|(BER_UNI_TAG_OCTETSTRING<<4):
1032 				if(oid_info->value_hfid> -1){
1033 					hfid = oid_info->value_hfid;
1034 				}else{
1035 					hfid = hf_snmp_octetstring_value;
1036 				}
1037 				break;
1038 			case BER_CLASS_UNI|(BER_UNI_TAG_OID<<4):
1039 				max_len = -1; min_len = 1;
1040 				if (value_len < (guint)min_len) format_error = BER_WRONG_LENGTH;
1041 				hfid = hf_snmp_oid_value;
1042 				break;
1043 			case BER_CLASS_UNI|(BER_UNI_TAG_NULL<<4):
1044 				max_len = 0; min_len = 0;
1045 				if (value_len != 0) format_error = BER_WRONG_LENGTH;
1046 				hfid = hf_snmp_null_value;
1047 				break;
1048 			case BER_CLASS_APP: /* | (SNMP_IPA<<4)*/
1049 				switch(value_len) {
1050 					case 4: hfid = hf_snmp_ipv4_value; break;
1051 					case 16: hfid = hf_snmp_ipv6_value; break;
1052 					default: hfid = hf_snmp_anyaddress_value; break;
1053 				}
1054 				break;
1055 			case BER_CLASS_APP|(SNMP_U32<<4):
1056 				hfid = hf_snmp_unsigned32_value;
1057 				break;
1058 			case BER_CLASS_APP|(SNMP_GGE<<4):
1059 				hfid = hf_snmp_gauge32_value;
1060 				break;
1061 			case BER_CLASS_APP|(SNMP_CNT<<4):
1062 				hfid = hf_snmp_counter_value;
1063 				break;
1064 			case BER_CLASS_APP|(SNMP_TIT<<4):
1065 				hfid = hf_snmp_timeticks_value;
1066 				break;
1067 			case BER_CLASS_APP|(SNMP_OPQ<<4):
1068 				hfid = hf_snmp_opaque_value;
1069 				break;
1070 			case BER_CLASS_APP|(SNMP_NSP<<4):
1071 				hfid = hf_snmp_nsap_value;
1072 				break;
1073 			case BER_CLASS_APP|(SNMP_C64<<4):
1074 				hfid = hf_snmp_big_counter_value;
1075 				break;
1076 			default:
1077 				hfid = hf_snmp_unknown_value;
1078 				break;
1079 		}
1080 		if (value_len > 8) {
1081 			/*
1082 			 * Too long for an FT_UINT64 or an FT_INT64.
1083 			 */
1084 			header_field_info *hfinfo = proto_registrar_get_nth(hfid);
1085 			if (hfinfo->type == FT_UINT64) {
1086 				/*
1087 				 * Check if this is an unsigned int64 with
1088 				 * a big value.
1089 				 */
1090 				if (value_len > 9 || tvb_get_guint8(tvb, value_offset) != 0) {
1091 					/* It is.  Fail. */
1092 					proto_tree_add_expert_format(pt_varbind,actx->pinfo,&ei_snmp_uint_too_large,tvb,value_offset,value_len,"Integral value too large");
1093 					goto already_added;
1094 				}
1095 				/* Cheat and skip the leading 0 byte */
1096 				value_len--;
1097 				value_offset++;
1098 			} else if (hfinfo->type == FT_INT64) {
1099 				/*
1100 				 * For now, just reject these.
1101 				 */
1102 				proto_tree_add_expert_format(pt_varbind,actx->pinfo,&ei_snmp_int_too_large,tvb,value_offset,value_len,"Integral value too large or too small");
1103 				goto already_added;
1104 			}
1105 		} else if (value_len == 0) {
1106 			/*
1107 			 * X.690 section 8.3.1 "Encoding of an integer value":
1108 			 * "The encoding of an integer value shall be
1109 			 * primitive. The contents octets shall consist of
1110 			 * one or more octets."
1111 			 *
1112 			 * Zero is not "one or more".
1113 			 */
1114 			header_field_info *hfinfo = proto_registrar_get_nth(hfid);
1115 			if (hfinfo->type == FT_UINT64 || hfinfo->type == FT_INT64) {
1116 				proto_tree_add_expert_format(pt_varbind,actx->pinfo,&ei_snmp_integral_value0,tvb,value_offset,value_len,"Integral value is zero-length");
1117 				goto already_added;
1118 			}
1119 		}
1120 		/* Special case DATE AND TIME */
1121 		if((oid_info->value_type)&&(oid_info->value_type->keytype == OID_KEY_TYPE_DATE_AND_TIME)&&(value_len > 7)){
1122 			pi_value = dissect_snmp_variable_date_and_time(pt_varbind, actx->pinfo, hfid, tvb, value_offset, value_len);
1123 		}else{
1124 			pi_value = proto_tree_add_item(pt_varbind,hfid,tvb,value_offset,value_len,ENC_BIG_ENDIAN);
1125 		}
1126 		if (format_error != BER_NO_ERROR) {
1127 			expert_add_info(actx->pinfo, pi_value, &ei_snmp_missing_mib);
1128 		}
1129 
1130 	}
1131 already_added:
1132 	pt_value = proto_item_add_subtree(pi_value,ett_value);
1133 
1134 	if (value_len > 0 && oid_string) {
1135 		tvbuff_t* sub_tvb = tvb_new_subset_length(tvb, value_offset, value_len);
1136 
1137 		next_tvb_add_string(var_list, sub_tvb, (snmp_var_in_tree) ? pt_value : NULL, value_sub_dissectors_table, oid_string);
1138 	}
1139 
1140 
1141 set_label:
1142 	if (pi_value) proto_item_fill_label(PITEM_FINFO(pi_value), label);
1143 
1144 	if (oid_info && oid_info->name) {
1145 		if (oid_left >= 1) {
1146 			repr = wmem_strdup_printf(actx->pinfo->pool, "%s.%s (%s)", oid_info->name,
1147 						oid_subid2string(actx->pinfo->pool, &(subids[oid_matched]),oid_left),
1148 						oid_subid2string(actx->pinfo->pool, subids,oid_matched+oid_left));
1149 			info_oid = wmem_strdup_printf(actx->pinfo->pool, "%s.%s", oid_info->name,
1150 						oid_subid2string(actx->pinfo->pool, &(subids[oid_matched]),oid_left));
1151 		} else {
1152 			repr = wmem_strdup_printf(actx->pinfo->pool, "%s (%s)", oid_info->name,
1153 						oid_subid2string(actx->pinfo->pool, subids,oid_matched));
1154 			info_oid = oid_info->name;
1155 		}
1156 	} else if (oid_string) {
1157 		repr = wmem_strdup(actx->pinfo->pool, oid_string);
1158 		info_oid = oid_string;
1159 	} else {
1160 		repr = wmem_strdup(actx->pinfo->pool, "[Bad OID]");
1161 	}
1162 
1163 	valstr = strstr(label,": ");
1164 	valstr = valstr ? valstr+2 : label;
1165 
1166 	proto_item_set_text(pi_varbind,"%s: %s",repr,valstr);
1167 
1168 	if (display_oid && info_oid) {
1169 		col_append_fstr (actx->pinfo->cinfo, COL_INFO, " %s", info_oid);
1170 	}
1171 
1172 	switch (format_error) {
1173 		case BER_WRONG_LENGTH: {
1174 			proto_item* pi;
1175 			proto_tree* p_tree = proto_item_add_subtree(pi_value,ett_decoding_error);
1176 			pt = proto_tree_add_subtree_format(p_tree,tvb,0,0,ett_decoding_error,&pi,
1177 							     "Wrong value length: %u  expecting: %u <= len <= %u",
1178 							     value_len, min_len, max_len == -1 ? 0xFFFFFF : max_len);
1179 			expert_add_info(actx->pinfo, pi, &ei_snmp_varbind_wrong_length_value);
1180 			return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
1181 		}
1182 		case BER_WRONG_TAG: {
1183 			proto_item* pi;
1184 			proto_tree* p_tree = proto_item_add_subtree(pi_value,ett_decoding_error);
1185 			pt = proto_tree_add_subtree_format(p_tree,tvb,0,0,ett_decoding_error,&pi,
1186 							     "Wrong class/tag for Value expected: %d,%d got: %d,%d",
1187 							     oid_info->value_type->ber_class, oid_info->value_type->ber_tag,
1188 							     ber_class, tag);
1189 			expert_add_info(actx->pinfo, pi, &ei_snmp_varbind_wrong_class_tag);
1190 			return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt);
1191 		}
1192 		default:
1193 			break;
1194 	}
1195 
1196 	return seq_offset + seq_len;
1197 }
1198 
1199 
1200 #define F_SNMP_ENGINEID_CONFORM 0x80
1201 #define SNMP_ENGINEID_RFC1910 0x00
1202 #define SNMP_ENGINEID_RFC3411 0x01
1203 
1204 static const true_false_string tfs_snmp_engineid_conform = {
1205 	"RFC3411 (SNMPv3)",
1206 	"RFC1910 (Non-SNMPv3)"
1207 };
1208 
1209 #define SNMP_ENGINEID_FORMAT_IPV4 0x01
1210 #define SNMP_ENGINEID_FORMAT_IPV6 0x02
1211 #define SNMP_ENGINEID_FORMAT_MACADDRESS 0x03
1212 #define SNMP_ENGINEID_FORMAT_TEXT 0x04
1213 #define SNMP_ENGINEID_FORMAT_OCTETS 0x05
1214 
1215 static const value_string snmp_engineid_format_vals[] = {
1216 	{ SNMP_ENGINEID_FORMAT_IPV4,	"IPv4 address" },
1217 	{ SNMP_ENGINEID_FORMAT_IPV6,	"IPv6 address" },
1218 	{ SNMP_ENGINEID_FORMAT_MACADDRESS,	"MAC address" },
1219 	{ SNMP_ENGINEID_FORMAT_TEXT,	"Text, administratively assigned" },
1220 	{ SNMP_ENGINEID_FORMAT_OCTETS,	"Octets, administratively assigned" },
1221 	{ 0,	NULL }
1222 };
1223 
1224 #define SNMP_ENGINEID_CISCO_AGENT 0x00
1225 #define SNMP_ENGINEID_CISCO_MANAGER 0x01
1226 
1227 static const value_string snmp_engineid_cisco_type_vals[] = {
1228 	{ SNMP_ENGINEID_CISCO_AGENT,	"Agent" },
1229 	{ SNMP_ENGINEID_CISCO_MANAGER,	"Manager" },
1230 	{ 0,	NULL }
1231 };
1232 
1233 /*
1234  * SNMP Engine ID dissection according to RFC 3411 (SnmpEngineID TC)
1235  * or historic RFC 1910 (AgentID)
1236  */
1237 int
dissect_snmp_engineid(proto_tree * tree,packet_info * pinfo,tvbuff_t * tvb,int offset,int len)1238 dissect_snmp_engineid(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int len)
1239 {
1240 	proto_item *item = NULL;
1241 	guint8 conformance, format;
1242 	guint32 enterpriseid;
1243 	time_t seconds;
1244 	nstime_t ts;
1245 	int len_remain = len;
1246 
1247 	/* first bit: engine id conformance */
1248 	if (len_remain<1) return offset;
1249 	conformance = ((tvb_get_guint8(tvb, offset)>>7) & 0x01);
1250 	proto_tree_add_item(tree, hf_snmp_engineid_conform, tvb, offset, 1, ENC_BIG_ENDIAN);
1251 
1252 	/* 4-byte enterprise number/name */
1253 	if (len_remain<4) return offset;
1254 	enterpriseid = tvb_get_ntohl(tvb, offset);
1255 	if (conformance)
1256 		enterpriseid -= 0x80000000; /* ignore first bit */
1257 	proto_tree_add_uint(tree, hf_snmp_engineid_enterprise, tvb, offset, 4, enterpriseid);
1258 	offset+=4;
1259 	len_remain-=4;
1260 
1261 	switch(conformance) {
1262 
1263 	case SNMP_ENGINEID_RFC1910:
1264 		/* 12-byte AgentID w/ 8-byte trailer */
1265 		if (len_remain==8) {
1266 			proto_tree_add_item(tree, hf_snmp_agentid_trailer, tvb, offset, 8, ENC_NA);
1267 			offset+=8;
1268 			len_remain-=8;
1269 		} else {
1270 			proto_tree_add_expert(tree, pinfo, &ei_snmp_rfc1910_non_conformant, tvb, offset, len_remain);
1271 			return offset;
1272 		}
1273 		break;
1274 
1275 	case SNMP_ENGINEID_RFC3411: /* variable length: 5..32 */
1276 
1277 		/* 1-byte format specifier */
1278 		if (len_remain<1) return offset;
1279 		format = tvb_get_guint8(tvb, offset);
1280 		item = proto_tree_add_uint_format(tree, hf_snmp_engineid_format, tvb, offset, 1, format, "Engine ID Format: %s (%d)",
1281 						  val_to_str(format, snmp_engineid_format_vals, "Reserved/Enterprise-specific"), format);
1282 		offset+=1;
1283 		len_remain-=1;
1284 
1285 		switch(format) {
1286 		case SNMP_ENGINEID_FORMAT_IPV4:
1287 			/* 4-byte IPv4 address */
1288 			if (len_remain==4) {
1289 				proto_tree_add_item(tree, hf_snmp_engineid_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
1290 				offset+=4;
1291 				len_remain=0;
1292 			}
1293 			break;
1294 		case SNMP_ENGINEID_FORMAT_IPV6:
1295 			/* 16-byte IPv6 address */
1296 			if (len_remain==16) {
1297 				proto_tree_add_item(tree, hf_snmp_engineid_ipv6, tvb, offset, 16, ENC_NA);
1298 				offset+=16;
1299 				len_remain=0;
1300 			}
1301 			break;
1302 		case SNMP_ENGINEID_FORMAT_MACADDRESS:
1303 			/* See: https://supportforums.cisco.com/message/3010617#3010617 for details. */
1304 			if ((enterpriseid==9)&&(len_remain==7)) {
1305 				proto_tree_add_item(tree, hf_snmp_engineid_cisco_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1306 				offset++;
1307 				len_remain--;
1308 			}
1309 			/* 6-byte MAC address */
1310 			if (len_remain==6) {
1311 				proto_tree_add_item(tree, hf_snmp_engineid_mac, tvb, offset, 6, ENC_NA);
1312 				offset+=6;
1313 				len_remain=0;
1314 			}
1315 			break;
1316 		case SNMP_ENGINEID_FORMAT_TEXT:
1317 			/* max. 27-byte string, administratively assigned */
1318 			if (len_remain<=27) {
1319 				proto_tree_add_item(tree, hf_snmp_engineid_text, tvb, offset, len_remain, ENC_ASCII|ENC_NA);
1320 				offset+=len_remain;
1321 				len_remain=0;
1322 			}
1323 			break;
1324 		case 128:
1325 			/* most common enterprise-specific format: (ucd|net)-snmp random */
1326 			if ((enterpriseid==2021)||(enterpriseid==8072)) {
1327 				proto_item_append_text(item, (enterpriseid==2021) ? ": UCD-SNMP Random" : ": Net-SNMP Random");
1328 				/* demystify: 4B random, 4B/8B epoch seconds */
1329 				if ((len_remain==8) || (len_remain==12)) {
1330 					proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, 4, ENC_NA);
1331 					if (len_remain==8) {
1332 						seconds = (time_t)tvb_get_letohl(tvb, offset + 4);
1333 					} else {
1334 						seconds = (time_t)tvb_get_letohi64(tvb, offset + 4);
1335 					}
1336 					ts.secs = seconds;
1337 					ts.nsecs = 0;
1338 					proto_tree_add_time_format_value(tree, hf_snmp_engineid_time, tvb, offset + 4, len_remain - 4,
1339 									 &ts, "%s",
1340 									 abs_time_secs_to_str(pinfo->pool, seconds, ABSOLUTE_TIME_LOCAL, TRUE));
1341 					offset+=len_remain;
1342 					len_remain=0;
1343 				}
1344 			break;
1345 			}
1346 		/* fall through */
1347 		case SNMP_ENGINEID_FORMAT_OCTETS:
1348 		default:
1349 			/* max. 27 bytes, administratively assigned or unknown format */
1350 			if (len_remain<=27) {
1351 				proto_tree_add_item(tree, hf_snmp_engineid_data, tvb, offset, len_remain, ENC_NA);
1352 				offset+=len_remain;
1353 				len_remain=0;
1354 			}
1355 		break;
1356 		}
1357 	}
1358 
1359 	if (len_remain>0) {
1360 		proto_tree_add_expert(tree, pinfo, &ei_snmp_rfc3411_non_conformant, tvb, offset, len_remain);
1361 		offset+=len_remain;
1362 	}
1363 	return offset;
1364 }
1365 
1366 
set_ue_keys(snmp_ue_assoc_t * n)1367 static void set_ue_keys(snmp_ue_assoc_t* n ) {
1368 	guint key_size = auth_hash_len[n->user.authModel];
1369 
1370 	n->user.authKey.data = (guint8 *)g_malloc(key_size);
1371 	n->user.authKey.len = key_size;
1372 	snmp_usm_password_to_key(n->user.authModel,
1373 				 n->user.authPassword.data,
1374 				 n->user.authPassword.len,
1375 				 n->engine.data,
1376 				 n->engine.len,
1377 				 n->user.authKey.data);
1378 
1379 	if (n->priv_proto == PRIV_AES128 || n->priv_proto == PRIV_AES192 || n->priv_proto == PRIV_AES256) {
1380 		guint need_key_len =
1381 			(n->priv_proto == PRIV_AES128) ? 16 :
1382 			(n->priv_proto == PRIV_AES192) ? 24 :
1383 			(n->priv_proto == PRIV_AES256) ? 32 :
1384 			0;
1385 
1386 		guint key_len = key_size;
1387 
1388 		while (key_len < need_key_len)
1389 			key_len += key_size;
1390 
1391 		n->user.privKey.data = (guint8 *)g_malloc(key_len);
1392 		n->user.privKey.len  = need_key_len;
1393 
1394 		snmp_usm_password_to_key(n->user.authModel,
1395 					 n->user.privPassword.data,
1396 					 n->user.privPassword.len,
1397 					 n->engine.data,
1398 					 n->engine.len,
1399 					 n->user.privKey.data);
1400 
1401 		key_len = key_size;
1402 
1403 		/* extend key if needed */
1404 		while (key_len < need_key_len) {
1405 			snmp_usm_password_to_key(n->user.authModel,
1406 						 n->user.privKey.data,
1407 						 key_len,
1408 						 n->engine.data,
1409 						 n->engine.len,
1410 						 n->user.privKey.data + key_len);
1411 
1412 			key_len += key_size;
1413 		}
1414 
1415 	} else {
1416 		n->user.privKey.data = (guint8 *)g_malloc(key_size);
1417 		n->user.privKey.len = key_size;
1418 		snmp_usm_password_to_key(n->user.authModel,
1419 					 n->user.privPassword.data,
1420 					 n->user.privPassword.len,
1421 					 n->engine.data,
1422 					 n->engine.len,
1423 					 n->user.privKey.data);
1424 	}
1425 }
1426 
1427 static snmp_ue_assoc_t*
ue_dup(snmp_ue_assoc_t * o)1428 ue_dup(snmp_ue_assoc_t* o)
1429 {
1430 	snmp_ue_assoc_t* d = (snmp_ue_assoc_t*)g_memdup2(o,sizeof(snmp_ue_assoc_t));
1431 
1432 	d->user.authModel = o->user.authModel;
1433 
1434 	d->user.privProtocol = o->user.privProtocol;
1435 
1436 	d->user.userName.data = (guint8 *)g_memdup2(o->user.userName.data,o->user.userName.len);
1437 	d->user.userName.len = o->user.userName.len;
1438 
1439 	d->user.authPassword.data = o->user.authPassword.data ? (guint8 *)g_memdup2(o->user.authPassword.data,o->user.authPassword.len) : NULL;
1440 	d->user.authPassword.len = o->user.authPassword.len;
1441 
1442 	d->user.privPassword.data = o->user.privPassword.data ? (guint8 *)g_memdup2(o->user.privPassword.data,o->user.privPassword.len) : NULL;
1443 	d->user.privPassword.len = o->user.privPassword.len;
1444 
1445 	d->engine.len = o->engine.len;
1446 
1447 	if (d->engine.len) {
1448 		d->engine.data = (guint8 *)g_memdup2(o->engine.data,o->engine.len);
1449 		set_ue_keys(d);
1450 	}
1451 
1452 	return d;
1453 
1454 }
1455 
1456 static void*
snmp_users_copy_cb(void * dest,const void * orig,size_t len _U_)1457 snmp_users_copy_cb(void* dest, const void* orig, size_t len _U_)
1458 {
1459 	const snmp_ue_assoc_t* o = (const snmp_ue_assoc_t*)orig;
1460 	snmp_ue_assoc_t* d = (snmp_ue_assoc_t*)dest;
1461 
1462 	d->auth_model = o->auth_model;
1463 	d->user.authModel = (snmp_usm_auth_model_t) o->auth_model;
1464 
1465 	d->priv_proto = o->priv_proto;
1466 	d->user.privProtocol = priv_protos[o->priv_proto];
1467 
1468 	d->user.userName.data = (guint8*)g_memdup2(o->user.userName.data,o->user.userName.len);
1469 	d->user.userName.len = o->user.userName.len;
1470 
1471 	d->user.authPassword.data = o->user.authPassword.data ? (guint8*)g_memdup2(o->user.authPassword.data,o->user.authPassword.len) : NULL;
1472 	d->user.authPassword.len = o->user.authPassword.len;
1473 
1474 	d->user.privPassword.data = o->user.privPassword.data ? (guint8*)g_memdup2(o->user.privPassword.data,o->user.privPassword.len) : NULL;
1475 	d->user.privPassword.len = o->user.privPassword.len;
1476 
1477 	d->engine.len = o->engine.len;
1478 	if (o->engine.data) {
1479 		d->engine.data = (guint8*)g_memdup2(o->engine.data,o->engine.len);
1480 	}
1481 
1482 	d->user.authKey.data = o->user.authKey.data ? (guint8*)g_memdup2(o->user.authKey.data,o->user.authKey.len) : NULL;
1483 	d->user.authKey.len = o->user.authKey.len;
1484 
1485 	d->user.privKey.data = o->user.privKey.data ? (guint8*)g_memdup2(o->user.privKey.data,o->user.privKey.len) : NULL;
1486 	d->user.privKey.len = o->user.privKey.len;
1487 
1488 	return d;
1489 }
1490 
1491 static void
snmp_users_free_cb(void * p)1492 snmp_users_free_cb(void* p)
1493 {
1494 	snmp_ue_assoc_t* ue = (snmp_ue_assoc_t*)p;
1495 	g_free(ue->user.userName.data);
1496 	g_free(ue->user.authPassword.data);
1497 	g_free(ue->user.privPassword.data);
1498 	g_free(ue->user.authKey.data);
1499 	g_free(ue->user.privKey.data);
1500 	g_free(ue->engine.data);
1501 }
1502 
1503 static gboolean
snmp_users_update_cb(void * p _U_,char ** err)1504 snmp_users_update_cb(void* p _U_, char** err)
1505 {
1506 	snmp_ue_assoc_t* ue = (snmp_ue_assoc_t*)p;
1507 	GString* es = g_string_new("");
1508 	unsigned int i;
1509 
1510 	*err = NULL;
1511 
1512 	if (! ue->user.userName.len) {
1513 		g_string_append_printf(es,"no userName\n");
1514 	} else if ((ue->engine.len > 0) && (ue->engine.len < 5 || ue->engine.len > 32)) {
1515 		/* RFC 3411 section 5 */
1516 		g_string_append_printf(es, "Invalid engineId length (%u). Must be between 5 and 32 (10 and 64 hex digits)\n", ue->engine.len);
1517 	} else if (num_ueas) {
1518 		for (i=0; i<num_ueas-1; i++) {
1519 			snmp_ue_assoc_t* u = &(ueas[i]);
1520 
1521 			if ( u->user.userName.len == ue->user.userName.len
1522 				&& u->engine.len == ue->engine.len && (u != ue)) {
1523 
1524 				if (u->engine.len > 0 && memcmp( u->engine.data, ue->engine.data, u->engine.len ) == 0) {
1525 					if ( memcmp( u->user.userName.data, ue->user.userName.data, ue->user.userName.len ) == 0 ) {
1526 						/* XXX: make a string for the engineId */
1527 						g_string_append_printf(es,"Duplicate key (userName='%s')\n",ue->user.userName.data);
1528 						break;
1529 					}
1530 				}
1531 
1532 				if (u->engine.len == 0) {
1533 					if ( memcmp( u->user.userName.data, ue->user.userName.data, ue->user.userName.len ) == 0 ) {
1534 						g_string_append_printf(es,"Duplicate key (userName='%s' engineId=NONE)\n",ue->user.userName.data);
1535 						break;
1536 					}
1537 				}
1538 			}
1539 		}
1540 	}
1541 
1542 	if (es->len) {
1543 		es = g_string_truncate(es,es->len-1);
1544 		*err = g_string_free(es, FALSE);
1545 		return FALSE;
1546 	}
1547 
1548 	return TRUE;
1549 }
1550 
1551 static void
free_ue_cache(snmp_ue_assoc_t ** cache)1552 free_ue_cache(snmp_ue_assoc_t **cache)
1553 {
1554 	static snmp_ue_assoc_t *a, *nxt;
1555 
1556 	for (a = *cache; a; a = nxt) {
1557 		nxt = a->next;
1558 		snmp_users_free_cb(a);
1559 		g_free(a);
1560 	}
1561 
1562 	*cache = NULL;
1563 }
1564 
1565 #define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
1566 
1567 static void
init_ue_cache(void)1568 init_ue_cache(void)
1569 {
1570 	guint i;
1571 
1572 	for (i = 0; i < num_ueas; i++) {
1573 		snmp_ue_assoc_t* a = ue_dup(&(ueas[i]));
1574 
1575 		if (a->engine.len) {
1576 			CACHE_INSERT(localized_ues,a);
1577 
1578 		} else {
1579 			CACHE_INSERT(unlocalized_ues,a);
1580 		}
1581 
1582 	}
1583 }
1584 
1585 static void
cleanup_ue_cache(void)1586 cleanup_ue_cache(void)
1587 {
1588 	free_ue_cache(&localized_ues);
1589 	free_ue_cache(&unlocalized_ues);
1590 }
1591 
1592 /* Called when the user applies changes to UAT preferences. */
1593 static void
renew_ue_cache(void)1594 renew_ue_cache(void)
1595 {
1596 	cleanup_ue_cache();
1597 	init_ue_cache();
1598 }
1599 
1600 
1601 static snmp_ue_assoc_t*
localize_ue(snmp_ue_assoc_t * o,const guint8 * engine,guint engine_len)1602 localize_ue( snmp_ue_assoc_t* o, const guint8* engine, guint engine_len )
1603 {
1604 	snmp_ue_assoc_t* n = (snmp_ue_assoc_t*)g_memdup2(o,sizeof(snmp_ue_assoc_t));
1605 
1606 	n->user.userName.data = (guint8*)g_memdup2(o->user.userName.data,o->user.userName.len);
1607 	n->user.authModel = o->user.authModel;
1608 	n->user.authPassword.data = (guint8*)g_memdup2(o->user.authPassword.data,o->user.authPassword.len);
1609 	n->user.authPassword.len = o->user.authPassword.len;
1610 	n->user.privPassword.data = (guint8*)g_memdup2(o->user.privPassword.data,o->user.privPassword.len);
1611 	n->user.privPassword.len = o->user.privPassword.len;
1612 	n->user.authKey.data = (guint8*)g_memdup2(o->user.authKey.data,o->user.authKey.len);
1613 	n->user.privKey.data = (guint8*)g_memdup2(o->user.privKey.data,o->user.privKey.len);
1614 	n->engine.data = (guint8*)g_memdup2(engine,engine_len);
1615 	n->engine.len = engine_len;
1616 	n->priv_proto = o->priv_proto;
1617 
1618 	set_ue_keys(n);
1619 
1620 	return n;
1621 }
1622 
1623 
1624 #define localized_match(a,u,ul,e,el) \
1625 	( a->user.userName.len == ul \
1626 	&& a->engine.len == el \
1627 	&& memcmp( a->user.userName.data, u, ul ) == 0 \
1628 	&& memcmp( a->engine.data,   e,  el ) == 0 )
1629 
1630 #define unlocalized_match(a,u,l) \
1631 	( a->user.userName.len == l && memcmp( a->user.userName.data, u, l) == 0 )
1632 
1633 static snmp_ue_assoc_t*
get_user_assoc(tvbuff_t * engine_tvb,tvbuff_t * user_tvb,packet_info * pinfo)1634 get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb, packet_info *pinfo)
1635 {
1636 	static snmp_ue_assoc_t* a;
1637 	guint given_username_len;
1638 	guint8* given_username;
1639 	guint given_engine_len = 0;
1640 	guint8* given_engine = NULL;
1641 
1642 	if ( ! (localized_ues || unlocalized_ues ) ) return NULL;
1643 
1644 	if (! ( user_tvb && engine_tvb ) ) return NULL;
1645 
1646 	given_username_len = tvb_captured_length(user_tvb);
1647 	given_engine_len = tvb_captured_length(engine_tvb);
1648 	if (! ( given_engine_len && given_username_len ) ) return NULL;
1649 	given_username = (guint8*)tvb_memdup(pinfo->pool,user_tvb,0,-1);
1650 	given_engine = (guint8*)tvb_memdup(pinfo->pool,engine_tvb,0,-1);
1651 
1652 	for (a = localized_ues; a; a = a->next) {
1653 		if ( localized_match(a, given_username, given_username_len, given_engine, given_engine_len) ) {
1654 			return a;
1655 		}
1656 	}
1657 
1658 	for (a = unlocalized_ues; a; a = a->next) {
1659 		if ( unlocalized_match(a, given_username, given_username_len) ) {
1660 			snmp_ue_assoc_t* n = localize_ue( a, given_engine, given_engine_len );
1661 			CACHE_INSERT(localized_ues,n);
1662 			return n;
1663 		}
1664 	}
1665 
1666 	return NULL;
1667 }
1668 
1669 static gboolean
snmp_usm_auth(const packet_info * pinfo,const snmp_usm_auth_model_t model,snmp_usm_params_t * p,guint8 ** calc_auth_p,guint * calc_auth_len_p,gchar const ** error)1670 snmp_usm_auth(const packet_info *pinfo, const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8** calc_auth_p,
1671 	guint* calc_auth_len_p, gchar const** error)
1672 {
1673 	gint msg_len;
1674 	guint8* msg;
1675 	guint auth_len;
1676 	guint8* auth;
1677 	guint8* key;
1678 	guint key_len;
1679 	guint8 *calc_auth;
1680 	guint start;
1681 	guint end;
1682 	guint i;
1683 
1684 	if (!p->auth_tvb) {
1685 		*error = "No Authenticator";
1686 		return FALSE;
1687 	}
1688 
1689 	key = p->user_assoc->user.authKey.data;
1690 	key_len = p->user_assoc->user.authKey.len;
1691 
1692 	if (! key ) {
1693 		*error = "User has no authKey";
1694 		return FALSE;
1695 	}
1696 
1697 	auth_len = tvb_captured_length(p->auth_tvb);
1698 
1699 	if (auth_len != auth_tag_len[model]) {
1700 		*error = "Authenticator length wrong";
1701 		return FALSE;
1702 	}
1703 
1704 	msg_len = tvb_captured_length(p->msg_tvb);
1705 	if (msg_len <= 0) {
1706 		*error = "Not enough data remaining";
1707 		return FALSE;
1708 	}
1709 	msg = (guint8*)tvb_memdup(pinfo->pool,p->msg_tvb,0,msg_len);
1710 
1711 	auth = (guint8*)tvb_memdup(pinfo->pool,p->auth_tvb,0,auth_len);
1712 
1713 	start = p->auth_offset - p->start_offset;
1714 	end =   start + auth_len;
1715 
1716 	/* fill the authenticator with zeros */
1717 	for ( i = start ; i < end ; i++ ) {
1718 		msg[i] = '\0';
1719 	}
1720 
1721 	calc_auth = (guint8*)wmem_alloc(pinfo->pool, auth_hash_len[model]);
1722 
1723 	if (ws_hmac_buffer(auth_hash_algo[model], calc_auth, msg, msg_len, key, key_len)) {
1724 		return FALSE;
1725 	}
1726 
1727 	if (calc_auth_p) *calc_auth_p = calc_auth;
1728 	if (calc_auth_len_p) *calc_auth_len_p = auth_len;
1729 
1730 	return ( memcmp(auth,calc_auth,auth_len) != 0 ) ? FALSE : TRUE;
1731 }
1732 
1733 static tvbuff_t*
snmp_usm_priv_des(snmp_usm_params_t * p,tvbuff_t * encryptedData,packet_info * pinfo,gchar const ** error)1734 snmp_usm_priv_des(snmp_usm_params_t* p, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error)
1735 {
1736 	gcry_error_t err;
1737 	gcry_cipher_hd_t hd = NULL;
1738 
1739 	guint8* cleartext;
1740 	guint8* des_key = p->user_assoc->user.privKey.data; /* first 8 bytes */
1741 	guint8* pre_iv = &(p->user_assoc->user.privKey.data[8]); /* last 8 bytes */
1742 	guint8* salt;
1743 	gint salt_len;
1744 	gint cryptgrm_len;
1745 	guint8* cryptgrm;
1746 	tvbuff_t* clear_tvb;
1747 	guint8 iv[8];
1748 	guint i;
1749 
1750 
1751 	salt_len = tvb_captured_length(p->priv_tvb);
1752 
1753 	if (salt_len != 8) {
1754 		*error = "decryptionError: msgPrivacyParameters length != 8";
1755 		return NULL;
1756 	}
1757 
1758 	salt = (guint8*)tvb_memdup(pinfo->pool,p->priv_tvb,0,salt_len);
1759 
1760 	/*
1761 	 The resulting "salt" is XOR-ed with the pre-IV to obtain the IV.
1762 	 */
1763 	for (i=0; i<8; i++) {
1764 		iv[i] = pre_iv[i] ^ salt[i];
1765 	}
1766 
1767 	cryptgrm_len = tvb_captured_length(encryptedData);
1768 
1769 	if ((cryptgrm_len <= 0) || (cryptgrm_len % 8)) {
1770 		*error = "decryptionError: the length of the encrypted data is not a multiple of 8 octets";
1771 		return NULL;
1772 	}
1773 
1774 	cryptgrm = (guint8*)tvb_memdup(pinfo->pool,encryptedData,0,-1);
1775 
1776 	cleartext = (guint8*)wmem_alloc(pinfo->pool, cryptgrm_len);
1777 
1778 	err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0);
1779 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1780 
1781 	err = gcry_cipher_setiv(hd, iv, 8);
1782 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1783 
1784 	err = gcry_cipher_setkey(hd,des_key,8);
1785 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1786 
1787 	err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
1788 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1789 
1790 	gcry_cipher_close(hd);
1791 
1792 	clear_tvb = tvb_new_child_real_data(encryptedData, cleartext, cryptgrm_len, cryptgrm_len);
1793 
1794 	return clear_tvb;
1795 
1796 on_gcry_error:
1797 	*error = (const gchar *)gcry_strerror(err);
1798 	if (hd) gcry_cipher_close(hd);
1799 	return NULL;
1800 }
1801 
1802 static tvbuff_t*
snmp_usm_priv_aes_common(snmp_usm_params_t * p,tvbuff_t * encryptedData,packet_info * pinfo,gchar const ** error,int algo)1803 snmp_usm_priv_aes_common(snmp_usm_params_t* p, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error, int algo)
1804 {
1805 	gcry_error_t err;
1806 	gcry_cipher_hd_t hd = NULL;
1807 
1808 	guint8* cleartext;
1809 	guint8* aes_key = p->user_assoc->user.privKey.data;
1810 	int aes_key_len = p->user_assoc->user.privKey.len;
1811 	guint8 iv[16];
1812 	gint priv_len;
1813 	gint cryptgrm_len;
1814 	guint8* cryptgrm;
1815 	tvbuff_t* clear_tvb;
1816 
1817 	priv_len = tvb_captured_length(p->priv_tvb);
1818 
1819 	if (priv_len != 8) {
1820 		*error = "decryptionError: msgPrivacyParameters length != 8";
1821 		return NULL;
1822 	}
1823 
1824 	iv[0] = (p->boots & 0xff000000) >> 24;
1825 	iv[1] = (p->boots & 0x00ff0000) >> 16;
1826 	iv[2] = (p->boots & 0x0000ff00) >> 8;
1827 	iv[3] = (p->boots & 0x000000ff);
1828 	iv[4] = (p->snmp_time & 0xff000000) >> 24;
1829 	iv[5] = (p->snmp_time & 0x00ff0000) >> 16;
1830 	iv[6] = (p->snmp_time & 0x0000ff00) >> 8;
1831 	iv[7] = (p->snmp_time & 0x000000ff);
1832 	tvb_memcpy(p->priv_tvb,&(iv[8]),0,8);
1833 
1834 	cryptgrm_len = tvb_captured_length(encryptedData);
1835 	if (cryptgrm_len <= 0) {
1836 		*error = "Not enough data remaining";
1837 		return NULL;
1838 	}
1839 	cryptgrm = (guint8*)tvb_memdup(pinfo->pool,encryptedData,0,-1);
1840 
1841 	cleartext = (guint8*)wmem_alloc(pinfo->pool, cryptgrm_len);
1842 
1843 	err = gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CFB, 0);
1844 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1845 
1846 	err = gcry_cipher_setiv(hd, iv, 16);
1847 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1848 
1849 	err = gcry_cipher_setkey(hd,aes_key,aes_key_len);
1850 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1851 
1852 	err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
1853 	if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
1854 
1855 	gcry_cipher_close(hd);
1856 
1857 	clear_tvb = tvb_new_child_real_data(encryptedData, cleartext, cryptgrm_len, cryptgrm_len);
1858 
1859 	return clear_tvb;
1860 
1861 on_gcry_error:
1862 	*error = (const gchar *)gcry_strerror(err);
1863 	if (hd) gcry_cipher_close(hd);
1864 	return NULL;
1865 }
1866 
1867 static tvbuff_t*
snmp_usm_priv_aes128(snmp_usm_params_t * p,tvbuff_t * encryptedData,packet_info * pinfo,gchar const ** error)1868 snmp_usm_priv_aes128(snmp_usm_params_t* p, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error)
1869 {
1870 	return snmp_usm_priv_aes_common(p, encryptedData, pinfo, error, GCRY_CIPHER_AES);
1871 }
1872 
1873 static tvbuff_t*
snmp_usm_priv_aes192(snmp_usm_params_t * p,tvbuff_t * encryptedData,packet_info * pinfo,gchar const ** error)1874 snmp_usm_priv_aes192(snmp_usm_params_t* p, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error)
1875 {
1876 	return snmp_usm_priv_aes_common(p, encryptedData, pinfo, error, GCRY_CIPHER_AES192);
1877 }
1878 
1879 static tvbuff_t*
snmp_usm_priv_aes256(snmp_usm_params_t * p,tvbuff_t * encryptedData,packet_info * pinfo,gchar const ** error)1880 snmp_usm_priv_aes256(snmp_usm_params_t* p, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error)
1881 {
1882 	return snmp_usm_priv_aes_common(p, encryptedData, pinfo, error, GCRY_CIPHER_AES256);
1883 }
1884 
1885 static gboolean
check_ScopedPdu(tvbuff_t * tvb)1886 check_ScopedPdu(tvbuff_t* tvb)
1887 {
1888 	int offset;
1889 	gint8 ber_class;
1890 	gboolean pc;
1891 	gint32 tag;
1892 	int hoffset, eoffset;
1893 	guint32 len;
1894 
1895 	offset = get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
1896 	offset = get_ber_length(tvb, offset, NULL, NULL);
1897 
1898 	if ( ! (((ber_class!=BER_CLASS_APP) && (ber_class!=BER_CLASS_PRI) )
1899 			&& ( (!pc) || (ber_class!=BER_CLASS_UNI) || (tag!=BER_UNI_TAG_ENUMERATED) )
1900 			)) return FALSE;
1901 
1902 	if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0))
1903 		return TRUE;
1904 
1905 	hoffset = offset;
1906 
1907 	offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
1908 	offset = get_ber_length(tvb, offset, &len, NULL);
1909 	eoffset = offset + len;
1910 
1911 	if (eoffset <= hoffset) return FALSE;
1912 
1913 	if ((ber_class!=BER_CLASS_APP)&&(ber_class!=BER_CLASS_PRI))
1914 		if( (ber_class!=BER_CLASS_UNI)
1915 			||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) )
1916 			return FALSE;
1917 
1918 	return TRUE;
1919 
1920 }
1921 
1922 #include "packet-snmp-fn.c"
1923 
1924 static snmp_conv_info_t*
snmp_find_conversation_and_get_conv_data(packet_info * pinfo)1925 snmp_find_conversation_and_get_conv_data(packet_info *pinfo) {
1926 
1927 	conversation_t *conversation;
1928 	snmp_conv_info_t *snmp_info = NULL;
1929 
1930 	conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1931 		pinfo->srcport, pinfo->destport, 0);
1932 
1933 	if( (conversation == NULL) || (conversation_get_dissector(conversation, pinfo->num)!=snmp_handle) ) {
1934 		conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1935 			pinfo->srcport, pinfo->destport, 0);
1936 		conversation_set_dissector(conversation, snmp_handle);
1937 	}
1938 
1939 	snmp_info = (snmp_conv_info_t *)conversation_get_proto_data(conversation, proto_snmp);
1940 	if (snmp_info == NULL) {
1941 		snmp_info = wmem_new0(wmem_file_scope(), snmp_conv_info_t);
1942 		snmp_info->request_response=wmem_map_new(wmem_file_scope(), g_int_hash, g_int_equal);
1943 
1944 		conversation_add_proto_data(conversation, proto_snmp, snmp_info);
1945 	}
1946 	return snmp_info;
1947 }
1948 
1949 guint
dissect_snmp_pdu(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,int proto,gint ett,gboolean is_tcp)1950 dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1951 		 proto_tree *tree, int proto, gint ett, gboolean is_tcp)
1952 {
1953 
1954 	guint length_remaining;
1955 	gint8 ber_class;
1956 	gboolean pc, ind = 0;
1957 	gint32 tag;
1958 	guint32 len;
1959 	guint message_length;
1960 	int start_offset = offset;
1961 	guint32 version = 0;
1962 	tvbuff_t	*next_tvb;
1963 
1964 	proto_tree *snmp_tree = NULL;
1965 	proto_item *item = NULL;
1966 
1967 	snmp_conv_info_t *snmp_info = snmp_find_conversation_and_get_conv_data(pinfo);
1968 
1969 	asn1_ctx_t asn1_ctx;
1970 	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1971 
1972 	asn1_ctx.private_data = snmp_info;
1973 
1974 	usm_p.msg_tvb = tvb;
1975 	usm_p.start_offset = tvb_offset_from_real_beginning(tvb);
1976 	usm_p.engine_tvb = NULL;
1977 	usm_p.user_tvb = NULL;
1978 	usm_p.auth_item = NULL;
1979 	usm_p.auth_tvb = NULL;
1980 	usm_p.auth_offset = 0;
1981 	usm_p.priv_tvb = NULL;
1982 	usm_p.user_assoc = NULL;
1983 	usm_p.authenticated = FALSE;
1984 	usm_p.encrypted = FALSE;
1985 	usm_p.boots = 0;
1986 	usm_p.snmp_time = 0;
1987 	usm_p.authOK = FALSE;
1988 
1989 	/*
1990 	 * This will throw an exception if we don't have any data left.
1991 	 * That's what we want.  (See "tcp_dissect_pdus()", which is
1992 	 * similar, but doesn't have to deal with ASN.1.
1993 	 * XXX - can we make "tcp_dissect_pdus()" provide enough
1994 	 * information to the "get_pdu_len" routine so that we could
1995 	 * have that routine deal with ASN.1, and just use
1996 	 * "tcp_dissect_pdus()"?)
1997 	 */
1998 	length_remaining = tvb_ensure_captured_length_remaining(tvb, offset);
1999 
2000 	/* NOTE: we have to parse the message piece by piece, since the
2001 	 * capture length may be less than the message length: a 'global'
2002 	 * parsing is likely to fail.
2003 	 */
2004 
2005 	/*
2006 	 * If this is SNMP-over-TCP, we might have to do reassembly
2007 	 * in order to read the "Sequence Of" header.
2008 	 */
2009 	if (is_tcp && snmp_desegment && pinfo->can_desegment) {
2010 		/*
2011 		 * This is TCP, and we should, and can, do reassembly.
2012 		 *
2013 		 * Is the "Sequence Of" header split across segment
2014 		 * boundaries?  We require at least 6 bytes for the
2015 		 * header, which allows for a 4-byte length (ASN.1
2016 		 * BER).
2017 		 */
2018 		if (length_remaining < 6) {
2019 			/*
2020 			 * Yes.  Tell the TCP dissector where the data
2021 			 * for this message starts in the data it handed
2022 			 * us and that we need "some more data."  Don't tell
2023 			 * it exactly how many bytes we need because if/when
2024 			 * we ask for even more (after the header) that will
2025 			 * break reassembly.
2026 			 */
2027 			pinfo->desegment_offset = offset;
2028 			pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2029 			return -1;
2030 		}
2031 	}
2032 
2033 	/*
2034 	 * OK, try to read the "Sequence Of" header; this gets the total
2035 	 * length of the SNMP message.
2036 	 */
2037 	offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2038 	/*Get the total octet length of the SNMP data*/
2039 	offset = get_ber_length(tvb, offset, &len, &ind);
2040 	message_length = len + offset;
2041 
2042 	/*Get the SNMP version data*/
2043 	/*offset =*/ dissect_ber_integer(FALSE, &asn1_ctx, 0, tvb, offset, -1, &version);
2044 
2045 
2046 	/*
2047 	 * If this is SNMP-over-TCP, we might have to do reassembly
2048 	 * to get all of this message.
2049 	 */
2050 	if (is_tcp && snmp_desegment && pinfo->can_desegment) {
2051 		/*
2052 		 * Yes - is the message split across segment boundaries?
2053 		 */
2054 		if (length_remaining < message_length) {
2055 			/*
2056 			 * Yes.  Tell the TCP dissector where the data
2057 			 * for this message starts in the data it handed
2058 			 * us, and how many more bytes we need, and
2059 			 * return.
2060 			 */
2061 			pinfo->desegment_offset = start_offset;
2062 			pinfo->desegment_len =
2063 			message_length - length_remaining;
2064 
2065 			/*
2066 			 * Return 0, which means "I didn't dissect anything
2067 			 * because I don't have enough data - we need
2068 			 * to desegment".
2069 			 */
2070 			return 0;
2071 		}
2072 	}
2073 
2074 	var_list = next_tvb_list_new(pinfo->pool);
2075 
2076 	col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_get_protocol_short_name(find_protocol_by_id(proto)));
2077 
2078 	item = proto_tree_add_item(tree, proto, tvb, start_offset, message_length, ENC_BIG_ENDIAN);
2079 	snmp_tree = proto_item_add_subtree(item, ett);
2080 
2081 	switch (version) {
2082 	case 0: /* v1 */
2083 	case 1: /* v2c */
2084 		offset = dissect_snmp_Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2085 		break;
2086 	case 2: /* v2u */
2087 		offset = dissect_snmp_Messagev2u(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2088 		break;
2089 			/* v3 */
2090 	case 3:
2091 		offset = dissect_snmp_SNMPv3Message(FALSE , tvb, start_offset, &asn1_ctx, snmp_tree, -1);
2092 		break;
2093 	default:
2094 		/*
2095 		 * Return the length remaining in the tvbuff, so
2096 		 * if this is SNMP-over-TCP, our caller thinks there's
2097 		 * nothing left to dissect.
2098 		 */
2099 		expert_add_info(pinfo, item, &ei_snmp_version_unknown);
2100 		return length_remaining;
2101 		break;
2102 	}
2103 
2104 	/* There may be appended data after the SNMP data, so treat as raw
2105 	 * data which needs to be dissected in case of UDP as UDP is PDU oriented.
2106  	 */
2107 	if((!is_tcp) && (length_remaining > (guint)offset)) {
2108 		next_tvb = tvb_new_subset_remaining(tvb, offset);
2109 		call_dissector(data_handle, next_tvb, pinfo, tree);
2110 	} else {
2111 		next_tvb_call(var_list, pinfo, tree, NULL, data_handle);
2112 	}
2113 
2114 	return offset;
2115 }
2116 
2117 static gint
dissect_snmp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2118 dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2119 {
2120 	int offset;
2121 	gint8 tmp_class;
2122 	gboolean tmp_pc;
2123 	gint32 tmp_tag;
2124 	guint32 tmp_length;
2125 	gboolean tmp_ind;
2126 
2127 	/*
2128 	 * See if this looks like SNMP or not. if not, return 0 so
2129 	 * wireshark can try some other dissector instead.
2130 	 */
2131 	/* All SNMP packets are BER encoded and consist of a SEQUENCE
2132 	 * that spans the entire PDU. The first item is an INTEGER that
2133 	 * has the values 0-2 (version 1-3).
2134 	 * if not it is not snmp.
2135 	 */
2136 	/* SNMP starts with a SEQUENCE */
2137 	offset = get_ber_identifier(tvb, 0, &tmp_class, &tmp_pc, &tmp_tag);
2138 	if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_SEQUENCE)) {
2139 		return 0;
2140 	}
2141 	/* then comes a length which spans the rest of the tvb */
2142 	offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
2143 	/* if(tmp_length!=(guint32)tvb_reported_length_remaining(tvb, offset)) {
2144 	 * Loosen the heuristic a bit to handle the case where data has intentionally
2145 	 * been added after the snmp PDU ( UDP case)
2146 	 */
2147 	if ( pinfo->ptype == PT_UDP ) {
2148 		if(tmp_length>(guint32)tvb_reported_length_remaining(tvb, offset)) {
2149 			return 0;
2150 		}
2151 	}else{
2152 		if(tmp_length!=(guint32)tvb_reported_length_remaining(tvb, offset)) {
2153 			return 0;
2154 		}
2155 	}
2156 	/* then comes an INTEGER (version)*/
2157 	get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
2158 	if((tmp_class!=BER_CLASS_UNI)||(tmp_tag!=BER_UNI_TAG_INTEGER)) {
2159 		return 0;
2160 	}
2161 	/* do we need to test that version is 0 - 2 (version1-3) ? */
2162 
2163 
2164 	/*
2165 	 * The first SNMP packet goes to the SNMP port; the second one
2166 	 * may come from some *other* port, but goes back to the same
2167 	 * IP address and port as the ones from which the first packet
2168 	 * came; all subsequent packets presumably go between those two
2169 	 * IP addresses and ports.
2170 	 *
2171 	 * If this packet went to the SNMP port, we check to see if
2172 	 * there's already a conversation with one address/port pair
2173 	 * matching the source IP address and port of this packet,
2174 	 * the other address matching the destination IP address of this
2175 	 * packet, and any destination port.
2176 	 *
2177 	 * If not, we create one, with its address 1/port 1 pair being
2178 	 * the source address/port of this packet, its address 2 being
2179 	 * the destination address of this packet, and its port 2 being
2180 	 * wildcarded, and give it the SNMP dissector as a dissector.
2181 	 */
2182 
2183 	return dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
2184 }
2185 
2186 static int
dissect_snmp_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2187 dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2188 {
2189 	int offset = 0;
2190 	guint message_len;
2191 
2192 	while (tvb_reported_length_remaining(tvb, offset) > 0) {
2193 		message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, TRUE);
2194 		if (message_len == 0) {
2195 			/*
2196 			 * We don't have all the data for that message,
2197 			 * so we need to do desegmentation;
2198 			 * "dissect_snmp_pdu()" has set that up.
2199 			 */
2200 			break;
2201 		}
2202 		offset += message_len;
2203 	}
2204 	return tvb_captured_length(tvb);
2205 }
2206 
2207 static int
dissect_smux(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2208 dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2209 {
2210 	proto_tree *smux_tree = NULL;
2211 	proto_item *item = NULL;
2212 
2213 	var_list = next_tvb_list_new(pinfo->pool);
2214 
2215 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
2216 
2217 	item = proto_tree_add_item(tree, proto_smux, tvb, 0, -1, ENC_NA);
2218 	smux_tree = proto_item_add_subtree(item, ett_smux);
2219 
2220 	return dissect_SMUX_PDUs_PDU(tvb, pinfo, smux_tree, data);
2221 }
2222 
2223 /*
2224   MD5 Password to Key Algorithm from RFC 3414 A.2.1
2225   SHA1 Password to Key Algorithm from RFC 3414 A.2.2
2226   SHA2 Password to Key Algorithm from RFC 7860 9.3
2227 */
2228 static void
snmp_usm_password_to_key(const snmp_usm_auth_model_t model,const guint8 * password,guint passwordlen,const guint8 * engineID,guint engineLength,guint8 * key)2229 snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password,
2230 	guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key)
2231 {
2232 	gcry_md_hd_t	hash_handle;
2233 	guint8	  *cp, password_buf[64];
2234 	guint32	 password_index = 0;
2235 	guint32	 count = 0, i;
2236 	guint	   hash_len;
2237 
2238 	if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
2239 		return;
2240 	}
2241 
2242 	hash_len = auth_hash_len[model];
2243 
2244 	/**********************************************/
2245 	/* Use while loop until we've done 1 Megabyte */
2246 	/**********************************************/
2247 	while (count < 1048576) {
2248 		cp = password_buf;
2249 		if (passwordlen != 0) {
2250 			for (i = 0; i < 64; i++) {
2251 				/*************************************************/
2252 				/* Take the next octet of the password, wrapping */
2253 				/* to the beginning of the password as necessary.*/
2254 				/*************************************************/
2255 				*cp++ = password[password_index++ % passwordlen];
2256 			}
2257 		} else {
2258 			*cp = 0;
2259 		}
2260 		gcry_md_write(hash_handle, password_buf, 64);
2261 		count += 64;
2262 	}
2263 	memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
2264 	gcry_md_close(hash_handle);
2265 
2266 	/*****************************************************/
2267 	/* Now localise the key with the engineID and pass   */
2268 	/* through hash function to produce final key        */
2269 	/* We ignore invalid engineLengths here. More strict */
2270 	/* checking is done in snmp_users_update_cb.         */
2271 	/*****************************************************/
2272 	if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
2273 		return;
2274 	}
2275 	gcry_md_write(hash_handle, key, hash_len);
2276 	gcry_md_write(hash_handle, engineID, engineLength);
2277 	gcry_md_write(hash_handle, key, hash_len);
2278 	memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
2279 	gcry_md_close(hash_handle);
2280 	return;
2281 }
2282 
2283 static void
process_prefs(void)2284 process_prefs(void)
2285 {
2286 }
2287 
2288 UAT_LSTRING_CB_DEF(snmp_users,userName,snmp_ue_assoc_t,user.userName.data,user.userName.len)
2289 UAT_LSTRING_CB_DEF(snmp_users,authPassword,snmp_ue_assoc_t,user.authPassword.data,user.authPassword.len)
2290 UAT_LSTRING_CB_DEF(snmp_users,privPassword,snmp_ue_assoc_t,user.privPassword.data,user.privPassword.len)
2291 UAT_BUFFER_CB_DEF(snmp_users,engine_id,snmp_ue_assoc_t,engine.data,engine.len)
2292 UAT_VS_DEF(snmp_users,auth_model,snmp_ue_assoc_t,guint,0,"MD5")
2293 UAT_VS_DEF(snmp_users,priv_proto,snmp_ue_assoc_t,guint,0,"DES")
2294 
2295 static void *
snmp_specific_trap_copy_cb(void * dest,const void * orig,size_t len _U_)2296 snmp_specific_trap_copy_cb(void *dest, const void *orig, size_t len _U_)
2297 {
2298 	snmp_st_assoc_t *u = (snmp_st_assoc_t *)dest;
2299 	const snmp_st_assoc_t *o = (const snmp_st_assoc_t *)orig;
2300 
2301 	u->enterprise = g_strdup(o->enterprise);
2302 	u->trap = o->trap;
2303 	u->desc = g_strdup(o->desc);
2304 
2305 	return dest;
2306 }
2307 
2308 static void
snmp_specific_trap_free_cb(void * r)2309 snmp_specific_trap_free_cb(void *r)
2310 {
2311 	snmp_st_assoc_t *u = (snmp_st_assoc_t *)r;
2312 
2313 	g_free(u->enterprise);
2314 	g_free(u->desc);
2315 }
2316 
UAT_CSTRING_CB_DEF(specific_traps,enterprise,snmp_st_assoc_t)2317 UAT_CSTRING_CB_DEF(specific_traps, enterprise, snmp_st_assoc_t)
2318 UAT_DEC_CB_DEF(specific_traps, trap, snmp_st_assoc_t)
2319 UAT_CSTRING_CB_DEF(specific_traps, desc, snmp_st_assoc_t)
2320 
2321 	/*--- proto_register_snmp -------------------------------------------*/
2322 void proto_register_snmp(void) {
2323 	/* List of fields */
2324 	static hf_register_info hf[] = {
2325 		{ &hf_snmp_response_in,
2326 		{ "Response In", "snmp.response_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2327 			"The response to this SNMP request is in this frame", HFILL }},
2328 		{ &hf_snmp_response_to,
2329 		{ "Response To", "snmp.response_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2330 			"This is a response to the SNMP request in this frame", HFILL }},
2331 		{ &hf_snmp_time,
2332 		{ "Time", "snmp.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2333 			"The time between the Request and the Response", HFILL }},
2334 		{ &hf_snmp_v3_flags_auth,
2335 		{ "Authenticated", "snmp.v3.flags.auth", FT_BOOLEAN, 8,
2336 		    TFS(&tfs_set_notset), TH_AUTH, NULL, HFILL }},
2337 		{ &hf_snmp_v3_flags_crypt,
2338 		{ "Encrypted", "snmp.v3.flags.crypt", FT_BOOLEAN, 8,
2339 		    TFS(&tfs_set_notset), TH_CRYPT, NULL, HFILL }},
2340 		{ &hf_snmp_v3_flags_report,
2341 		{ "Reportable", "snmp.v3.flags.report", FT_BOOLEAN, 8,
2342 		    TFS(&tfs_set_notset), TH_REPORT, NULL, HFILL }},
2343 		{ &hf_snmp_engineid_conform, {
2344 		    "Engine ID Conformance", "snmp.engineid.conform", FT_BOOLEAN, 8,
2345 		    TFS(&tfs_snmp_engineid_conform), F_SNMP_ENGINEID_CONFORM, "Engine ID RFC3411 Conformance", HFILL }},
2346 		{ &hf_snmp_engineid_enterprise, {
2347 		    "Engine Enterprise ID", "snmp.engineid.enterprise", FT_UINT32, BASE_ENTERPRISES,
2348 		    STRINGS_ENTERPRISES, 0, NULL, HFILL }},
2349 		{ &hf_snmp_engineid_format, {
2350 		    "Engine ID Format", "snmp.engineid.format", FT_UINT8, BASE_DEC,
2351 		    VALS(snmp_engineid_format_vals), 0, NULL, HFILL }},
2352 		{ &hf_snmp_engineid_ipv4, {
2353 		    "Engine ID Data: IPv4 address", "snmp.engineid.ipv4", FT_IPv4, BASE_NONE,
2354 		    NULL, 0, NULL, HFILL }},
2355 		{ &hf_snmp_engineid_ipv6, {
2356 		    "Engine ID Data: IPv6 address", "snmp.engineid.ipv6", FT_IPv6, BASE_NONE,
2357 		    NULL, 0, NULL, HFILL }},
2358 		{ &hf_snmp_engineid_cisco_type, {
2359 		    "Engine ID Data: Cisco type", "snmp.engineid.cisco.type", FT_UINT8, BASE_HEX,
2360 		    VALS(snmp_engineid_cisco_type_vals), 0, NULL, HFILL }},
2361 		{ &hf_snmp_engineid_mac, {
2362 		    "Engine ID Data: MAC address", "snmp.engineid.mac", FT_ETHER, BASE_NONE,
2363 		    NULL, 0, NULL, HFILL }},
2364 		{ &hf_snmp_engineid_text, {
2365 		    "Engine ID Data: Text", "snmp.engineid.text", FT_STRING, BASE_NONE,
2366 		    NULL, 0, NULL, HFILL }},
2367 		{ &hf_snmp_engineid_time, {
2368 		    "Engine ID Data: Creation Time", "snmp.engineid.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
2369 		    NULL, 0, NULL, HFILL }},
2370 		{ &hf_snmp_engineid_data, {
2371 		    "Engine ID Data", "snmp.engineid.data", FT_BYTES, BASE_NONE,
2372 		    NULL, 0, NULL, HFILL }},
2373 		{ &hf_snmp_msgAuthentication, {
2374 		    "Authentication", "snmp.v3.auth", FT_BOOLEAN, BASE_NONE,
2375 		    TFS(&auth_flags), 0, NULL, HFILL }},
2376 		{ &hf_snmp_decryptedPDU, {
2377 		    "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES, BASE_NONE,
2378 		    NULL, 0, "Decrypted PDU", HFILL }},
2379 		{ &hf_snmp_noSuchObject, {
2380 		    "noSuchObject", "snmp.noSuchObject", FT_NONE, BASE_NONE,
2381 		    NULL, 0, NULL, HFILL }},
2382 		{ &hf_snmp_noSuchInstance, {
2383 		    "noSuchInstance", "snmp.noSuchInstance", FT_NONE, BASE_NONE,
2384 		    NULL, 0, NULL, HFILL }},
2385 		{ &hf_snmp_endOfMibView, {
2386 		    "endOfMibView", "snmp.endOfMibView", FT_NONE, BASE_NONE,
2387 		    NULL, 0, NULL, HFILL }},
2388 		{ &hf_snmp_unSpecified, {
2389 		    "unSpecified", "snmp.unSpecified", FT_NONE, BASE_NONE,
2390 		    NULL, 0, NULL, HFILL }},
2391 
2392 		{ &hf_snmp_integer32_value, {
2393 		    "Value (Integer32)", "snmp.value.int", FT_INT64, BASE_DEC,
2394 		    NULL, 0, NULL, HFILL }},
2395 		{ &hf_snmp_octetstring_value, {
2396 		    "Value (OctetString)", "snmp.value.octets", FT_BYTES, BASE_SHOW_ASCII_PRINTABLE,
2397 		    NULL, 0, NULL, HFILL }},
2398 		{ &hf_snmp_oid_value, {
2399 		    "Value (OID)", "snmp.value.oid", FT_OID, BASE_NONE,
2400 		    NULL, 0, NULL, HFILL }},
2401 		{ &hf_snmp_null_value, {
2402 		    "Value (Null)", "snmp.value.null", FT_NONE, BASE_NONE,
2403 		    NULL, 0, NULL, HFILL }},
2404 		{ &hf_snmp_ipv4_value, {
2405 		    "Value (IpAddress)", "snmp.value.ipv4", FT_IPv4, BASE_NONE,
2406 		    NULL, 0, NULL, HFILL }},
2407 		{ &hf_snmp_ipv6_value, {
2408 		    "Value (IpAddress)", "snmp.value.ipv6", FT_IPv6, BASE_NONE,
2409 		    NULL, 0, NULL, HFILL }},
2410 		{ &hf_snmp_anyaddress_value, {
2411 		    "Value (IpAddress)", "snmp.value.addr", FT_BYTES, BASE_NONE,
2412 		    NULL, 0, NULL, HFILL }},
2413 		{ &hf_snmp_unsigned32_value, {
2414 		    "Value (Unsigned32)", "snmp.value.u32", FT_INT64, BASE_DEC,
2415 		    NULL, 0, NULL, HFILL }},
2416 		{ &hf_snmp_gauge32_value, {
2417 		    "Value (Gauge32)", "snmp.value.g32", FT_INT64, BASE_DEC,
2418 		    NULL, 0, NULL, HFILL }},
2419 		{ &hf_snmp_unknown_value, {
2420 		    "Value (Unknown)", "snmp.value.unk", FT_BYTES, BASE_NONE,
2421 		    NULL, 0, NULL, HFILL }},
2422 		{ &hf_snmp_counter_value, {
2423 		    "Value (Counter32)", "snmp.value.counter", FT_UINT64, BASE_DEC,
2424 		    NULL, 0, NULL, HFILL }},
2425 		{ &hf_snmp_big_counter_value, {
2426 		    "Value (Counter64)", "snmp.value.counter", FT_UINT64, BASE_DEC,
2427 		    NULL, 0, NULL, HFILL }},
2428 		{ &hf_snmp_nsap_value, {
2429 		    "Value (NSAP)", "snmp.value.nsap", FT_UINT64, BASE_DEC,
2430 		    NULL, 0, NULL, HFILL }},
2431 		{ &hf_snmp_timeticks_value, {
2432 		    "Value (Timeticks)", "snmp.value.timeticks", FT_UINT64, BASE_DEC,
2433 		    NULL, 0, NULL, HFILL }},
2434 		{ &hf_snmp_opaque_value, {
2435 		    "Value (Opaque)", "snmp.value.opaque", FT_BYTES, BASE_NONE,
2436 		    NULL, 0, NULL, HFILL }},
2437 		{ &hf_snmp_objectname, {
2438 		    "Object Name", "snmp.name", FT_OID, BASE_NONE,
2439 		    NULL, 0, NULL, HFILL }},
2440 		{ &hf_snmp_scalar_instance_index, {
2441 		    "Scalar Instance Index", "snmp.name.index", FT_UINT64, BASE_DEC,
2442 		    NULL, 0, NULL, HFILL }},
2443 		{ &hf_snmp_var_bind_str, {
2444 		    "Variable-binding-string", "snmp.var-bind_str", FT_STRING, BASE_NONE,
2445 		    NULL, 0, NULL, HFILL }},
2446 		{ &hf_snmp_agentid_trailer, {
2447 		    "AgentID Trailer", "snmp.agentid_trailer", FT_BYTES, BASE_NONE,
2448 		    NULL, 0, NULL, HFILL }},
2449 
2450 
2451 #include "packet-snmp-hfarr.c"
2452 	};
2453 
2454 	/* List of subtrees */
2455 	static gint *ett[] = {
2456 		&ett_snmp,
2457 		&ett_engineid,
2458 		&ett_msgFlags,
2459 		&ett_encryptedPDU,
2460 		&ett_decrypted,
2461 		&ett_authParameters,
2462 		&ett_internet,
2463 		&ett_varbind,
2464 		&ett_name,
2465 		&ett_value,
2466 		&ett_decoding_error,
2467 #include "packet-snmp-ettarr.c"
2468 	};
2469 	static ei_register_info ei[] = {
2470 		{ &ei_snmp_failed_decrypted_data_pdu, { "snmp.failed_decrypted_data_pdu", PI_MALFORMED, PI_WARN, "Failed to decrypt encryptedPDU", EXPFILL }},
2471 		{ &ei_snmp_decrypted_data_bad_formatted, { "snmp.decrypted_data_bad_formatted", PI_MALFORMED, PI_WARN, "Decrypted data not formatted as expected, wrong key?", EXPFILL }},
2472 		{ &ei_snmp_verify_authentication_error, { "snmp.verify_authentication_error", PI_MALFORMED, PI_ERROR, "Error while verifying Message authenticity", EXPFILL }},
2473 		{ &ei_snmp_authentication_ok, { "snmp.authentication_ok", PI_CHECKSUM, PI_CHAT, "SNMP Authentication OK", EXPFILL }},
2474 		{ &ei_snmp_authentication_error, { "snmp.authentication_error", PI_CHECKSUM, PI_WARN, "SNMP Authentication Error", EXPFILL }},
2475 		{ &ei_snmp_varbind_not_uni_class_seq, { "snmp.varbind.not_uni_class_seq", PI_MALFORMED, PI_WARN, "VarBind is not an universal class sequence", EXPFILL }},
2476 		{ &ei_snmp_varbind_has_indicator, { "snmp.varbind.has_indicator", PI_MALFORMED, PI_WARN, "VarBind has indicator set", EXPFILL }},
2477 		{ &ei_snmp_objectname_not_oid, { "snmp.objectname_not_oid", PI_MALFORMED, PI_WARN, "ObjectName not an OID", EXPFILL }},
2478 		{ &ei_snmp_objectname_has_indicator, { "snmp.objectname_has_indicator", PI_MALFORMED, PI_WARN, "ObjectName has indicator set", EXPFILL }},
2479 		{ &ei_snmp_value_not_primitive_encoding, { "snmp.value_not_primitive_encoding", PI_MALFORMED, PI_WARN, "value not in primitive encoding", EXPFILL }},
2480 		{ &ei_snmp_invalid_oid, { "snmp.invalid_oid", PI_MALFORMED, PI_WARN, "invalid oid", EXPFILL }},
2481 		{ &ei_snmp_varbind_wrong_tag, { "snmp.varbind.wrong_tag", PI_MALFORMED, PI_WARN, "Wrong tag for SNMP VarBind error value", EXPFILL }},
2482 		{ &ei_snmp_varbind_response, { "snmp.varbind.response", PI_RESPONSE_CODE, PI_NOTE, "Response", EXPFILL }},
2483 		{ &ei_snmp_no_instance_subid, { "snmp.no_instance_subid", PI_MALFORMED, PI_WARN, "No instance sub-id in scalar value", EXPFILL }},
2484 		{ &ei_snmp_wrong_num_of_subids, { "snmp.wrong_num_of_subids", PI_MALFORMED, PI_WARN, "Wrong number of instance sub-ids in scalar value", EXPFILL }},
2485 		{ &ei_snmp_index_suboid_too_short, { "snmp.index_suboid_too_short", PI_MALFORMED, PI_WARN, "index sub-oid shorter than expected", EXPFILL }},
2486 		{ &ei_snmp_unimplemented_instance_index, { "snmp.unimplemented_instance_index", PI_UNDECODED, PI_WARN, "OID instaces not handled, if you want this implemented please contact the wireshark developers", EXPFILL }},
2487 		{ &ei_snmp_index_suboid_len0, { "snmp.ndex_suboid_len0", PI_MALFORMED, PI_WARN, "an index sub-oid OID cannot be 0 bytes long!", EXPFILL }},
2488 		{ &ei_snmp_index_suboid_too_long, { "snmp.index_suboid_too_long", PI_MALFORMED, PI_WARN, "index sub-oid should not be longer than remaining oid size", EXPFILL }},
2489 		{ &ei_snmp_index_string_too_long, { "snmp.index_string_too_long", PI_MALFORMED, PI_WARN, "index string should not be longer than remaining oid size", EXPFILL }},
2490 		{ &ei_snmp_column_parent_not_row, { "snmp.column_parent_not_row", PI_MALFORMED, PI_ERROR, "COLUMNS's parent is not a ROW", EXPFILL }},
2491 		{ &ei_snmp_uint_too_large, { "snmp.uint_too_large", PI_UNDECODED, PI_NOTE, "Unsigned integer value > 2^64 - 1", EXPFILL }},
2492 		{ &ei_snmp_int_too_large, { "snmp.int_too_large", PI_UNDECODED, PI_NOTE, "Signed integer value > 2^63 - 1 or <= -2^63", EXPFILL }},
2493 		{ &ei_snmp_integral_value0, { "snmp.integral_value0", PI_UNDECODED, PI_NOTE, "Integral value is zero-length", EXPFILL }},
2494 		{ &ei_snmp_missing_mib, { "snmp.missing_mib", PI_UNDECODED, PI_NOTE, "Unresolved value, Missing MIB", EXPFILL }},
2495 		{ &ei_snmp_varbind_wrong_length_value, { "snmp.varbind.wrong_length_value", PI_MALFORMED, PI_WARN, "Wrong length for SNMP VarBind/value", EXPFILL }},
2496 		{ &ei_snmp_varbind_wrong_class_tag, { "snmp.varbind.wrong_class_tag", PI_MALFORMED, PI_WARN, "Wrong class/tag for SNMP VarBind/value", EXPFILL }},
2497 		{ &ei_snmp_rfc1910_non_conformant, { "snmp.rfc1910_non_conformant", PI_PROTOCOL, PI_WARN, "Data not conforming to RFC1910", EXPFILL }},
2498 		{ &ei_snmp_rfc3411_non_conformant, { "snmp.rfc3411_non_conformant", PI_PROTOCOL, PI_WARN, "Data not conforming to RFC3411", EXPFILL }},
2499 		{ &ei_snmp_version_unknown, { "snmp.version.unknown", PI_PROTOCOL, PI_WARN, "Unknown version", EXPFILL }},
2500 		{ &ei_snmp_trap_pdu_obsolete, { "snmp.trap_pdu_obsolete", PI_PROTOCOL, PI_WARN, "Trap-PDU is obsolete in this SNMP version", EXPFILL }},
2501 
2502 	};
2503 
2504 	expert_module_t* expert_snmp;
2505 	module_t *snmp_module;
2506 
2507 	static uat_field_t users_fields[] = {
2508 		UAT_FLD_BUFFER(snmp_users,engine_id,"Engine ID","Engine-id for this entry (empty = any)"),
2509 		UAT_FLD_LSTRING(snmp_users,userName,"Username","The username"),
2510 		UAT_FLD_VS(snmp_users,auth_model,"Authentication model",auth_types,"Algorithm to be used for authentication."),
2511 		UAT_FLD_LSTRING(snmp_users,authPassword,"Password","The password used for authenticating packets for this entry"),
2512 		UAT_FLD_VS(snmp_users,priv_proto,"Privacy protocol",priv_types,"Algorithm to be used for privacy."),
2513 		UAT_FLD_LSTRING(snmp_users,privPassword,"Privacy password","The password used for encrypting packets for this entry"),
2514 		UAT_END_FIELDS
2515 	};
2516 
2517 	uat_t *assocs_uat = uat_new("SNMP Users",
2518 				    sizeof(snmp_ue_assoc_t),
2519 				    "snmp_users",
2520 				    TRUE,
2521 				    &ueas,
2522 				    &num_ueas,
2523 				    UAT_AFFECTS_DISSECTION,	/* affects dissection of packets, but not set of named fields */
2524 				    "ChSNMPUsersSection",
2525 				    snmp_users_copy_cb,
2526 				    snmp_users_update_cb,
2527 				    snmp_users_free_cb,
2528 				    renew_ue_cache,
2529 				    NULL,
2530 				    users_fields);
2531 
2532 	static uat_field_t specific_traps_flds[] = {
2533 		UAT_FLD_CSTRING(specific_traps,enterprise,"Enterprise OID","Enterprise Object Identifier"),
2534 		UAT_FLD_DEC(specific_traps,trap,"Trap Id","The specific-trap value"),
2535 		UAT_FLD_CSTRING(specific_traps,desc,"Description","Trap type description"),
2536 		UAT_END_FIELDS
2537 	};
2538 
2539 	uat_t* specific_traps_uat = uat_new("SNMP Enterprise Specific Trap Types",
2540 					    sizeof(snmp_st_assoc_t),
2541 					    "snmp_specific_traps",
2542 					    TRUE,
2543 					    &specific_traps,
2544 					    &num_specific_traps,
2545 					    UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
2546 					    "ChSNMPEnterpriseSpecificTrapTypes",
2547 					    snmp_specific_trap_copy_cb,
2548 					    NULL,
2549 					    snmp_specific_trap_free_cb,
2550 					    NULL,
2551 					    NULL,
2552 					    specific_traps_flds);
2553 
2554 	/* Register protocol */
2555 	proto_snmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
2556 	snmp_handle = register_dissector("snmp", dissect_snmp, proto_snmp);
2557 
2558 	/* Register fields and subtrees */
2559 	proto_register_field_array(proto_snmp, hf, array_length(hf));
2560 	proto_register_subtree_array(ett, array_length(ett));
2561 	expert_snmp = expert_register_protocol(proto_snmp);
2562 	expert_register_field_array(expert_snmp, ei, array_length(ei));
2563 
2564 
2565 	/* Register configuration preferences */
2566 	snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
2567 	prefs_register_bool_preference(snmp_module, "display_oid",
2568 			"Show SNMP OID in info column",
2569 			"Whether the SNMP OID should be shown in the info column",
2570 			&display_oid);
2571 
2572 	prefs_register_obsolete_preference(snmp_module, "mib_modules");
2573 	prefs_register_obsolete_preference(snmp_module, "users_file");
2574 
2575 	prefs_register_bool_preference(snmp_module, "desegment",
2576 			"Reassemble SNMP-over-TCP messages spanning multiple TCP segments",
2577 			"Whether the SNMP dissector should reassemble messages spanning multiple TCP segments."
2578 			" To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2579 			&snmp_desegment);
2580 
2581 	prefs_register_bool_preference(snmp_module, "var_in_tree",
2582 			"Display dissected variables inside SNMP tree",
2583 			"ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP",
2584 			&snmp_var_in_tree);
2585 
2586 	prefs_register_uat_preference(snmp_module, "users_table",
2587 				"Users Table",
2588 				"Table of engine-user associations used for authentication and decryption",
2589 				assocs_uat);
2590 
2591 	prefs_register_uat_preference(snmp_module, "specific_traps_table",
2592 				"Enterprise Specific Trap Types",
2593 				"Table of enterprise specific-trap type descriptions",
2594 				specific_traps_uat);
2595 
2596 #ifdef HAVE_LIBSMI
2597 	prefs_register_static_text_preference(snmp_module, "info_mibs",
2598 				"MIB settings can be changed in the Name Resolution preferences",
2599 				"MIB settings can be changed in the Name Resolution preferences");
2600 #endif
2601 
2602 	value_sub_dissectors_table = register_dissector_table("snmp.variable_oid","SNMP Variable OID", proto_snmp, FT_STRING, BASE_NONE);
2603 
2604 	register_init_routine(init_ue_cache);
2605 	register_cleanup_routine(cleanup_ue_cache);
2606 
2607 	register_ber_syntax_dissector("SNMP", proto_snmp, dissect_snmp_tcp);
2608 
2609 	snmp_tap=register_tap("snmp");
2610 
2611 	register_srt_table(proto_snmp, NULL, 1, snmpstat_packet, snmpstat_init, NULL);
2612 }
2613 
2614 
2615 /*--- proto_reg_handoff_snmp ---------------------------------------*/
proto_reg_handoff_snmp(void)2616 void proto_reg_handoff_snmp(void) {
2617 	dissector_handle_t snmp_tcp_handle;
2618 
2619 	dissector_add_uint_with_preference("udp.port", UDP_PORT_SNMP, snmp_handle);
2620 	dissector_add_uint("ethertype", ETHERTYPE_SNMP, snmp_handle);
2621 	dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
2622 	dissector_add_uint("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
2623 	dissector_add_uint("hpext.dxsap", HPEXT_SNMP, snmp_handle);
2624 
2625 	snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
2626 	dissector_add_uint_with_preference("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
2627 	/* Since "regular" SNMP port and "trap" SNMP port use the same handler,
2628 	   the "trap" port doesn't really need a separate preference.  Just register
2629 	   normally */
2630 	dissector_add_uint("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
2631 	dissector_add_uint("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
2632 	dissector_add_uint("udp.port", UDP_PORT_SNMP_PATROL, snmp_handle);
2633 
2634 	data_handle = find_dissector("data");
2635 
2636 	/* SNMPv2-MIB sysDescr "1.3.6.1.2.1.1.1.0" */
2637 	dissector_add_string("snmp.variable_oid", "1.3.6.1.2.1.1.1.0",
2638 		create_dissector_handle(dissect_snmp_variable_string, proto_snmp));
2639 	/* SNMPv2-MIB::sysName.0 (1.3.6.1.2.1.1.5.0) */
2640 	dissector_add_string("snmp.variable_oid", "1.3.6.1.2.1.1.5.0",
2641 		create_dissector_handle(dissect_snmp_variable_string, proto_snmp));
2642 
2643 	/*
2644 	 * Process preference settings.
2645 	 *
2646 	 * We can't do this in the register routine, as preferences aren't
2647 	 * read until all dissector register routines have been called (so
2648 	 * that all dissector preferences have been registered).
2649 	 */
2650 	process_prefs();
2651 
2652 }
2653 
2654 void
proto_register_smux(void)2655 proto_register_smux(void)
2656 {
2657 	static gint *ett[] = {
2658 		&ett_smux,
2659 	};
2660 
2661 	proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
2662 	    "SMUX", "smux");
2663 
2664 	proto_register_subtree_array(ett, array_length(ett));
2665 
2666 }
2667 
2668 void
proto_reg_handoff_smux(void)2669 proto_reg_handoff_smux(void)
2670 {
2671 	dissector_handle_t smux_handle;
2672 
2673 	smux_handle = create_dissector_handle(dissect_smux, proto_smux);
2674 	dissector_add_uint_with_preference("tcp.port", TCP_PORT_SMUX, smux_handle);
2675 }
2676 
2677 /*
2678  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2679  *
2680  * Local variables:
2681  * c-basic-offset: 8
2682  * tab-width: 8
2683  * indent-tabs-mode: t
2684  * End:
2685  *
2686  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2687  * :indentSize=8:tabSize=8:noTabs=false:
2688  */
2689