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