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