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