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