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