Update Free Software Foundation address.
[metze/wireshark/wip.git] / asn1 / ldap / packet-ldap-template.c
1 /* packet-ldap.c
2  * Routines for ldap packet dissection
3  *
4  * See RFC 1777 (LDAP v2), RFC 4511 (LDAP v3), and RFC 2222 (SASL).
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 /*
28  * This is not a complete implementation. It doesn't handle the full version 3, more specifically,
29  * it handles only the commands of version 2, but any additional characteristics of the ver3 command are supported.
30  * It's also missing extensible search filters.
31  *
32  * There should probably be alot more error checking, I simply assume that if we have a full packet, it will be a complete
33  * and correct packet.
34  *
35  * AFAIK, it will handle all messages used by the OpenLDAP 1.2.9 server and libraries which was my goal. I do plan to add
36  * the remaining commands as time permits but this is not a priority to me. Send me an email if you need it and I'll see what
37  * I can do.
38  *
39  * Doug Nazar
40  * nazard@dragoninc.on.ca
41  */
42
43 /*
44  * 11/11/2002 - Fixed problem when decoding LDAP with desegmentation enabled and the
45  *              ASN.1 BER Universal Class Tag: "Sequence Of" header is encapsulated across 2
46  *              TCP segments.
47  *
48  * Ronald W. Henderson
49  * ronald.henderson@cognicaseusa.com
50  */
51
52 /*
53  * 20-JAN-2004 - added decoding of MS-CLDAP netlogon RPC
54  *               using information from the SNIA 2003 conference paper :
55  *               Active Directory Domain Controller Location Service
56  *                    by Anthony Liguori
57  * ronnie sahlberg
58  */
59
60 /*
61  * 17-DEC-2004 - added basic decoding for LDAP Controls
62  * 20-DEC-2004 - added handling for GSS-API encrypted blobs
63  *
64  * Stefan Metzmacher <metze@samba.org>
65  *
66  * 15-NOV-2005 - Changed to use the asn2wrs compiler
67  * Anders Broman <anders.broman@ericsson.com>
68  */
69
70 /*
71  * 3-AUG-2008 - Extended the cldap support to include all netlogon data types.
72  *                              Updated cldap_netlogon_flags to include Windows 2008 flags
73  *                              Expanded the ntver ldap option with bit field
74  *
75  * Gary Reynolds <gazzadownunder@yahoo.co.uk>
76  */
77
78 /*
79  * 09-DEC-2009 - Added support for RFC4533
80  *               Content Synchronization Operation (aka syncrepl)
81  * 11-DEC-2009 - Added support for IntermediateResponse (LDAP v3 from RFC 4511)
82  * Mathieu Parent <math.parent@gmail.com>
83  */
84
85 #ifdef HAVE_CONFIG_H
86 # include "config.h"
87 #endif
88
89 #include <string.h>
90 #include <ctype.h>
91
92 #include <glib.h>
93
94 #include <epan/packet.h>
95 #include <epan/conversation.h>
96 #include <epan/prefs.h>
97 #include <epan/tap.h>
98 #include <epan/emem.h>
99 #include <epan/oids.h>
100 #include <epan/strutil.h>
101 #include <epan/dissectors/packet-frame.h>
102 #include <epan/dissectors/packet-tcp.h>
103 #include <epan/dissectors/packet-windows-common.h>
104 #include <epan/dissectors/packet-dcerpc.h>
105 #include <epan/asn1.h>
106 #include <epan/expert.h>
107 #include <epan/uat.h>
108
109 #include "packet-ldap.h"
110 #include "packet-ntlmssp.h"
111 #include "packet-ssl.h"
112 #include "packet-smb-common.h"
113
114 #include "packet-ber.h"
115 #include "packet-per.h"
116 #include "packet-dns.h"
117
118 #define PNAME  "Lightweight Directory Access Protocol"
119 #define PSNAME "LDAP"
120 #define PFNAME "ldap"
121
122 /* Initialize the protocol and registered fields */
123 static int ldap_tap = -1;
124 static int proto_ldap = -1;
125 static int proto_cldap = -1;
126
127 static int hf_ldap_sasl_buffer_length = -1;
128 static int hf_ldap_response_in = -1;
129 static int hf_ldap_response_to = -1;
130 static int hf_ldap_time = -1;
131 static int hf_ldap_guid = -1;
132
133 static int hf_mscldap_ntver_flags = -1;
134 static int hf_mscldap_ntver_flags_v1 = -1;
135 static int hf_mscldap_ntver_flags_v5 = -1;
136 static int hf_mscldap_ntver_flags_v5ex = -1;
137 static int hf_mscldap_ntver_flags_v5ep = -1;
138 static int hf_mscldap_ntver_flags_vcs = -1;
139 static int hf_mscldap_ntver_flags_vnt4 = -1;
140 static int hf_mscldap_ntver_flags_vpdc = -1;
141 static int hf_mscldap_ntver_flags_vip = -1;
142 static int hf_mscldap_ntver_flags_vl = -1;
143 static int hf_mscldap_ntver_flags_vgc = -1;
144
145 static int hf_mscldap_netlogon_ipaddress_family = -1;
146 static int hf_mscldap_netlogon_ipaddress_port = -1;
147 static int hf_mscldap_netlogon_ipaddress = -1;
148 static int hf_mscldap_netlogon_ipaddress_ipv4 = -1;
149 static int hf_mscldap_netlogon_opcode = -1;
150 static int hf_mscldap_netlogon_flags = -1;
151 static int hf_mscldap_netlogon_flags_pdc = -1;
152 static int hf_mscldap_netlogon_flags_gc = -1;
153 static int hf_mscldap_netlogon_flags_ldap = -1;
154 static int hf_mscldap_netlogon_flags_ds = -1;
155 static int hf_mscldap_netlogon_flags_kdc = -1;
156 static int hf_mscldap_netlogon_flags_timeserv = -1;
157 static int hf_mscldap_netlogon_flags_closest = -1;
158 static int hf_mscldap_netlogon_flags_writable = -1;
159 static int hf_mscldap_netlogon_flags_good_timeserv = -1;
160 static int hf_mscldap_netlogon_flags_ndnc = -1;
161 static int hf_mscldap_netlogon_flags_fnc = -1;
162 static int hf_mscldap_netlogon_flags_dnc = -1;
163 static int hf_mscldap_netlogon_flags_dns = -1;
164 static int hf_mscldap_netlogon_flags_wdc = -1;
165 static int hf_mscldap_netlogon_flags_rodc = -1;
166 static int hf_mscldap_domain_guid = -1;
167 static int hf_mscldap_forest = -1;
168 static int hf_mscldap_domain = -1;
169 static int hf_mscldap_hostname = -1;
170 static int hf_mscldap_nb_domain = -1;
171 static int hf_mscldap_nb_hostname = -1;
172 static int hf_mscldap_username = -1;
173 static int hf_mscldap_sitename = -1;
174 static int hf_mscldap_clientsitename = -1;
175 static int hf_mscldap_netlogon_lm_token = -1;
176 static int hf_mscldap_netlogon_nt_token = -1;
177 static int hf_ldap_sid = -1;
178 static int hf_ldap_AccessMask_ADS_CREATE_CHILD = -1;
179 static int hf_ldap_AccessMask_ADS_DELETE_CHILD = -1;
180 static int hf_ldap_AccessMask_ADS_LIST = -1;
181 static int hf_ldap_AccessMask_ADS_SELF_WRITE = -1;
182 static int hf_ldap_AccessMask_ADS_READ_PROP = -1;
183 static int hf_ldap_AccessMask_ADS_WRITE_PROP = -1;
184 static int hf_ldap_AccessMask_ADS_DELETE_TREE = -1;
185 static int hf_ldap_AccessMask_ADS_LIST_OBJECT = -1;
186 static int hf_ldap_AccessMask_ADS_CONTROL_ACCESS = -1;
187
188 #include "packet-ldap-hf.c"
189
190 /* Initialize the subtree pointers */
191 static gint ett_ldap = -1;
192 static gint ett_ldap_msg = -1;
193 static gint ett_ldap_sasl_blob = -1;
194 static gint ett_ldap_payload = -1;
195 static gint ett_mscldap_netlogon_flags = -1;
196 static gint ett_mscldap_ntver_flags = -1;
197 static gint ett_mscldap_ipdetails = -1;
198
199 #include "packet-ldap-ett.c"
200
201 static dissector_table_t ldap_name_dissector_table=NULL;
202 static const char *object_identifier_id = NULL; /* LDAP OID */
203
204 static gboolean do_protocolop = FALSE;
205 static gchar    *attr_type = NULL;
206 static gboolean is_binary_attr_type = FALSE;
207 static gboolean ldap_found_in_frame = FALSE;
208
209 #define TCP_PORT_LDAP                   389
210 #define TCP_PORT_LDAPS                  636
211 #define UDP_PORT_CLDAP                  389
212 #define TCP_PORT_GLOBALCAT_LDAP         3268 /* Windows 2000 Global Catalog */
213
214 /* desegmentation of LDAP */
215 static gboolean ldap_desegment = TRUE;
216 static guint global_ldap_tcp_port = TCP_PORT_LDAP;
217 static guint global_ldaps_tcp_port = TCP_PORT_LDAPS;
218 static guint tcp_port = 0;
219 static guint ssl_port = 0;
220
221 static dissector_handle_t gssapi_handle;
222 static dissector_handle_t gssapi_wrap_handle;
223 static dissector_handle_t ntlmssp_handle;
224 static dissector_handle_t spnego_handle;
225 static dissector_handle_t ssl_handle;
226 static dissector_handle_t ldap_handle ;
227
228 static void prefs_register_ldap(void); /* forward declaration for use in preferences registration */
229
230
231 /* different types of rpc calls ontop of ms cldap */
232 #define MSCLDAP_RPC_NETLOGON    1
233
234 /* Message type Choice values */
235 static const value_string ldap_ProtocolOp_choice_vals[] = {
236   {   0, "bindRequest" },
237   {   1, "bindResponse" },
238   {   2, "unbindRequest" },
239   {   3, "searchRequest" },
240   {   4, "searchResEntry" },
241   {   5, "searchResDone" },
242   {   6, "searchResRef" },
243   {   7, "modifyRequest" },
244   {   8, "modifyResponse" },
245   {   9, "addRequest" },
246   {  10, "addResponse" },
247   {  11, "delRequest" },
248   {  12, "delResponse" },
249   {  13, "modDNRequest" },
250   {  14, "modDNResponse" },
251   {  15, "compareRequest" },
252   {  16, "compareResponse" },
253   {  17, "abandonRequest" },
254   {  18, "extendedReq" },
255   {  19, "extendedResp" },
256   {  20, "intermediateResponse" },
257   { 0, NULL }
258 };
259
260 #define LOGON_PRIMARY_QUERY             7
261 #define LOGON_PRIMARY_RESPONSE         12
262 #define LOGON_SAM_LOGON_REQUEST        18
263 #define LOGON_SAM_LOGON_RESPONSE       19
264 #define LOGON_SAM_PAUSE_RESPONSE       20
265 #define LOGON_SAM_USER_UNKNOWN         21
266 #define LOGON_SAM_LOGON_RESPONSE_EX    23
267 #define LOGON_SAM_PAUSE_RESPONSE_EX    24
268 #define LOGON_SAM_USER_UNKNOWN_EX      25
269
270 static const value_string netlogon_opcode_vals[] = {
271         { LOGON_PRIMARY_QUERY,         "LOGON_PRIMARY_QUERY" },
272         { LOGON_PRIMARY_RESPONSE,      "LOGON_PRIMARY_RESPONSE" },
273         { LOGON_SAM_LOGON_REQUEST,     "LOGON_SAM_LOGON_REQUEST" },
274         { LOGON_SAM_LOGON_RESPONSE,    "LOGON_SAM_LOGON_RESPONSE" },
275         { LOGON_SAM_PAUSE_RESPONSE,    "LOGON_SAM_PAUSE_RESPONSE" },
276         { LOGON_SAM_LOGON_RESPONSE_EX, "LOGON_SAM_LOGON_RESPONSE_EX" },
277         { LOGON_SAM_PAUSE_RESPONSE_EX, "LOGON_SAM_PAUSE_RESPONSE_EX" },
278         { LOGON_SAM_USER_UNKNOWN_EX,   "LOGON_SAM_USER_UNKNOWN_EX" },
279         { 0, NULL }
280 };
281
282 /*
283  * Data structure attached to a conversation, giving authentication
284  * information from a bind request.
285  * We keep a linked list of them, so that we can free up all the
286  * authentication mechanism strings.
287  */
288 typedef struct ldap_conv_info_t {
289   struct ldap_conv_info_t *next;
290   guint auth_type;              /* authentication type */
291   char *auth_mech;              /* authentication mechanism */
292   guint32 first_auth_frame;     /* first frame that would use a security layer */
293   GHashTable *unmatched;
294   GHashTable *matched;
295   gboolean is_mscldap;
296   guint32  num_results;
297   gboolean start_tls_pending;
298   guint32  start_tls_frame;
299 } ldap_conv_info_t;
300 static ldap_conv_info_t *ldap_info_items;
301
302 static guint
303 ldap_info_hash_matched(gconstpointer k)
304 {
305   const ldap_call_response_t *key = (const ldap_call_response_t *)k;
306
307   return key->messageId;
308 }
309
310 static gint
311 ldap_info_equal_matched(gconstpointer k1, gconstpointer k2)
312 {
313   const ldap_call_response_t *key1 = (const ldap_call_response_t*)k1;
314   const ldap_call_response_t *key2 = (const ldap_call_response_t*)k2;
315
316   if( key1->req_frame && key2->req_frame && (key1->req_frame!=key2->req_frame) ){
317     return 0;
318   }
319   /* a response may span multiple frames
320   if( key1->rep_frame && key2->rep_frame && (key1->rep_frame!=key2->rep_frame) ){
321     return 0;
322   }
323   */
324
325   return key1->messageId==key2->messageId;
326 }
327
328 static guint
329 ldap_info_hash_unmatched(gconstpointer k)
330 {
331   const ldap_call_response_t *key = (const ldap_call_response_t*)k;
332
333   return key->messageId;
334 }
335
336 static gint
337 ldap_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
338 {
339   const ldap_call_response_t *key1 = (const ldap_call_response_t*)k1;
340   const ldap_call_response_t *key2 = (const ldap_call_response_t*)k2;
341
342   return key1->messageId==key2->messageId;
343 }
344
345
346  /* These are the NtVer flags
347         http://msdn.microsoft.com/en-us/library/cc201035.aspx
348  */
349
350 static const true_false_string tfs_ntver_v1 = {
351         "Client requested version 1 netlogon response",
352         "Version 1 netlogon response not requested"
353 };
354
355 static const true_false_string tfs_ntver_v5 = {
356         "Client requested version 5 netlogon response",
357         "Version 5 netlogon response not requested"
358 };
359 static const true_false_string tfs_ntver_v5ex = {
360         "Client requested version 5 extended netlogon response",
361         "Version 5 extended response not requested"
362 };
363 static const true_false_string tfs_ntver_v5ep = {
364         "Client has requested IP address of the server",
365         "IP address of server not requested"
366 };
367 static const true_false_string tfs_ntver_vcs = {
368         "Client has asked for the closest site information",
369         "Closest site information not requested"
370 };
371 static const true_false_string tfs_ntver_vnt4 = {
372         "Client is requesting server to avoid NT4 emulation",
373         "Only full AD DS requested"
374 };
375 static const true_false_string tfs_ntver_vpdc = {
376         "Client has requested the Primary Domain Controller",
377         "Primary Domain Controller not requested"
378 };
379 static const true_false_string tfs_ntver_vip = {
380         "Client has requested IP details (obsolete)",
381         "IP details not requested (obsolete)"
382 };
383 static const true_false_string tfs_ntver_vl = {
384         "Client indicated that it is the local machine",
385         "Client is not the local machine"
386 };static const true_false_string tfs_ntver_vgc = {
387         "Client has requested a Global Catalog server",
388         "Global Catalog not requested"
389 };
390
391 /* Stuff for generation/handling of fields for custom AttributeValues */
392 typedef struct _attribute_type_t {
393   gchar* attribute_type;
394   gchar* attribute_desc;
395 } attribute_type_t;
396
397 static attribute_type_t* attribute_types = NULL;
398 static guint num_attribute_types = 0;
399
400 static GHashTable* attribute_types_hash = NULL;
401
402 static void
403 attribute_types_update_cb(void *r, const char **err)
404 {
405   attribute_type_t *rec = (attribute_type_t *)r;
406   char c;
407
408   if (rec->attribute_type == NULL) {
409     *err = ep_strdup_printf("Attribute type can't be empty");
410     return;
411   }
412
413   g_strstrip(rec->attribute_type);
414   if (rec->attribute_type[0] == 0) {
415     *err = ep_strdup_printf("Attribute type can't be empty");
416     return;
417   }
418
419   /* Check for invalid characters (to avoid asserting out when
420    * registering the field).
421    */
422   c = proto_check_field_name(rec->attribute_type);
423   if (c) {
424     *err = ep_strdup_printf("Attribute type can't contain '%c'", c);
425     return;
426   }
427
428   *err = NULL;
429 }
430
431 static void *
432 attribute_types_copy_cb(void* n, const void* o, size_t siz _U_)
433 {
434   attribute_type_t* new_rec = (attribute_type_t*)n;
435   const attribute_type_t* old_rec = (const attribute_type_t*)o;
436
437   new_rec->attribute_type = g_strdup(old_rec->attribute_type);
438   new_rec->attribute_desc = g_strdup(old_rec->attribute_desc);
439
440   return new_rec;
441 }
442
443 static void
444 attribute_types_free_cb(void*r)
445 {
446   attribute_type_t* rec = (attribute_type_t*)r;
447
448   if (rec->attribute_type) g_free(rec->attribute_type);
449   if (rec->attribute_desc) g_free(rec->attribute_desc);
450 }
451
452 UAT_CSTRING_CB_DEF(attribute_types, attribute_type, attribute_type_t)
453 UAT_CSTRING_CB_DEF(attribute_types, attribute_desc, attribute_type_t)
454
455 /*
456  *
457  */
458 static gint*
459 get_hf_for_header(char* attribute_type)
460 {
461   gint* hf_id = NULL;
462
463   if (attribute_types_hash) {
464     hf_id = (gint*) g_hash_table_lookup(attribute_types_hash, attribute_type);
465   } else {
466     hf_id = NULL;
467   }
468
469   return hf_id;
470 }
471
472 /*
473  *
474  */
475 static void
476 attribute_types_initialize_cb(void)
477 {
478   static hf_register_info* hf;
479   gint* hf_id;
480   guint i;
481   gchar* attribute_type;
482
483   if (attribute_types_hash) {
484     guint hf_size = g_hash_table_size (attribute_types_hash);
485     /* Unregister all fields */
486     for (i = 0; i < hf_size; i++) {
487       proto_unregister_field (proto_ldap, *(hf[i].p_id));
488
489       g_free (hf[i].p_id);
490       g_free ((char *) hf[i].hfinfo.name);
491       g_free ((char *) hf[i].hfinfo.abbrev);
492       g_free ((char *) hf[i].hfinfo.blurb);
493     }
494     g_hash_table_destroy (attribute_types_hash);
495     g_free (hf);
496     attribute_types_hash = NULL;
497   }
498
499   if (num_attribute_types) {
500     attribute_types_hash = g_hash_table_new(g_str_hash, g_str_equal);
501     hf = g_new0(hf_register_info,num_attribute_types);
502
503     for (i = 0; i < num_attribute_types; i++) {
504       hf_id = g_new(gint,1);
505       *hf_id = -1;
506       attribute_type = g_strdup(attribute_types[i].attribute_type);
507
508       hf[i].p_id = hf_id;
509       hf[i].hfinfo.name = attribute_type;
510       hf[i].hfinfo.abbrev = g_strdup_printf("ldap.AttributeValue.%s", attribute_type);
511       hf[i].hfinfo.type = FT_STRING;
512       hf[i].hfinfo.display = BASE_NONE;
513       hf[i].hfinfo.strings = NULL;
514       hf[i].hfinfo.blurb = g_strdup(attribute_types[i].attribute_desc);
515       hf[i].hfinfo.same_name_prev = NULL;
516       hf[i].hfinfo.same_name_next = NULL;
517
518       g_hash_table_insert(attribute_types_hash, attribute_type, hf_id);
519     }
520
521     proto_register_field_array(proto_ldap, hf, num_attribute_types);
522   }
523 }
524
525 /* MS-ADTS specification, section 7.3.1.1, NETLOGON_NT_VERSION Options Bits */
526 static int dissect_mscldap_ntver_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
527 {
528   guint32 flags;
529   proto_item *item;
530   proto_tree *tree=NULL;
531   guint fields[] = {
532                      hf_mscldap_ntver_flags_v1,
533                      hf_mscldap_ntver_flags_v5,
534                      hf_mscldap_ntver_flags_v5ex,
535                      hf_mscldap_ntver_flags_v5ep,
536                      hf_mscldap_ntver_flags_vcs,
537                      hf_mscldap_ntver_flags_vnt4,
538                      hf_mscldap_ntver_flags_vpdc,
539                      hf_mscldap_ntver_flags_vip,
540                      hf_mscldap_ntver_flags_vl,
541                      hf_mscldap_ntver_flags_vgc,
542                      0 };
543
544   guint  *field;
545   header_field_info *hfi;
546   gboolean one_bit_set = FALSE;
547
548   flags=tvb_get_letohl(tvb, offset);
549   item=proto_tree_add_item(parent_tree, hf_mscldap_ntver_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
550   if(parent_tree){
551     tree = proto_item_add_subtree(item, ett_mscldap_ntver_flags);
552   }
553
554   proto_item_append_text(item, " (");
555
556   for(field = fields; *field; field++) {
557     proto_tree_add_boolean(tree, *field, tvb, offset, 4, flags);
558     hfi = proto_registrar_get_nth(*field);
559
560     if(flags & hfi->bitmask) {
561
562       if(one_bit_set)
563         proto_item_append_text(item, ", ");
564       else
565         one_bit_set = TRUE;
566
567       proto_item_append_text(item, "%s", hfi->name);
568
569     }
570   }
571
572   proto_item_append_text(item, ")");
573
574   offset += 4;
575
576   return offset;
577 }
578
579 /* This string contains the last LDAPString that was decoded */
580 static const char *attributedesc_string=NULL;
581
582 /* This string contains the last AssertionValue that was decoded */
583 static char *ldapvalue_string=NULL;
584
585 /* if the octet string contain all printable ASCII characters, then
586  * display it as a string, othervise just display it in hex.
587  */
588 static int
589 dissect_ldap_AssertionValue(gboolean implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_, proto_tree *tree, int hf_index)
590 {
591         gint8 ber_class;
592         gboolean pc, ind, is_ascii;
593         gint32 tag;
594         guint32 len, i;
595         const guchar *str;
596
597         if(!implicit_tag){
598                 offset=get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
599                 offset=get_ber_length(tvb, offset, &len, &ind);
600         } else {
601                 len=tvb_length_remaining(tvb,offset);
602         }
603
604         if(len==0){
605                 return offset;
606         }
607
608
609         /*
610          * Some special/wellknown attributes in common LDAP (read AD)
611          * are neither ascii strings nor blobs of hex data.
612          * Special case these attributes and decode them more nicely.
613          *
614          * Add more special cases as required to prettify further
615          * (there cant be that many ones that are truly interesting)
616          */
617         if(attributedesc_string && !strncmp("DomainSid", attributedesc_string, 9)){
618                 tvbuff_t *sid_tvb;
619                 char *tmpstr;
620
621                 /* this octet string contains an NT SID */
622                 sid_tvb=tvb_new_subset(tvb, offset, len, len);
623                 dissect_nt_sid(sid_tvb, 0, tree, "SID", &tmpstr, hf_index);
624                 ldapvalue_string=tmpstr;
625
626                 goto finished;
627         } else if ( (len==16) /* GUIDs are always 16 bytes */
628         && (attributedesc_string && !strncmp("DomainGuid", attributedesc_string, 10))) {
629                 guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
630                 e_uuid_t uuid;
631
632                 /* This octet string contained a GUID */
633                 dissect_dcerpc_uuid_t(tvb, offset, actx->pinfo, tree, drep, hf_ldap_guid, &uuid);
634
635                 ldapvalue_string=(char*)ep_alloc(1024);
636                 g_snprintf(ldapvalue_string, 1023, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
637                           uuid.Data1, uuid.Data2, uuid.Data3,
638                           uuid.Data4[0], uuid.Data4[1],
639                           uuid.Data4[2], uuid.Data4[3],
640                           uuid.Data4[4], uuid.Data4[5],
641                           uuid.Data4[6], uuid.Data4[7]);
642
643                 goto finished;
644         } else if (attributedesc_string && !strncmp("NtVer", attributedesc_string, 5)){
645                 guint32 flags;
646
647                 len = 0;
648                 /* get flag value to populate ldapvalue_string */
649                 flags=tvb_get_letohl(tvb, offset);
650
651                 ldapvalue_string=(char*)ep_alloc(1024);
652                 g_snprintf(ldapvalue_string, 1023, "0x%08x",flags);
653
654                 /* populate bitmask subtree */
655                 offset = dissect_mscldap_ntver_flags(tree, tvb, offset);
656
657                 goto finished;
658
659
660         }
661
662         /*
663          * It was not one of our "wellknown" attributes so make the best
664          * we can and just try to see if it is an ascii string or if it
665          * is a binary blob.
666          *
667          * XXX - should we support reading RFC 2252-style schemas
668          * for LDAP, and using that to determine how to display
669          * attribute values and assertion values?
670          *
671          * -- I dont think there are full schemas available that describe the
672          *  interesting cases i.e. AD -- ronnie
673          */
674         str=tvb_get_ptr(tvb, offset, len);
675         is_ascii=TRUE;
676         for(i=0;i<len;i++){
677                 if(!isascii(str[i]) || !isprint(str[i])){
678                         is_ascii=FALSE;
679                         break;
680                 }
681         }
682
683         /* convert the string into a printable string */
684         if(is_ascii){
685                 ldapvalue_string=ep_strndup(str, len);
686         } else {
687                 ldapvalue_string=(char*)ep_alloc(3*len);
688                 for(i=0;i<len;i++){
689                         g_snprintf(ldapvalue_string+i*3,3,"%02x",str[i]&0xff);
690                         ldapvalue_string[3*i+2]=':';
691                 }
692                 ldapvalue_string[3*len-1]=0;
693         }
694
695         proto_tree_add_string(tree, hf_index, tvb, offset, len, ldapvalue_string);
696
697
698 finished:
699         offset+=len;
700         return offset;
701 }
702
703 /* This string contains the last Filter item that was decoded */
704 static const char *Filter_string=NULL;
705 static const char *and_filter_string=NULL;
706 static const char *or_filter_string=NULL;
707 static const char *substring_value=NULL;
708 static const char *substring_item_init=NULL;
709 static const char *substring_item_any=NULL;
710 static const char *substring_item_final=NULL;
711 static const char *matching_rule_string=NULL;
712 static gboolean matching_rule_dnattr=FALSE;
713
714 #define MAX_FILTER_LEN 4096
715 static gint Filter_length;
716
717 #define MAX_FILTER_ELEMENTS 200
718 static gint Filter_elements;
719
720 /* Global variables */
721 static gint MessageID =-1;
722 static gint ProtocolOp = -1;
723 static gint result = 0;
724 static proto_item *ldm_tree = NULL; /* item to add text to */
725
726 static void ldap_do_protocolop(packet_info *pinfo)
727 {
728   const gchar* valstr;
729
730   if (do_protocolop)  {
731
732     valstr = val_to_str(ProtocolOp, ldap_ProtocolOp_choice_vals, "Unknown (%%u)");
733
734     col_append_fstr(pinfo->cinfo, COL_INFO, "%s(%u) ", valstr, MessageID);
735
736     if(ldm_tree)
737       proto_item_append_text(ldm_tree, " %s(%d)", valstr, MessageID);
738
739     do_protocolop = FALSE;
740
741   }
742 }
743
744 static ldap_call_response_t *
745 ldap_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint messageId, guint protocolOpTag)
746 {
747   ldap_call_response_t lcr, *lcrp=NULL;
748   ldap_conv_info_t *ldap_info = (ldap_conv_info_t *)pinfo->private_data;
749
750   /* first see if we have already matched this */
751
752       lcr.messageId=messageId;
753       switch(protocolOpTag){
754         case LDAP_REQ_BIND:
755         case LDAP_REQ_SEARCH:
756         case LDAP_REQ_MODIFY:
757         case LDAP_REQ_ADD:
758         case LDAP_REQ_DELETE:
759         case LDAP_REQ_MODRDN:
760         case LDAP_REQ_COMPARE:
761         case LDAP_REQ_EXTENDED:
762           lcr.is_request=TRUE;
763           lcr.req_frame=pinfo->fd->num;
764           lcr.rep_frame=0;
765           break;
766         case LDAP_RES_BIND:
767         case LDAP_RES_SEARCH_ENTRY:
768         case LDAP_RES_SEARCH_REF:
769         case LDAP_RES_SEARCH_RESULT:
770         case LDAP_RES_MODIFY:
771         case LDAP_RES_ADD:
772         case LDAP_RES_DELETE:
773         case LDAP_RES_MODRDN:
774         case LDAP_RES_COMPARE:
775         case LDAP_RES_EXTENDED:
776         case LDAP_RES_INTERMEDIATE:
777           lcr.is_request=FALSE;
778           lcr.req_frame=0;
779           lcr.rep_frame=pinfo->fd->num;
780           break;
781       }
782       lcrp=(ldap_call_response_t *)g_hash_table_lookup(ldap_info->matched, &lcr);
783
784       if(lcrp){
785
786         lcrp->is_request=lcr.is_request;
787
788       } else {
789
790                   /* we haven't found a match - try and match it up */
791
792   switch(protocolOpTag){
793       case LDAP_REQ_BIND:
794       case LDAP_REQ_SEARCH:
795       case LDAP_REQ_MODIFY:
796       case LDAP_REQ_ADD:
797       case LDAP_REQ_DELETE:
798       case LDAP_REQ_MODRDN:
799       case LDAP_REQ_COMPARE:
800       case LDAP_REQ_EXTENDED:
801
802                 /* this a a request - add it to the unmatched list */
803
804         /* check that we dont already have one of those in the
805            unmatched list and if so remove it */
806
807         lcr.messageId=messageId;
808         lcrp=(ldap_call_response_t *)g_hash_table_lookup(ldap_info->unmatched, &lcr);
809         if(lcrp){
810           g_hash_table_remove(ldap_info->unmatched, lcrp);
811         }
812         /* if we cant reuse the old one, grab a new chunk */
813         if(!lcrp){
814           lcrp=se_new(ldap_call_response_t);
815         }
816         lcrp->messageId=messageId;
817         lcrp->req_frame=pinfo->fd->num;
818         lcrp->req_time=pinfo->fd->abs_ts;
819         lcrp->rep_frame=0;
820         lcrp->protocolOpTag=protocolOpTag;
821         lcrp->is_request=TRUE;
822         g_hash_table_insert(ldap_info->unmatched, lcrp, lcrp);
823         return NULL;
824         break;
825       case LDAP_RES_BIND:
826       case LDAP_RES_SEARCH_ENTRY:
827       case LDAP_RES_SEARCH_REF:
828       case LDAP_RES_SEARCH_RESULT:
829       case LDAP_RES_MODIFY:
830       case LDAP_RES_ADD:
831       case LDAP_RES_DELETE:
832       case LDAP_RES_MODRDN:
833       case LDAP_RES_COMPARE:
834       case LDAP_RES_EXTENDED:
835       case LDAP_RES_INTERMEDIATE:
836
837                 /* this is a result - it should be in our unmatched list */
838
839         lcr.messageId=messageId;
840         lcrp=(ldap_call_response_t *)g_hash_table_lookup(ldap_info->unmatched, &lcr);
841
842         if(lcrp){
843
844           if(!lcrp->rep_frame){
845             g_hash_table_remove(ldap_info->unmatched, lcrp);
846             lcrp->rep_frame=pinfo->fd->num;
847             lcrp->is_request=FALSE;
848             g_hash_table_insert(ldap_info->matched, lcrp, lcrp);
849           }
850         }
851
852         break;
853           }
854
855         }
856     /* we have found a match */
857
858     if(lcrp){
859       proto_item *it;
860
861       if(lcrp->is_request){
862         it=proto_tree_add_uint(tree, hf_ldap_response_in, tvb, 0, 0, lcrp->rep_frame);
863         PROTO_ITEM_SET_GENERATED(it);
864       } else {
865         nstime_t ns;
866         it=proto_tree_add_uint(tree, hf_ldap_response_to, tvb, 0, 0, lcrp->req_frame);
867         PROTO_ITEM_SET_GENERATED(it);
868         nstime_delta(&ns, &pinfo->fd->abs_ts, &lcrp->req_time);
869         it=proto_tree_add_time(tree, hf_ldap_time, tvb, 0, 0, &ns);
870         PROTO_ITEM_SET_GENERATED(it);
871       }
872     }
873
874     return lcrp;
875 }
876
877 #include "packet-ldap-fn.c"
878
879 static void
880 dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo,
881                      proto_tree *tree, ldap_conv_info_t *ldap_info,
882                      gboolean is_mscldap)
883 {
884   int offset = 0;
885   guint length_remaining;
886   guint msg_len = 0;
887   int messageOffset = 0;
888   guint headerLength = 0;
889   guint length = 0;
890   tvbuff_t *msg_tvb = NULL;
891   gint8 ber_class;
892   gboolean pc, ind = 0;
893   gint32 ber_tag;
894
895   attributedesc_string=NULL;
896
897
898 one_more_pdu:
899
900     length_remaining = tvb_ensure_length_remaining(tvb, offset);
901
902     if (length_remaining < 6) return;
903
904     /*
905      * OK, try to read the "Sequence Of" header; this gets the total
906      * length of the LDAP message.
907      */
908         messageOffset = get_ber_identifier(tvb, offset, &ber_class, &pc, &ber_tag);
909         messageOffset = get_ber_length(tvb, messageOffset, &msg_len, &ind);
910
911     /* sanity check */
912     if((msg_len<4) || (msg_len>10000000)) return;
913
914     if ( (ber_class==BER_CLASS_UNI) && (ber_tag==BER_UNI_TAG_SEQUENCE) ) {
915         /*
916          * Add the length of the "Sequence Of" header to the message
917          * length.
918          */
919         headerLength = messageOffset - offset;
920         msg_len += headerLength;
921         if (msg_len < headerLength) {
922             /*
923              * The message length was probably so large that the total length
924              * overflowed.
925              *
926              * Report this as an error.
927              */
928             show_reported_bounds_error(tvb, pinfo, tree);
929             return;
930         }
931     } else {
932         /*
933          * We couldn't parse the header; just make it the amount of data
934          * remaining in the tvbuff, so we'll give up on this segment
935          * after attempting to parse the message - there's nothing more
936          * we can do.  "dissect_ldap_message()" will display the error.
937          */
938         msg_len = length_remaining;
939     }
940
941     /*
942      * Construct a tvbuff containing the amount of the payload we have
943      * available.  Make its reported length the amount of data in the
944      * LDAP message.
945      *
946      * XXX - if reassembly isn't enabled. the subdissector will throw a
947      * BoundsError exception, rather than a ReportedBoundsError exception.
948      * We really want a tvbuff where the length is "length", the reported
949      * length is "plen", and the "if the snapshot length were infinite"
950      * length is the minimum of the reported length of the tvbuff handed
951      * to us and "plen", with a new type of exception thrown if the offset
952      * is within the reported length but beyond that third length, with
953      * that exception getting the "Unreassembled Packet" error.
954      */
955     length = length_remaining;
956     if (length > msg_len) length = msg_len;
957     msg_tvb = tvb_new_subset(tvb, offset, length, msg_len);
958
959     /*
960      * Now dissect the LDAP message.
961      */
962     ldap_info->is_mscldap = is_mscldap;
963     pinfo->private_data = ldap_info;
964     dissect_LDAPMessage_PDU(msg_tvb, pinfo, tree);
965
966     offset += msg_len;
967
968     /* If this was a sasl blob there might be another PDU following in the
969      * same blob
970      */
971     if(tvb_length_remaining(tvb, offset)>=6){
972         tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), -1);
973         offset = 0;
974
975         goto one_more_pdu;
976     }
977
978 }
979
980 static void
981 ldap_frame_end(void)
982 {
983    ldap_found_in_frame = FALSE;
984    attr_type = NULL;
985    ldapvalue_string = NULL;
986 /* ? */
987    attributedesc_string = NULL;
988    Filter_string = NULL;
989    and_filter_string = NULL;
990    object_identifier_id = NULL;
991    or_filter_string = NULL;
992
993    substring_item_any = NULL;
994    substring_item_final = NULL;
995    substring_item_init = NULL;
996    substring_value = NULL;
997
998    ldm_tree = NULL;
999
1000    Filter_elements = 0;
1001    Filter_length = 0;
1002    do_protocolop = FALSE;
1003    result = 0;
1004
1005 /* seems to be ok, but reset just in case */
1006    matching_rule_string = NULL;
1007 }
1008
1009 static void
1010         dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_mscldap)
1011 {
1012         int offset = 0;
1013         conversation_t *conversation;
1014         gboolean doing_sasl_security = FALSE;
1015         guint length_remaining;
1016         ldap_conv_info_t *ldap_info = NULL;
1017         proto_item *ldap_item = NULL;
1018         proto_tree *ldap_tree = NULL;
1019
1020         ldm_tree = NULL;
1021
1022         conversation = find_or_create_conversation(pinfo);
1023
1024         /*
1025         * Do we already have a type and mechanism?
1026         */
1027         ldap_info = (ldap_conv_info_t *)conversation_get_proto_data(conversation, proto_ldap);
1028         if (ldap_info == NULL) {
1029                 /* No.  Attach that information to the conversation, and add
1030                 * it to the list of information structures.
1031                 */
1032                 ldap_info = g_new0(ldap_conv_info_t,1);
1033                 ldap_info->matched=g_hash_table_new(ldap_info_hash_matched, ldap_info_equal_matched);
1034                 ldap_info->unmatched=g_hash_table_new(ldap_info_hash_unmatched, ldap_info_equal_unmatched);
1035
1036                 conversation_add_proto_data(conversation, proto_ldap, ldap_info);
1037
1038                 ldap_info->next = ldap_info_items;
1039                 ldap_info_items = ldap_info;
1040
1041         }
1042
1043         switch (ldap_info->auth_type) {
1044         case LDAP_AUTH_SASL:
1045                 /*
1046                 * It's SASL; are we using a security layer?
1047                 */
1048                 if (ldap_info->first_auth_frame != 0 &&
1049                         pinfo->fd->num >= ldap_info->first_auth_frame) {
1050                                 doing_sasl_security = TRUE;     /* yes */
1051                 }
1052         }
1053
1054         length_remaining = tvb_ensure_length_remaining(tvb, offset);
1055
1056         /* It might still be a packet containing a SASL security layer
1057         * but its just that we never saw the BIND packet.
1058         * check if it looks like it could be a SASL blob here
1059         * and in that case just assume it is GSS-SPNEGO
1060         */
1061         if(!doing_sasl_security && (tvb_bytes_exist(tvb, offset, 5))
1062                 &&(tvb_get_ntohl(tvb, offset)<=(guint)(tvb_reported_length_remaining(tvb, offset)-4))
1063                 &&(tvb_get_guint8(tvb, offset+4)==0x60) ){
1064                         ldap_info->auth_type=LDAP_AUTH_SASL;
1065                         ldap_info->first_auth_frame=pinfo->fd->num;
1066                         ldap_info->auth_mech=g_strdup("GSS-SPNEGO");
1067                         doing_sasl_security=TRUE;
1068         }
1069
1070         /*
1071         * This is the first PDU, set the Protocol column and clear the
1072         * Info column.
1073         */
1074         col_set_str(pinfo->cinfo, COL_PROTOCOL, pinfo->current_proto);
1075
1076         if(ldap_found_in_frame) {
1077                 /* we have already dissected an ldap PDU in this frame - add a separator and set a fence */
1078                 col_append_str(pinfo->cinfo, COL_INFO, " | ");
1079                 col_set_fence(pinfo->cinfo, COL_INFO);
1080         } else {
1081                 col_clear(pinfo->cinfo, COL_INFO);
1082                 register_frame_end_routine (ldap_frame_end);
1083                 ldap_found_in_frame = TRUE;
1084         }
1085
1086         ldap_item = proto_tree_add_item(tree, is_mscldap?proto_cldap:proto_ldap, tvb, 0, -1, ENC_NA);
1087         ldap_tree = proto_item_add_subtree(ldap_item, ett_ldap);
1088
1089         /*
1090         * Might we be doing a SASL security layer and, if so, *are* we doing
1091         * one?
1092         *
1093         * Just because we've seen a bind reply for SASL, that doesn't mean
1094         * that we're using a SASL security layer; I've seen captures in
1095         * which some SASL negotiations lead to a security layer being used
1096         * and other negotiations don't, and it's not obvious what's different
1097         * in the two negotiations.  Therefore, we assume that if the first
1098         * byte is 0, it's a length for a SASL security layer (that way, we
1099         * never reassemble more than 16 megabytes, protecting us from
1100         * chewing up *too* much memory), and otherwise that it's an LDAP
1101         * message (actually, if it's an LDAP message it should begin with 0x30,
1102         * but we want to parse garbage as LDAP messages rather than really
1103         * huge lengths).
1104         */
1105
1106         if (doing_sasl_security && tvb_get_guint8(tvb, offset) == 0) {
1107                 proto_item *sasl_item = NULL;
1108                 proto_tree *sasl_tree = NULL;
1109                 tvbuff_t *sasl_tvb;
1110                 guint sasl_len, sasl_msg_len, length;
1111                 /*
1112                 * Yes.  The frame begins with a 4-byte big-endian length.
1113                 * And we know we have at least 6 bytes
1114                 */
1115
1116                 /*
1117                 * Get the SASL length, which is the length of data in the buffer
1118                 * following the length (i.e., it's 4 less than the total length).
1119                 *
1120                 * XXX - do we need to reassemble buffers?  For now, we
1121                 * assume that each LDAP message is entirely contained within
1122                 * a buffer.
1123                 */
1124                 sasl_len = tvb_get_ntohl(tvb, offset);
1125                 sasl_msg_len = sasl_len + 4;
1126                 if (sasl_msg_len < 4) {
1127                         /*
1128                         * The message length was probably so large that the total length
1129                         * overflowed.
1130                         *
1131                         * Report this as an error.
1132                         */
1133                         show_reported_bounds_error(tvb, pinfo, tree);
1134                         return;
1135                 }
1136
1137                 /*
1138                 * Construct a tvbuff containing the amount of the payload we have
1139                 * available.  Make its reported length the amount of data in the PDU.
1140                 *
1141                 * XXX - if reassembly isn't enabled. the subdissector will throw a
1142                 * BoundsError exception, rather than a ReportedBoundsError exception.
1143                 * We really want a tvbuff where the length is "length", the reported
1144                 * length is "plen", and the "if the snapshot length were infinite"
1145                 * length is the minimum of the reported length of the tvbuff handed
1146                 * to us and "plen", with a new type of exception thrown if the offset
1147                 * is within the reported length but beyond that third length, with
1148                 * that exception getting the "Unreassembled Packet" error.
1149                 */
1150                 length = length_remaining;
1151                 if (length > sasl_msg_len) length = sasl_msg_len;
1152                 sasl_tvb = tvb_new_subset(tvb, offset, length, sasl_msg_len);
1153
1154                 if (ldap_tree) {
1155                         proto_tree_add_uint(ldap_tree, hf_ldap_sasl_buffer_length, sasl_tvb, 0, 4,
1156                                 sasl_len);
1157
1158                         sasl_item = proto_tree_add_text(ldap_tree, sasl_tvb, 0,  sasl_msg_len, "SASL Buffer");
1159                         sasl_tree = proto_item_add_subtree(sasl_item, ett_ldap_sasl_blob);
1160                 }
1161
1162                 if (ldap_info->auth_mech != NULL &&
1163                         ((strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) ||
1164                         /* auth_mech may have been set from the bind */
1165                         (strcmp(ldap_info->auth_mech, "GSSAPI") == 0))) {
1166                                 tvbuff_t *gssapi_tvb, *plain_tvb = NULL, *decr_tvb= NULL;
1167                                 int ver_len;
1168                                 int tmp_length;
1169
1170                                 /*
1171                                 * This is GSS-API (using SPNEGO, but we should be done with
1172                                 * the negotiation by now).
1173                                 *
1174                                 * Dissect the GSS_Wrap() token; it'll return the length of
1175                                 * the token, from which we compute the offset in the tvbuff at
1176                                 * which the plaintext data, i.e. the LDAP message, begins.
1177                                 */
1178                                 tmp_length = tvb_length_remaining(sasl_tvb, 4);
1179                                 if ((guint)tmp_length > sasl_len)
1180                                         tmp_length = sasl_len;
1181                                 gssapi_tvb = tvb_new_subset(sasl_tvb, 4, tmp_length, sasl_len);
1182
1183                                 /* Attempt decryption of the GSSAPI wrapped data if possible */
1184                                 pinfo->decrypt_gssapi_tvb=DECRYPT_GSSAPI_NORMAL;
1185                                 pinfo->gssapi_wrap_tvb=NULL;
1186                                 pinfo->gssapi_encrypted_tvb=NULL;
1187                                 pinfo->gssapi_decrypted_tvb=NULL;
1188                                 ver_len = call_dissector(gssapi_wrap_handle, gssapi_tvb, pinfo, sasl_tree);
1189                                 /* if we could unwrap, do a tvb shuffle */
1190                                 if(pinfo->gssapi_decrypted_tvb){
1191                                         decr_tvb=pinfo->gssapi_decrypted_tvb;
1192                                 }
1193                                 /* tidy up */
1194                                 pinfo->decrypt_gssapi_tvb=0;
1195                                 pinfo->gssapi_wrap_tvb=NULL;
1196                                 pinfo->gssapi_encrypted_tvb=NULL;
1197                                 pinfo->gssapi_decrypted_tvb=NULL;
1198
1199                                 /*
1200                                 * if len is 0 it probably mean that we got a PDU that is not
1201                                 * aligned to the start of the segment.
1202                                 */
1203                                 if(ver_len==0){
1204                                         return;
1205                                 }
1206
1207                                 /*
1208                                 * if we don't have unwrapped data,
1209                                 * see if the wrapping involved encryption of the
1210                                 * data; if not, just use the plaintext data.
1211                                 */
1212                                 if (!decr_tvb) {
1213                                         if(!pinfo->gssapi_data_encrypted){
1214                                                 plain_tvb = tvb_new_subset_remaining(gssapi_tvb,  ver_len);
1215                                         }
1216                                 }
1217
1218                                 if (decr_tvb) {
1219                                         proto_item *enc_item = NULL;
1220                                         proto_tree *enc_tree = NULL;
1221
1222                                         /*
1223                                         * The LDAP message was encrypted in the packet, and has
1224                                         * been decrypted; dissect the decrypted LDAP message.
1225                                         */
1226                                         col_set_str(pinfo->cinfo, COL_INFO, "SASL GSS-API Privacy (decrypted): ");
1227
1228                                         if (sasl_tree) {
1229                                                 enc_item = proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
1230                                                         "GSS-API Encrypted payload (%d byte%s)",
1231                                                         sasl_len - ver_len,
1232                                                         plurality(sasl_len - ver_len, "", "s"));
1233                                                 enc_tree = proto_item_add_subtree(enc_item, ett_ldap_payload);
1234                                         }
1235                                         dissect_ldap_payload(decr_tvb, pinfo, enc_tree, ldap_info, is_mscldap);
1236                                 } else if (plain_tvb) {
1237                                         proto_item *plain_item = NULL;
1238                                         proto_tree *plain_tree = NULL;
1239
1240                                         /*
1241                                         * The LDAP message wasn't encrypted in the packet;
1242                                         * dissect the plain LDAP message.
1243                                         */
1244                                         col_set_str(pinfo->cinfo, COL_INFO, "SASL GSS-API Integrity: ");
1245
1246                                         if (sasl_tree) {
1247                                                 plain_item = proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
1248                                                         "GSS-API payload (%d byte%s)",
1249                                                         sasl_len - ver_len,
1250                                                         plurality(sasl_len - ver_len, "", "s"));
1251                                                 plain_tree = proto_item_add_subtree(plain_item, ett_ldap_payload);
1252                                         }
1253
1254                                         dissect_ldap_payload(plain_tvb, pinfo, plain_tree, ldap_info, is_mscldap);
1255                                 } else {
1256                                         /*
1257                                         * The LDAP message was encrypted in the packet, and was
1258                                         * not decrypted; just show it as encrypted data.
1259                                         */
1260                                         col_add_fstr(pinfo->cinfo, COL_INFO, "SASL GSS-API Privacy: payload (%d byte%s)",
1261                                                 sasl_len - ver_len,
1262                                                 plurality(sasl_len - ver_len, "", "s"));
1263
1264                                         if (sasl_tree) {
1265                                                 proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
1266                                                         "GSS-API Encrypted payload (%d byte%s)",
1267                                                         sasl_len - ver_len,
1268                                                         plurality(sasl_len - ver_len, "", "s"));
1269                                         }
1270                                 }
1271                 }
1272         } else {
1273                 /* plain LDAP, so dissect the payload */
1274                 dissect_ldap_payload(tvb, pinfo, ldap_tree, ldap_info, is_mscldap);
1275         }
1276 }
1277
1278 /*
1279  * prepend_dot is no longer used, but is being left in place in order to
1280  * maintain ABI compatibility.
1281  */
1282 int dissect_mscldap_string(tvbuff_t *tvb, int offset, char *str, int max_len, gboolean prepend_dot _U_)
1283 {
1284   int compr_len;
1285   const guchar *name;
1286
1287   /* The name data MUST start at offset 0 of the tvb */
1288   compr_len = expand_dns_name(tvb, offset, max_len, 0, &name);
1289   g_strlcpy(str, name, max_len);
1290   return offset + compr_len;
1291 }
1292
1293
1294 /* These are the cldap DC flags
1295    http://msdn.microsoft.com/en-us/library/cc201036.aspx
1296  */
1297 static const true_false_string tfs_ads_pdc = {
1298         "This is a PDC",
1299         "This is NOT a pdc"
1300 };
1301 static const true_false_string tfs_ads_gc = {
1302         "This is a GLOBAL CATALOGUE of forest",
1303         "This is NOT a global catalog of forest"
1304 };
1305 static const true_false_string tfs_ads_ldap = {
1306         "This is an LDAP server",
1307         "This is NOT an ldap server"
1308 };
1309 static const true_false_string tfs_ads_ds = {
1310         "This dc supports DS",
1311         "This dc does NOT support ds"
1312 };
1313 static const true_false_string tfs_ads_kdc = {
1314         "This is a KDC (kerberos)",
1315         "This is NOT a kdc (kerberos)"
1316 };
1317 static const true_false_string tfs_ads_timeserv = {
1318         "This dc is running TIME SERVICES (ntp)",
1319         "This dc is NOT running time services (ntp)"
1320 };
1321 static const true_false_string tfs_ads_closest = {
1322         "This server is in the same site as the client",
1323         "This server is NOT in the same site as the client"
1324 };
1325 static const true_false_string tfs_ads_writable = {
1326         "This dc is WRITABLE",
1327         "This dc is NOT writable"
1328 };
1329 static const true_false_string tfs_ads_good_timeserv = {
1330         "This dc has a GOOD TIME SERVICE (i.e. hardware clock)",
1331         "This dc does NOT have a good time service (i.e. no hardware clock)"
1332 };
1333 static const true_false_string tfs_ads_ndnc = {
1334         "Domain is NON-DOMAIN NC serviced by ldap server",
1335         "Domain is NOT non-domain nc serviced by ldap server"
1336 };
1337 static const true_false_string tfs_ads_rodc = {
1338         "Domain controller is a Windows 2008 RODC",
1339         "Domain controller is not a Windows 2008 RODC"
1340 };
1341 static const true_false_string tfs_ads_wdc = {
1342         "Domain controller is a Windows 2008 writable NC",
1343         "Domain controller is not a Windows 2008 writable NC"
1344 };
1345 static const true_false_string tfs_ads_dns = {
1346         "Server name is in DNS format (Windows 2008)",
1347         "Server name is not in DNS format (Windows 2008)"
1348 };
1349 static const true_false_string tfs_ads_dnc = {
1350         "The NC is the default NC (Windows 2008)",
1351         "The NC is not the default NC (Windows 2008)"
1352 };
1353 static const true_false_string tfs_ads_fnc = {
1354         "The NC is the default forest NC(Windows 2008)",
1355         "The NC is not the default forest NC (Windows 2008)"
1356 };
1357 static int dissect_mscldap_netlogon_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
1358 {
1359   guint32 flags;
1360   proto_item *item;
1361   proto_tree *tree=NULL;
1362   guint fields[] = {
1363              hf_mscldap_netlogon_flags_fnc,
1364              hf_mscldap_netlogon_flags_dnc,
1365              hf_mscldap_netlogon_flags_dns,
1366              hf_mscldap_netlogon_flags_wdc,
1367              hf_mscldap_netlogon_flags_rodc,
1368              hf_mscldap_netlogon_flags_ndnc,
1369              hf_mscldap_netlogon_flags_good_timeserv,
1370              hf_mscldap_netlogon_flags_writable,
1371              hf_mscldap_netlogon_flags_closest,
1372              hf_mscldap_netlogon_flags_timeserv,
1373              hf_mscldap_netlogon_flags_kdc,
1374              hf_mscldap_netlogon_flags_ds,
1375              hf_mscldap_netlogon_flags_ldap,
1376              hf_mscldap_netlogon_flags_gc,
1377              hf_mscldap_netlogon_flags_pdc,
1378              0 };
1379   guint  *field;
1380   header_field_info *hfi;
1381   gboolean one_bit_set = FALSE;
1382
1383   flags=tvb_get_letohl(tvb, offset);
1384   item=proto_tree_add_item(parent_tree, hf_mscldap_netlogon_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1385   if(parent_tree){
1386     tree = proto_item_add_subtree(item, ett_mscldap_netlogon_flags);
1387   }
1388
1389   proto_item_append_text(item, " (");
1390
1391   for(field = fields; *field; field++) {
1392     proto_tree_add_boolean(tree, *field, tvb, offset, 4, flags);
1393     hfi = proto_registrar_get_nth(*field);
1394
1395     if(flags & hfi->bitmask) {
1396
1397       if(one_bit_set)
1398         proto_item_append_text(item, ", ");
1399       else
1400         one_bit_set = TRUE;
1401
1402       proto_item_append_text(item, "%s", hfi->name);
1403
1404     }
1405   }
1406
1407   proto_item_append_text(item, ")");
1408
1409   offset += 4;
1410
1411   return offset;
1412 }
1413
1414 static void dissect_NetLogon_PDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1415 {
1416   int old_offset, offset=0;
1417   char str[256];
1418   guint16 itype;
1419   guint16 len;
1420   guint32 version;
1421   const char *fn;
1422   int fn_len;
1423   guint16 bc;
1424   proto_item *item;
1425
1426   ldm_tree = NULL;
1427
1428
1429   /* Get the length of the buffer */
1430   len=tvb_length_remaining(tvb,offset);
1431
1432   /* check the len if it is to small return */
1433   if (len < 10) return;
1434
1435   /* Type */
1436   proto_tree_add_item(tree, hf_mscldap_netlogon_opcode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1437   itype = tvb_get_letohs(tvb, offset);
1438   offset += 2;
1439
1440   /* get the version number from the end of the buffer, as the
1441      length is variable and the version determines what fields
1442          need to be decoded */
1443
1444   version = tvb_get_letohl(tvb,len-8);
1445
1446   switch(itype){
1447
1448                 case LOGON_SAM_LOGON_RESPONSE:
1449                         bc = tvb_length_remaining(tvb, offset);
1450                         /* logon server name */
1451                         fn = get_unicode_or_ascii_string(tvb,&offset,TRUE,&fn_len,FALSE,FALSE,&bc);
1452                         proto_tree_add_string(tree, hf_mscldap_nb_hostname, tvb,offset, fn_len, fn);
1453                         offset +=fn_len;
1454
1455                         /* username */
1456                         fn = get_unicode_or_ascii_string(tvb,&offset,TRUE,&fn_len,FALSE,FALSE,&bc);
1457                         proto_tree_add_string(tree, hf_mscldap_username, tvb,offset, fn_len, fn);
1458                         offset +=fn_len;
1459
1460                         /* domain name */
1461                         fn = get_unicode_or_ascii_string(tvb,&offset,TRUE,&fn_len,FALSE,FALSE,&bc);
1462                         proto_tree_add_string(tree, hf_mscldap_nb_domain, tvb,offset, fn_len, fn);
1463                         offset +=fn_len;
1464
1465                         /* include the extra version 5 fields */
1466                         if ((version & NETLOGON_NT_VERSION_5) == NETLOGON_NT_VERSION_5){
1467
1468                                 /* domain guid */
1469                                 proto_tree_add_item(tree, hf_mscldap_domain_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
1470                                 offset += 16;
1471
1472                                 /* domain guid part 2
1473                                    there is another 16 byte guid but this is alway zero, so we will skip it */
1474                                 offset += 16;
1475
1476                                 /* Forest */
1477                                 old_offset=offset;
1478                                 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1479                                 proto_tree_add_string(tree, hf_mscldap_forest, tvb, old_offset, offset-old_offset, str);
1480
1481                                 /* Domain */
1482                                 old_offset=offset;
1483                                 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1484                                 proto_tree_add_string(tree, hf_mscldap_domain, tvb, old_offset, offset-old_offset, str);
1485
1486                                 /* Hostname */
1487                                 old_offset=offset;
1488                                 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1489                                 proto_tree_add_string(tree, hf_mscldap_hostname, tvb, old_offset, offset-old_offset, str);
1490
1491                                 /* DC IP Address */
1492                                 proto_tree_add_ipv4(tree, hf_mscldap_netlogon_ipaddress, tvb, offset, 4, tvb_get_ntohl(tvb,offset));
1493                                 offset += 4;
1494
1495                                 /* Flags */
1496                                 offset = dissect_mscldap_netlogon_flags(tree, tvb, offset);
1497
1498                         }
1499
1500                         break;
1501
1502                 case LOGON_SAM_LOGON_RESPONSE_EX:
1503                         /* MS-ADTS 7.3.1.9 */
1504                         offset += 2; /* Skip over "Sbz" field (MUST be set to 0) */
1505
1506                         /* Flags */
1507                         offset = dissect_mscldap_netlogon_flags(tree, tvb, offset);
1508
1509                         /* Domain GUID */
1510                         proto_tree_add_item(tree, hf_mscldap_domain_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
1511                         offset += 16;
1512
1513                         /* Forest */
1514                         old_offset=offset;
1515                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1516                         proto_tree_add_string(tree, hf_mscldap_forest, tvb, old_offset, offset-old_offset, str);
1517
1518                         /* Domain */
1519                         old_offset=offset;
1520                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1521                         proto_tree_add_string(tree, hf_mscldap_domain, tvb, old_offset, offset-old_offset, str);
1522
1523                         /* Hostname */
1524                         old_offset=offset;
1525                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1526                         proto_tree_add_string(tree, hf_mscldap_hostname, tvb, old_offset, offset-old_offset, str);
1527
1528                         /* NetBIOS Domain */
1529                         old_offset=offset;
1530                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1531                         proto_tree_add_string(tree, hf_mscldap_nb_domain, tvb, old_offset, offset-old_offset, str);
1532
1533                         /* NetBIOS Hostname */
1534                         old_offset=offset;
1535                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1536                         proto_tree_add_string(tree, hf_mscldap_nb_hostname, tvb, old_offset, offset-old_offset, str);
1537
1538                         /* User */
1539                         old_offset=offset;
1540                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1541                         proto_tree_add_string(tree, hf_mscldap_username, tvb, old_offset, offset-old_offset, str);
1542
1543                         /* Server Site */
1544                         old_offset=offset;
1545                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1546                         proto_tree_add_string(tree, hf_mscldap_sitename, tvb, old_offset, offset-old_offset, str);
1547
1548                         /* Client Site */
1549                         old_offset=offset;
1550                         offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1551                         proto_tree_add_string(tree, hf_mscldap_clientsitename, tvb, old_offset, offset-old_offset, str);
1552
1553                         /* include the extra fields for version 5 with IP s */
1554                         if ((version & NETLOGON_NT_VERSION_5EX_WITH_IP) == NETLOGON_NT_VERSION_5EX_WITH_IP){
1555                                 /* The ip address is returned as a sockaddr_in structure
1556                                  *
1557                                  *  This section may need to be updated if the base Windows APIs
1558                                  *  are changed to support ipv6, which currently is not the case.
1559                                  *
1560                                  *  The desector assumes the length is based on ipv4 and
1561                                  *  ignores the length
1562                                  */
1563
1564                                 /* skip the length of the sockaddr_in */
1565
1566                                 offset +=1;
1567
1568                                 /* add IP address and desect the sockaddr_in structure */
1569
1570                                 old_offset = offset + 4;
1571                                 item = proto_tree_add_ipv4(tree, hf_mscldap_netlogon_ipaddress, tvb, old_offset, 4, tvb_get_ipv4(tvb,old_offset));
1572
1573                                 if (tree){
1574                                         proto_tree *subtree;
1575
1576                                         subtree = proto_item_add_subtree(item, ett_mscldap_ipdetails);
1577
1578                                         /* get sockaddr family */
1579                                         proto_tree_add_item(subtree, hf_mscldap_netlogon_ipaddress_family, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1580                                         offset +=2;
1581
1582                                         /* get sockaddr port */
1583                                         proto_tree_add_item(subtree, hf_mscldap_netlogon_ipaddress_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1584                                         offset +=2;
1585
1586                                         /* get IP address */
1587                                         proto_tree_add_ipv4(subtree, hf_mscldap_netlogon_ipaddress_ipv4, tvb, offset, 4, tvb_get_ipv4(tvb,offset));
1588                                         offset +=4;
1589
1590                                         /* skip the 8 bytes of zeros in the sockaddr structure */
1591                                         offset += 8;
1592                                 }
1593
1594                         }
1595
1596                         break;
1597   }
1598
1599
1600  /* complete the decode with the version and token details */
1601
1602   offset = len-8;
1603
1604   /* NETLOGON_NT_VERISON Options (MS-ADTS 7.3.1.1) */
1605   offset = dissect_mscldap_ntver_flags(tree, tvb, offset);
1606
1607   /* LM Token */
1608   proto_tree_add_item(tree, hf_mscldap_netlogon_lm_token, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1609   offset += 2;
1610
1611   /* NT Token */
1612   proto_tree_add_item(tree, hf_mscldap_netlogon_nt_token, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1613   offset += 2;
1614
1615 }
1616
1617
1618 static guint
1619 get_sasl_ldap_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1620 {
1621         /* sasl encapsulated ldap is 4 bytes plus the length in size */
1622         return tvb_get_ntohl(tvb, offset)+4;
1623 }
1624
1625 static void
1626 dissect_sasl_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1627 {
1628         dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
1629         return;
1630 }
1631
1632 static guint
1633 get_normal_ldap_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1634 {
1635         guint32 len;
1636         gboolean ind;
1637         int data_offset;
1638
1639         /* normal ldap is tag+len bytes plus the length
1640          * offset is where the tag is
1641          * offset+1 is where length starts
1642          */
1643         data_offset=get_ber_length(tvb, offset+1, &len, &ind);
1644         return len+data_offset-offset;
1645 }
1646
1647 static void
1648 dissect_normal_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1649 {
1650         dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
1651         return;
1652 }
1653
1654 static void
1655 dissect_ldap_oid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1656 {
1657         char *oid;
1658         const char *oidname;
1659
1660         /* tvb here contains an ascii string that is really an oid */
1661 /* XXX   we should convert the string oid into a real oid so we can use
1662  *       proto_tree_add_oid() instead.
1663  */
1664
1665         oid=tvb_get_ephemeral_string(tvb, 0, tvb_length(tvb));
1666         if(!oid){
1667                 return;
1668         }
1669
1670         oidname=oid_resolved_from_string(oid);
1671
1672         if(oidname){
1673                 proto_tree_add_text(tree, tvb, 0, tvb_length(tvb), "OID: %s (%s)",oid,oidname);
1674         } else {
1675                 proto_tree_add_text(tree, tvb, 0, tvb_length(tvb), "OID: %s",oid);
1676         }
1677 }
1678
1679 #define LDAP_ACCESSMASK_ADS_CREATE_CHILD        0x00000001
1680 static const true_false_string ldap_AccessMask_ADS_CREATE_CHILD_tfs = {
1681    "ADS CREATE CHILD is SET",
1682    "Ads create child is NOT set",
1683 };
1684
1685 #define LDAP_ACCESSMASK_ADS_DELETE_CHILD        0x00000002
1686 static const true_false_string ldap_AccessMask_ADS_DELETE_CHILD_tfs = {
1687    "ADS DELETE CHILD is SET",
1688    "Ads delete child is NOT set",
1689 };
1690 #define LDAP_ACCESSMASK_ADS_LIST                0x00000004
1691 static const true_false_string ldap_AccessMask_ADS_LIST_tfs = {
1692    "ADS LIST is SET",
1693    "Ads list is NOT set",
1694 };
1695 #define LDAP_ACCESSMASK_ADS_SELF_WRITE          0x00000008
1696 static const true_false_string ldap_AccessMask_ADS_SELF_WRITE_tfs = {
1697    "ADS SELF WRITE is SET",
1698    "Ads self write is NOT set",
1699 };
1700 #define LDAP_ACCESSMASK_ADS_READ_PROP           0x00000010
1701 static const true_false_string ldap_AccessMask_ADS_READ_PROP_tfs = {
1702    "ADS READ PROP is SET",
1703    "Ads read prop is NOT set",
1704 };
1705 #define LDAP_ACCESSMASK_ADS_WRITE_PROP          0x00000020
1706 static const true_false_string ldap_AccessMask_ADS_WRITE_PROP_tfs = {
1707    "ADS WRITE PROP is SET",
1708    "Ads write prop is NOT set",
1709 };
1710 #define LDAP_ACCESSMASK_ADS_DELETE_TREE         0x00000040
1711 static const true_false_string ldap_AccessMask_ADS_DELETE_TREE_tfs = {
1712    "ADS DELETE TREE is SET",
1713    "Ads delete tree is NOT set",
1714 };
1715 #define LDAP_ACCESSMASK_ADS_LIST_OBJECT         0x00000080
1716 static const true_false_string ldap_AccessMask_ADS_LIST_OBJECT_tfs = {
1717    "ADS LIST OBJECT is SET",
1718    "Ads list object is NOT set",
1719 };
1720 #define LDAP_ACCESSMASK_ADS_CONTROL_ACCESS      0x00000100
1721 static const true_false_string ldap_AccessMask_ADS_CONTROL_ACCESS_tfs = {
1722    "ADS CONTROL ACCESS is SET",
1723    "Ads control access is NOT set",
1724 };
1725
1726 static void
1727 ldap_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree, guint32 access)
1728 {
1729         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_CONTROL_ACCESS, tvb, offset, 4, access);
1730
1731         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_LIST_OBJECT, tvb, offset, 4, access);
1732
1733         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_DELETE_TREE, tvb, offset, 4, access);
1734
1735         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_WRITE_PROP, tvb, offset, 4, access);
1736
1737         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_READ_PROP, tvb, offset, 4, access);
1738
1739         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_SELF_WRITE, tvb, offset, 4, access);
1740
1741         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_LIST, tvb, offset, 4, access);
1742
1743         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_DELETE_CHILD, tvb, offset, 4, access);
1744
1745         proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_CREATE_CHILD, tvb, offset, 4, access);
1746 }
1747 struct access_mask_info ldap_access_mask_info = {
1748         "LDAP",                 /* Name of specific rights */
1749         ldap_specific_rights,   /* Dissection function */
1750         NULL,                   /* Generic mapping table */
1751         NULL                    /* Standard mapping table */
1752 };
1753
1754 static void
1755 dissect_ldap_nt_sec_desc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1756 {
1757         dissect_nt_sec_desc(tvb, 0, pinfo, tree, NULL, TRUE, tvb_length(tvb), &ldap_access_mask_info);
1758 }
1759
1760 static void
1761 dissect_ldap_sid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1762 {
1763         char *tmpstr;
1764
1765         /* this octet string contains an NT SID */
1766         dissect_nt_sid(tvb, 0, tree, "SID", &tmpstr, hf_ldap_sid);
1767         ldapvalue_string=tmpstr;
1768 }
1769
1770 static void
1771 dissect_ldap_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1772 {
1773         guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1774         e_uuid_t uuid;
1775
1776         /* This octet string contained a GUID */
1777         dissect_dcerpc_uuid_t(tvb, 0, pinfo, tree, drep, hf_ldap_guid, &uuid);
1778
1779         ldapvalue_string=(char*)ep_alloc(1024);
1780         g_snprintf(ldapvalue_string, 1023, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1781                    uuid.Data1, uuid.Data2, uuid.Data3,
1782                    uuid.Data4[0], uuid.Data4[1],
1783                    uuid.Data4[2], uuid.Data4[3],
1784                    uuid.Data4[4], uuid.Data4[5],
1785                    uuid.Data4[6], uuid.Data4[7]);
1786 }
1787
1788 static void
1789 dissect_ldap_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1790 {
1791         guint32 sasl_len;
1792         guint32 ldap_len;
1793         gboolean ind;
1794         conversation_t *conversation;
1795         ldap_conv_info_t *ldap_info = NULL;
1796
1797         /*
1798          * Do we have a conversation for this connection?
1799          */
1800         conversation = find_conversation(pinfo->fd->num,
1801                                          &pinfo->src, &pinfo->dst,
1802                                          pinfo->ptype, pinfo->srcport,
1803                                          pinfo->destport, 0);
1804         if(conversation){
1805                 ldap_info = (ldap_conv_info_t *)conversation_get_proto_data(conversation, proto_ldap);
1806         }
1807
1808         ldm_tree = NULL;
1809
1810         /* This is a bit tricky. We have to find out whether SASL is used
1811          * so that we know how big a header we are supposed to pass
1812          * to tcp_dissect_pdus()
1813          * We must also cope with the case when a client connects to LDAP
1814          * and performs a few unauthenticated searches of LDAP before
1815          * it performs the bind on the same tcp connection.
1816          */
1817         /* check for a SASL header, i.e. assume it is SASL if
1818          * 1, first four bytes (SASL length) is an integer
1819          *    with a value that must be <LDAP_SASL_MAX_BUF and >2
1820          *    (>2 to fight false positives, 0x00000000 is a common
1821          *        "random" tcp payload)
1822          * (SASL ldap PDUs might be >64k in size, which is why
1823          * LDAP_SASL_MAX_BUF is used - defined in packet-ldap.h)
1824          *
1825          * 2, we must have a conversation and the auth type must
1826          *    be LDAP_AUTH_SASL
1827          */
1828         sasl_len=tvb_get_ntohl(tvb, 0);
1829
1830         if( sasl_len<2 ){
1831                 goto this_was_not_sasl;
1832         }
1833
1834         if( sasl_len>LDAP_SASL_MAX_BUF ){
1835                 goto this_was_not_sasl;
1836         }
1837
1838         if((!ldap_info) || (ldap_info->auth_type!=LDAP_AUTH_SASL) ){
1839                 goto this_was_not_sasl;
1840         }
1841
1842         tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_sasl_ldap_pdu_len, dissect_sasl_ldap_pdu);
1843         return;
1844
1845 this_was_not_sasl:
1846         /* check if it is a normal BER encoded LDAP packet
1847          * i.e. first byte is 0x30 followed by a length that is
1848          * <64k
1849          * (no ldap PDUs are ever >64kb? )
1850          */
1851         if(tvb_get_guint8(tvb, 0)!=0x30){
1852                 goto this_was_not_normal_ldap;
1853         }
1854
1855         /* check that length makes sense */
1856         get_ber_length(tvb, 1, &ldap_len, &ind);
1857
1858         /* dont check ind since indefinite length is never used for ldap (famous last words)*/
1859         if(ldap_len<2){
1860                 goto this_was_not_normal_ldap;
1861         }
1862
1863         /*
1864          * The minimun size of a LDAP pdu is 7 bytes
1865          *
1866          * dumpasn1 -hh ldap-unbind-min.dat
1867          *
1868          *     <30 05 02 01 09 42 00>
1869          *    0    5: SEQUENCE {
1870          *     <02 01 09>
1871          *    2    1:   INTEGER 9
1872          *     <42 00>
1873          *    5    0:   [APPLICATION 2]
1874          *          :     Error: Object has zero length.
1875          *          :   }
1876          *
1877          * dumpasn1 -hh ldap-unbind-windows.dat
1878          *
1879          *     <30 84 00 00 00 05 02 01 09 42 00>
1880          *    0    5: SEQUENCE {
1881          *     <02 01 09>
1882          *    6    1:   INTEGER 9
1883          *     <42 00>
1884          *    9    0:   [APPLICATION 2]
1885          *          :     Error: Object has zero length.
1886          *          :   }
1887          *
1888          * 6 bytes would also be ok to get the full length of
1889          * the pdu, but as the smallest pdu can be 7 bytes
1890          * we can use 7.
1891          */
1892         tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 7, get_normal_ldap_pdu_len, dissect_normal_ldap_pdu);
1893
1894         goto end;
1895
1896 this_was_not_normal_ldap:
1897
1898         /* perhaps it was SSL? */
1899         if(ldap_info &&
1900            ldap_info->start_tls_frame &&
1901            ( pinfo->fd->num >= ldap_info->start_tls_frame)) {
1902
1903           /* we have started TLS and so this may be an SSL layer */
1904           guint32 old_start_tls_frame;
1905
1906           /* temporarily dissect this port as SSL */
1907           dissector_delete_uint("tcp.port", tcp_port, ldap_handle);
1908           ssl_dissector_add(tcp_port, "ldap", TRUE);
1909
1910           old_start_tls_frame = ldap_info->start_tls_frame;
1911           ldap_info->start_tls_frame = 0; /* make sure we don't call SSL again */
1912           pinfo->can_desegment++; /* ignore this LDAP layer so SSL can use the TCP resegment */
1913
1914           call_dissector(ssl_handle, tvb, pinfo, tree);
1915
1916           ldap_info->start_tls_frame = old_start_tls_frame;
1917           ssl_dissector_delete(tcp_port, "ldap", TRUE);
1918
1919           /* restore ldap as the dissector for this port */
1920           dissector_add_uint("tcp.port", tcp_port, ldap_handle);
1921
1922           /* we are done */
1923           return;
1924         }
1925         /* Ok it might be a strange case of SASL still
1926          * It has been seen with Exchange setup to MS AD
1927          * when Exchange pretend that there is SASL but in fact data are still
1928          * in clear*/
1929         if ((sasl_len + 4) == (guint32)tvb_length_remaining(tvb, 0))
1930                 tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_sasl_ldap_pdu_len, dissect_sasl_ldap_pdu);
1931  end:
1932         return;
1933 }
1934
1935 static void
1936 dissect_mscldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1937 {
1938         dissect_ldap_pdu(tvb, pinfo, tree, TRUE);
1939         return;
1940 }
1941
1942
1943 static void
1944 ldap_reinit(void)
1945 {
1946   ldap_conv_info_t *ldap_info;
1947
1948   /* Free up state attached to the ldap_info structures */
1949   for (ldap_info = ldap_info_items; ldap_info != NULL; ) {
1950     ldap_conv_info_t *next;
1951
1952     g_free(ldap_info->auth_mech);
1953     g_hash_table_destroy(ldap_info->matched);
1954     g_hash_table_destroy(ldap_info->unmatched);
1955
1956     next = ldap_info->next;
1957     g_free(ldap_info);
1958     ldap_info = next;
1959   }
1960
1961   ldap_info_items = NULL;
1962 }
1963
1964 void
1965 register_ldap_name_dissector_handle(const char *attr_type_p, dissector_handle_t dissector)
1966 {
1967         dissector_add_string("ldap.name", attr_type_p, dissector);
1968 }
1969
1970 void
1971 register_ldap_name_dissector(const char *attr_type_p, dissector_t dissector, int proto)
1972 {
1973         dissector_handle_t dissector_handle;
1974
1975         dissector_handle=create_dissector_handle(dissector, proto);
1976         register_ldap_name_dissector_handle(attr_type_p, dissector_handle);
1977 }
1978
1979
1980 /*--- proto_register_ldap -------------------------------------------*/
1981 void proto_register_ldap(void) {
1982
1983   /* List of fields */
1984
1985   static hf_register_info hf[] = {
1986
1987     { &hf_ldap_sasl_buffer_length,
1988       { "SASL Buffer Length",   "ldap.sasl_buffer_length",
1989         FT_UINT32, BASE_DEC, NULL, 0x0,
1990         NULL, HFILL }},
1991     { &hf_ldap_response_in,
1992       { "Response In", "ldap.response_in",
1993         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1994         "The response to this LDAP request is in this frame", HFILL }},
1995     { &hf_ldap_response_to,
1996       { "Response To", "ldap.response_to",
1997         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1998         "This is a response to the LDAP request in this frame", HFILL }},
1999     { &hf_ldap_time,
2000       { "Time", "ldap.time",
2001         FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2002         "The time between the Call and the Reply", HFILL }},
2003
2004     { &hf_mscldap_netlogon_opcode,
2005       { "Operation code", "mscldap.netlogon.opcode",
2006         FT_UINT16, BASE_DEC, VALS(netlogon_opcode_vals), 0x0,
2007         "LDAP ping operation code", HFILL }},
2008
2009     { &hf_mscldap_netlogon_ipaddress_family,
2010       { "Family", "mscldap.netlogon.ipaddress.family",
2011         FT_UINT16, BASE_DEC, NULL, 0x0,
2012         NULL, HFILL }},
2013
2014     { &hf_mscldap_netlogon_ipaddress_ipv4,
2015       { "IPv4", "mscldap.netlogon.ipaddress.ipv4",
2016         FT_IPv4, BASE_NONE, NULL, 0x0,
2017         "IP Address", HFILL }},
2018
2019     { &hf_mscldap_netlogon_ipaddress_port,
2020       { "Port", "mscldap.netlogon.ipaddress.port",
2021         FT_UINT16, BASE_DEC, NULL, 0x0,
2022         NULL, HFILL }},
2023
2024     { &hf_mscldap_netlogon_ipaddress,
2025       { "IP Address","mscldap.netlogon.ipaddress",
2026         FT_IPv4, BASE_NONE, NULL, 0x0,
2027         "Domain Controller IP Address", HFILL }},
2028
2029     { &hf_mscldap_netlogon_lm_token,
2030       { "LM Token", "mscldap.netlogon.lm_token",
2031         FT_UINT16, BASE_HEX, NULL, 0x0,
2032         "MUST be set to 0xFFFF", HFILL }},
2033
2034     { &hf_mscldap_netlogon_nt_token,
2035       { "NT Token", "mscldap.netlogon.nt_token",
2036         FT_UINT16, BASE_HEX, NULL, 0x0,
2037         "MUST be set to 0xFFFF", HFILL }},
2038
2039     { &hf_mscldap_netlogon_flags,
2040       { "Flags", "mscldap.netlogon.flags",
2041         FT_UINT32, BASE_HEX, NULL, 0x0,
2042         "Netlogon flags describing the DC properties", HFILL }},
2043
2044     { &hf_mscldap_ntver_flags,
2045       { "Version Flags", "mscldap.ntver.flags",
2046         FT_UINT32, BASE_HEX, NULL, 0x0,
2047         "NETLOGON_NT_VERSION Options Bits", HFILL }},
2048
2049     { &hf_mscldap_domain_guid,
2050       { "Domain GUID", "mscldap.domain.guid",
2051         FT_GUID, BASE_NONE, NULL, 0x0,
2052         "Value of the NC's GUID attribute", HFILL }},
2053
2054     { &hf_mscldap_forest,
2055       { "Forest", "mscldap.forest",
2056         FT_STRING, BASE_NONE, NULL, 0x0,
2057         "DNS name of the forest", HFILL }},
2058
2059     { &hf_mscldap_domain,
2060       { "Domain", "mscldap.domain",
2061         FT_STRING, BASE_NONE, NULL, 0x0,
2062         "DNS name of the NC", HFILL }},
2063
2064     { &hf_mscldap_hostname,
2065       { "Hostname", "mscldap.hostname",
2066         FT_STRING, BASE_NONE, NULL, 0x0,
2067         "DNS name of server", HFILL }},
2068
2069     { &hf_mscldap_nb_domain,
2070       { "NetBIOS Domain", "mscldap.nb_domain",
2071         FT_STRING, BASE_NONE, NULL, 0x0,
2072         "NetBIOS name of the NC", HFILL }},
2073
2074     { &hf_mscldap_nb_hostname,
2075       { "NetBIOS Hostname", "mscldap.nb_hostname",
2076         FT_STRING, BASE_NONE, NULL, 0x0,
2077         "NetBIOS name of the server", HFILL }},
2078
2079     { &hf_mscldap_username,
2080       { "Username", "mscldap.username",
2081         FT_STRING, BASE_NONE, NULL, 0x0,
2082         "User specified in client's request", HFILL }},
2083
2084     { &hf_mscldap_sitename,
2085       { "Server Site", "mscldap.sitename",
2086         FT_STRING, BASE_NONE, NULL, 0x0,
2087         "Site name of the server", HFILL }},
2088
2089     { &hf_mscldap_clientsitename,
2090       { "Client Site", "mscldap.clientsitename",
2091         FT_STRING, BASE_NONE, NULL, 0x0,
2092         "Site name of the client", HFILL }},
2093
2094     { &hf_ldap_sid,
2095       { "Sid", "ldap.sid",
2096         FT_STRING, BASE_NONE, NULL, 0x0,
2097         NULL, HFILL }},
2098
2099     { &hf_mscldap_ntver_flags_v1,
2100       { "V1", "mscldap.ntver.searchflags.v1", FT_BOOLEAN, 32,
2101         TFS(&tfs_ntver_v1), 0x00000001, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2102
2103     { &hf_mscldap_ntver_flags_v5,
2104       { "V5", "mscldap.ntver.searchflags.v5", FT_BOOLEAN, 32,
2105         TFS(&tfs_ntver_v5), 0x00000002, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2106
2107     { &hf_mscldap_ntver_flags_v5ex,
2108       { "V5EX", "mscldap.ntver.searchflags.v5ex", FT_BOOLEAN, 32,
2109         TFS(&tfs_ntver_v5ex), 0x00000004, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2110
2111     { &hf_mscldap_ntver_flags_v5ep,
2112       { "V5EP", "mscldap.ntver.searchflags.v5ep", FT_BOOLEAN, 32,
2113         TFS(&tfs_ntver_v5ep), 0x00000008, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2114
2115     { &hf_mscldap_ntver_flags_vcs,
2116       { "VCS", "mscldap.ntver.searchflags.vcs", FT_BOOLEAN, 32,
2117         TFS(&tfs_ntver_vcs), 0x00000010, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2118
2119     { &hf_mscldap_ntver_flags_vnt4,
2120       { "VNT4", "mscldap.ntver.searchflags.vnt4", FT_BOOLEAN, 32,
2121         TFS(&tfs_ntver_vnt4), 0x01000000, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2122
2123     { &hf_mscldap_ntver_flags_vpdc,
2124       { "VPDC", "mscldap.ntver.searchflags.vpdc", FT_BOOLEAN, 32,
2125         TFS(&tfs_ntver_vpdc), 0x10000000, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2126
2127     { &hf_mscldap_ntver_flags_vip,
2128       { "VIP", "mscldap.ntver.searchflags.vip", FT_BOOLEAN, 32,
2129         TFS(&tfs_ntver_vip), 0x20000000, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2130
2131     { &hf_mscldap_ntver_flags_vl,
2132       { "VL", "mscldap.ntver.searchflags.vl", FT_BOOLEAN, 32,
2133         TFS(&tfs_ntver_vl), 0x40000000, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2134
2135     { &hf_mscldap_ntver_flags_vgc,
2136       { "VGC", "mscldap.ntver.searchflags.vgc", FT_BOOLEAN, 32,
2137         TFS(&tfs_ntver_vgc), 0x80000000, "See section 7.3.1.1 of MS-ADTS specification", HFILL }},
2138
2139
2140     { &hf_mscldap_netlogon_flags_pdc,
2141       { "PDC", "mscldap.netlogon.flags.pdc", FT_BOOLEAN, 32,
2142         TFS(&tfs_ads_pdc), 0x00000001, "Is this DC a PDC or not?", HFILL }},
2143
2144     { &hf_mscldap_netlogon_flags_gc,
2145       { "GC", "mscldap.netlogon.flags.gc", FT_BOOLEAN, 32,
2146         TFS(&tfs_ads_gc), 0x00000004, "Does this dc service as a GLOBAL CATALOGUE?", HFILL }},
2147
2148     { &hf_mscldap_netlogon_flags_ldap,
2149       { "LDAP", "mscldap.netlogon.flags.ldap", FT_BOOLEAN, 32,
2150         TFS(&tfs_ads_ldap), 0x00000008, "Does this DC act as an LDAP server?", HFILL }},
2151
2152     { &hf_mscldap_netlogon_flags_ds,
2153       { "DS", "mscldap.netlogon.flags.ds", FT_BOOLEAN, 32,
2154         TFS(&tfs_ads_ds), 0x00000010, "Does this dc provide DS services?", HFILL }},
2155
2156     { &hf_mscldap_netlogon_flags_kdc,
2157       { "KDC", "mscldap.netlogon.flags.kdc", FT_BOOLEAN, 32,
2158         TFS(&tfs_ads_kdc), 0x00000020, "Does this dc act as a KDC?", HFILL }},
2159
2160     { &hf_mscldap_netlogon_flags_timeserv,
2161       { "Time Serv", "mscldap.netlogon.flags.timeserv", FT_BOOLEAN, 32,
2162         TFS(&tfs_ads_timeserv), 0x00000040, "Does this dc provide time services (ntp) ?", HFILL }},
2163
2164     { &hf_mscldap_netlogon_flags_closest,
2165       { "Closest", "mscldap.netlogon.flags.closest", FT_BOOLEAN, 32,
2166         TFS(&tfs_ads_closest), 0x00000080, "Is this the closest dc?", HFILL }},
2167
2168     { &hf_mscldap_netlogon_flags_writable,
2169       { "Writable", "mscldap.netlogon.flags.writable", FT_BOOLEAN, 32,
2170         TFS(&tfs_ads_writable), 0x00000100, "Is this dc writable?", HFILL }},
2171
2172     { &hf_mscldap_netlogon_flags_good_timeserv,
2173       { "Good Time Serv", "mscldap.netlogon.flags.good_timeserv", FT_BOOLEAN, 32,
2174         TFS(&tfs_ads_good_timeserv), 0x00000200, "Is this a Good Time Server? (i.e. does it have a hardware clock)", HFILL }},
2175
2176     { &hf_mscldap_netlogon_flags_ndnc,
2177       { "NDNC", "mscldap.netlogon.flags.ndnc", FT_BOOLEAN, 32,
2178         TFS(&tfs_ads_ndnc), 0x00000400, "Is this an NDNC dc?", HFILL }},
2179
2180     { &hf_mscldap_netlogon_flags_rodc,
2181       { "RODC", "mscldap.netlogon.flags.rodc", FT_BOOLEAN, 32,
2182         TFS(&tfs_ads_rodc), 0x00000800, "Is this an read only dc?", HFILL }},
2183
2184     { &hf_mscldap_netlogon_flags_wdc,
2185       { "WDC", "mscldap.netlogon.flags.writabledc.", FT_BOOLEAN, 32,
2186         TFS(&tfs_ads_wdc), 0x00001000, "Is this an writable dc (Windows 2008)?", HFILL }},
2187
2188     { &hf_mscldap_netlogon_flags_dns,
2189       { "DNS", "mscldap.netlogon.flags.dnsname", FT_BOOLEAN, 32,
2190         TFS(&tfs_ads_dns), 0x20000000, "Does the server have a dns name (Windows 2008)?", HFILL }},
2191
2192     { &hf_mscldap_netlogon_flags_dnc,
2193       { "DNC", "mscldap.netlogon.flags.defaultnc", FT_BOOLEAN, 32,
2194         TFS(&tfs_ads_dnc), 0x40000000, "Is this the default NC (Windows 2008)?", HFILL }},
2195
2196     { &hf_mscldap_netlogon_flags_fnc,
2197       { "FDC", "mscldap.netlogon.flags.forestnc", FT_BOOLEAN, 32,
2198         TFS(&tfs_ads_fnc), 0x80000000, "Is the the NC the default forest root(Windows 2008)?", HFILL }},
2199
2200     { &hf_ldap_guid,
2201       { "GUID", "ldap.guid", FT_GUID, BASE_NONE,
2202         NULL, 0, NULL, HFILL }},
2203
2204     { &hf_ldap_AccessMask_ADS_CREATE_CHILD,
2205       { "Create Child", "ldap.AccessMask.ADS_CREATE_CHILD", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_CREATE_CHILD_tfs), LDAP_ACCESSMASK_ADS_CREATE_CHILD, NULL, HFILL }},
2206
2207     { &hf_ldap_AccessMask_ADS_DELETE_CHILD,
2208       { "Delete Child", "ldap.AccessMask.ADS_DELETE_CHILD", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_DELETE_CHILD_tfs), LDAP_ACCESSMASK_ADS_DELETE_CHILD, NULL, HFILL }},
2209
2210     { &hf_ldap_AccessMask_ADS_LIST,
2211       { "List", "ldap.AccessMask.ADS_LIST", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_LIST_tfs), LDAP_ACCESSMASK_ADS_LIST, NULL, HFILL }},
2212
2213     { &hf_ldap_AccessMask_ADS_SELF_WRITE,
2214       { "Self Write", "ldap.AccessMask.ADS_SELF_WRITE", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_SELF_WRITE_tfs), LDAP_ACCESSMASK_ADS_SELF_WRITE, NULL, HFILL }},
2215
2216     { &hf_ldap_AccessMask_ADS_READ_PROP,
2217       { "Read Prop", "ldap.AccessMask.ADS_READ_PROP", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_READ_PROP_tfs), LDAP_ACCESSMASK_ADS_READ_PROP, NULL, HFILL }},
2218
2219     { &hf_ldap_AccessMask_ADS_WRITE_PROP,
2220       { "Write Prop", "ldap.AccessMask.ADS_WRITE_PROP", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_WRITE_PROP_tfs), LDAP_ACCESSMASK_ADS_WRITE_PROP, NULL, HFILL }},
2221
2222     { &hf_ldap_AccessMask_ADS_DELETE_TREE,
2223       { "Delete Tree", "ldap.AccessMask.ADS_DELETE_TREE", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_DELETE_TREE_tfs), LDAP_ACCESSMASK_ADS_DELETE_TREE, NULL, HFILL }},
2224
2225     { &hf_ldap_AccessMask_ADS_LIST_OBJECT,
2226       { "List Object", "ldap.AccessMask.ADS_LIST_OBJECT", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_LIST_OBJECT_tfs), LDAP_ACCESSMASK_ADS_LIST_OBJECT, NULL, HFILL }},
2227
2228     { &hf_ldap_AccessMask_ADS_CONTROL_ACCESS,
2229       { "Control Access", "ldap.AccessMask.ADS_CONTROL_ACCESS", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_CONTROL_ACCESS_tfs), LDAP_ACCESSMASK_ADS_CONTROL_ACCESS, NULL, HFILL }},
2230
2231 #include "packet-ldap-hfarr.c"
2232   };
2233
2234   /* List of subtrees */
2235   static gint *ett[] = {
2236     &ett_ldap,
2237     &ett_ldap_payload,
2238     &ett_ldap_sasl_blob,
2239     &ett_ldap_msg,
2240     &ett_mscldap_netlogon_flags,
2241     &ett_mscldap_ntver_flags,
2242     &ett_mscldap_ipdetails,
2243
2244 #include "packet-ldap-ettarr.c"
2245   };
2246   /* UAT for header fields */
2247   static uat_field_t custom_attribute_types_uat_fields[] = {
2248      UAT_FLD_CSTRING(attribute_types, attribute_type, "Attribute type", "Attribute type"),
2249      UAT_FLD_CSTRING(attribute_types, attribute_desc, "Description", "Description of the value matching type"),
2250      UAT_END_FIELDS
2251   };
2252
2253   module_t *ldap_module;
2254   uat_t *attributes_uat;
2255   
2256   /* Register protocol */
2257   proto_ldap = proto_register_protocol(PNAME, PSNAME, PFNAME);
2258   /* Register fields and subtrees */
2259   proto_register_field_array(proto_ldap, hf, array_length(hf));
2260   proto_register_subtree_array(ett, array_length(ett));
2261
2262
2263   register_dissector("ldap", dissect_ldap_tcp, proto_ldap);
2264
2265   ldap_module = prefs_register_protocol(proto_ldap, prefs_register_ldap);
2266   prefs_register_bool_preference(ldap_module, "desegment_ldap_messages",
2267     "Reassemble LDAP messages spanning multiple TCP segments",
2268     "Whether the LDAP dissector should reassemble messages spanning multiple TCP segments."
2269     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2270     &ldap_desegment);
2271
2272   prefs_register_uint_preference(ldap_module, "tcp.port", "LDAP TCP Port",
2273                                  "Set the port for LDAP operations",
2274                                  10, &global_ldap_tcp_port);
2275
2276   prefs_register_uint_preference(ldap_module, "ssl.port", "LDAPS TCP Port",
2277                                  "Set the port for LDAP operations over SSL",
2278                                  10, &global_ldaps_tcp_port);
2279   /* UAT */
2280   attributes_uat = uat_new("Custom LDAP AttributeValue types",
2281                            sizeof(attribute_type_t),
2282                            "custom_ldap_attribute_types",
2283                            TRUE,
2284                            (void*) &attribute_types,
2285                            &num_attribute_types,
2286                            UAT_CAT_FIELDS,
2287                            NULL,
2288                            attribute_types_copy_cb,
2289                            attribute_types_update_cb,
2290                            attribute_types_free_cb,
2291                            attribute_types_initialize_cb,
2292                            custom_attribute_types_uat_fields);
2293
2294   prefs_register_uat_preference(ldap_module, "custom_ldap_attribute_types",
2295                                 "Custom AttributeValue types",
2296                                 "A table to define custom LDAP attribute type values for which fields can be setup and used for filtering/data extraction etc.",
2297                                 attributes_uat);
2298
2299   prefs_register_obsolete_preference(ldap_module, "max_pdu");
2300
2301   proto_cldap = proto_register_protocol(
2302           "Connectionless Lightweight Directory Access Protocol",
2303           "CLDAP", "cldap");
2304
2305   register_init_routine(ldap_reinit);
2306   ldap_tap=register_tap("ldap");
2307
2308   ldap_name_dissector_table = register_dissector_table("ldap.name", "LDAP Attribute Type Dissectors", FT_STRING, BASE_NONE);
2309
2310 }
2311
2312
2313 /*--- proto_reg_handoff_ldap ---------------------------------------*/
2314 void
2315 proto_reg_handoff_ldap(void)
2316 {
2317         dissector_handle_t cldap_handle;
2318         ldap_handle = find_dissector("ldap");
2319
2320         dissector_add_uint("tcp.port", TCP_PORT_GLOBALCAT_LDAP, ldap_handle);
2321
2322         cldap_handle = create_dissector_handle(dissect_mscldap, proto_cldap);
2323         dissector_add_uint("udp.port", UDP_PORT_CLDAP, cldap_handle);
2324
2325         gssapi_handle = find_dissector("gssapi");
2326         gssapi_wrap_handle = find_dissector("gssapi_verf");
2327         spnego_handle = find_dissector("spnego");
2328
2329         ntlmssp_handle = find_dissector("ntlmssp");
2330
2331         ssl_handle = find_dissector("ssl");
2332
2333         prefs_register_ldap();
2334
2335 /*  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dsml/dsml/ldap_controls_and_session_support.asp */
2336         oid_add_from_string("LDAP_PAGED_RESULT_OID_STRING","1.2.840.113556.1.4.319");
2337         oid_add_from_string("LDAP_SERVER_SHOW_DELETED_OID","1.2.840.113556.1.4.417");
2338         oid_add_from_string("LDAP_SERVER_SORT_OID","1.2.840.113556.1.4.473");
2339         oid_add_from_string("LDAP_CONTROL_SORT_RESP_OID","1.2.840.113556.1.4.474");
2340         oid_add_from_string("LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID","1.2.840.113556.1.4.521");
2341         oid_add_from_string("LDAP_SERVER_NOTIFICATION_OID","1.2.840.113556.1.4.528");
2342         oid_add_from_string("LDAP_SERVER_EXTENDED_DN_OID","1.2.840.113556.1.4.529");
2343         oid_add_from_string("meetingAdvertiseScope","1.2.840.113556.1.4.582");
2344         oid_add_from_string("LDAP_SERVER_LAZY_COMMIT_OID","1.2.840.113556.1.4.619");
2345         oid_add_from_string("mhsORAddress","1.2.840.113556.1.4.650");
2346         oid_add_from_string("managedObjects","1.2.840.113556.1.4.654");
2347         oid_add_from_string("LDAP_CAP_ACTIVE_DIRECTORY_OID","1.2.840.113556.1.4.800");
2348         oid_add_from_string("LDAP_SERVER_SD_FLAGS_OID","1.2.840.113556.1.4.801");
2349         oid_add_from_string("LDAP_OID_COMPARATOR_OR","1.2.840.113556.1.4.804");
2350         oid_add_from_string("LDAP_SERVER_TREE_DELETE_OID","1.2.840.113556.1.4.805");
2351         oid_add_from_string("LDAP_SERVER_DIRSYNC_OID","1.2.840.113556.1.4.841");
2352         oid_add_from_string("None","1.2.840.113556.1.4.970");
2353         oid_add_from_string("LDAP_SERVER_VERIFY_NAME_OID","1.2.840.113556.1.4.1338");
2354         oid_add_from_string("LDAP_SERVER_DOMAIN_SCOPE_OID","1.2.840.113556.1.4.1339");
2355         oid_add_from_string("LDAP_SERVER_SEARCH_OPTIONS_OID","1.2.840.113556.1.4.1340");
2356         oid_add_from_string("LDAP_SERVER_PERMISSIVE_MODIFY_OID","1.2.840.113556.1.4.1413");
2357         oid_add_from_string("LDAP_SERVER_ASQ_OID","1.2.840.113556.1.4.1504");
2358         oid_add_from_string("LDAP_CAP_ACTIVE_DIRECTORY_V51_OID","1.2.840.113556.1.4.1670");
2359         oid_add_from_string("LDAP_SERVER_FAST_BIND_OID","1.2.840.113556.1.4.1781");
2360         oid_add_from_string("LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID","1.2.840.113556.1.4.1791");
2361         oid_add_from_string("msDS-ObjectReference","1.2.840.113556.1.4.1840");
2362         oid_add_from_string("msDS-QuotaEffective","1.2.840.113556.1.4.1848");
2363         oid_add_from_string("LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID","1.2.840.113556.1.4.1851");
2364         oid_add_from_string("msDS-PortSSL","1.2.840.113556.1.4.1860");
2365         oid_add_from_string("msDS-isRODC","1.2.840.113556.1.4.1960");
2366         oid_add_from_string("msDS-SDReferenceDomain","1.2.840.113556.1.4.1711");
2367         oid_add_from_string("msDS-AdditionalDnsHostName","1.2.840.113556.1.4.1717");
2368         oid_add_from_string("None","1.3.6.1.4.1.1466.101.119.1");
2369         oid_add_from_string("LDAP_START_TLS_OID","1.3.6.1.4.1.1466.20037");
2370         oid_add_from_string("LDAP_CONTROL_VLVREQUEST VLV","2.16.840.1.113730.3.4.9");
2371         oid_add_from_string("LDAP_CONTROL_VLVRESPONSE VLV","2.16.840.1.113730.3.4.10");
2372         oid_add_from_string("LDAP_SERVER_QUOTA_CONTROL_OID","1.2.840.113556.1.4.1852");
2373         oid_add_from_string("LDAP_SERVER_RANGE_OPTION_OID","1.2.840.113556.1.4.802");
2374         oid_add_from_string("LDAP_SERVER_SHUTDOWN_NOTIFY_OID","1.2.840.113556.1.4.1907");
2375         oid_add_from_string("LDAP_SERVER_RANGE_RETRIEVAL_NOERR_OID","1.2.840.113556.1.4.1948");
2376
2377         register_ldap_name_dissector("netlogon", dissect_NetLogon_PDU, proto_cldap);
2378         register_ldap_name_dissector("objectGUID", dissect_ldap_guid, proto_ldap);
2379         register_ldap_name_dissector("supportedControl", dissect_ldap_oid, proto_ldap);
2380         register_ldap_name_dissector("supportedCapabilities", dissect_ldap_oid, proto_ldap);
2381         register_ldap_name_dissector("objectSid", dissect_ldap_sid, proto_ldap);
2382         register_ldap_name_dissector("nTSecurityDescriptor", dissect_ldap_nt_sec_desc, proto_ldap);
2383
2384 #include "packet-ldap-dis-tab.c"
2385
2386
2387 }
2388
2389 static void
2390 prefs_register_ldap(void)
2391 {
2392
2393   if(tcp_port != global_ldap_tcp_port) {
2394     if(tcp_port)
2395       dissector_delete_uint("tcp.port", tcp_port, ldap_handle);
2396
2397     /* Set our port number for future use */
2398     tcp_port = global_ldap_tcp_port;
2399
2400     if(tcp_port)
2401       dissector_add_uint("tcp.port", tcp_port, ldap_handle);
2402
2403   }
2404
2405   if(ssl_port != global_ldaps_tcp_port) {
2406     if(ssl_port)
2407       ssl_dissector_delete(ssl_port, "ldap", TRUE);
2408
2409     /* Set our port number for future use */
2410     ssl_port = global_ldaps_tcp_port;
2411
2412     if(ssl_port)
2413       ssl_dissector_add(ssl_port, "ldap", TRUE);
2414   }
2415
2416 }