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