From Yuriy Sidelnikov: handle the case where a presentation selector
[obnox/wireshark/wip.git] / packet-ldap.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: packet-ldap.c,v 1.73 2004/01/19 22:58:59 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
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 #ifdef HAVE_CONFIG_H
61 # include "config.h"
62 #endif
63
64 #include <stdio.h>
65
66 #include <string.h>
67 #include <glib.h>
68
69 #ifdef NEED_SNPRINTF_H
70 # include "snprintf.h"
71 #endif
72
73 #include <epan/packet.h>
74
75 #include "asn1.h"
76 #include "prefs.h"
77 #include <epan/conversation.h>
78 #include "packet-frame.h"
79 #include "tap.h"
80 #include "packet-ldap.h"
81
82 static int proto_ldap = -1;
83 static int proto_cldap = -1;
84 static int hf_ldap_response_to = -1;
85 static int hf_ldap_response_in = -1;
86 static int hf_ldap_time = -1;
87 static int hf_ldap_sasl_buffer_length = -1;
88 static int hf_ldap_length = -1;
89 static int hf_ldap_message_id = -1;
90 static int hf_ldap_message_type = -1;
91 static int hf_ldap_message_length = -1;
92
93 static int hf_ldap_message_result = -1;
94 static int hf_ldap_message_result_matcheddn = -1;
95 static int hf_ldap_message_result_errormsg = -1;
96 static int hf_ldap_message_result_referral = -1;
97
98 static int hf_ldap_message_bind_version = -1;
99 static int hf_ldap_message_bind_dn = -1;
100 static int hf_ldap_message_bind_auth = -1;
101 static int hf_ldap_message_bind_auth_password = -1;
102 static int hf_ldap_message_bind_auth_mechanism = -1;
103 static int hf_ldap_message_bind_auth_credentials = -1;
104 static int hf_ldap_message_bind_server_credentials = -1;
105
106 static int hf_ldap_message_search_base = -1;
107 static int hf_ldap_message_search_scope = -1;
108 static int hf_ldap_message_search_deref = -1;
109 static int hf_ldap_message_search_sizeLimit = -1;
110 static int hf_ldap_message_search_timeLimit = -1;
111 static int hf_ldap_message_search_typesOnly = -1;
112 static int hf_ldap_message_search_filter = -1;
113 static int hf_ldap_message_search_reference = -1;
114
115 static int hf_ldap_message_dn = -1;
116 static int hf_ldap_message_attribute = -1;
117 static int hf_ldap_message_value = -1;
118
119 static int hf_ldap_message_modrdn_name = -1;
120 static int hf_ldap_message_modrdn_delete = -1;
121 static int hf_ldap_message_modrdn_superior = -1;
122
123 static int hf_ldap_message_compare = -1;
124
125 static int hf_ldap_message_modify_add = -1;
126 static int hf_ldap_message_modify_replace = -1;
127 static int hf_ldap_message_modify_delete = -1;
128
129 static int hf_ldap_message_abandon_msgid = -1;
130
131 static int hf_mscldap_netlogon_type = -1;
132 static int hf_mscldap_netlogon_flags = -1;
133 static int hf_mscldap_domain_guid = -1;
134 static int hf_mscldap_forest = -1;
135 static int hf_mscldap_domain = -1;
136 static int hf_mscldap_hostname = -1;
137 static int hf_mscldap_nb_domain = -1;
138 static int hf_mscldap_nb_hostname = -1;
139 static int hf_mscldap_username = -1;
140 static int hf_mscldap_sitename = -1;
141 static int hf_mscldap_clientsitename = -1;
142 static int hf_mscldap_netlogon_version = -1;
143 static int hf_mscldap_netlogon_lm_token = -1;
144 static int hf_mscldap_netlogon_nt_token = -1;
145
146 static gint ett_ldap = -1;
147 static gint ett_ldap_gssapi_token = -1;
148 static gint ett_ldap_referrals = -1;
149 static gint ett_ldap_attribute = -1;
150
151 static int ldap_tap = -1;
152
153 /* desegmentation of LDAP */
154 static gboolean ldap_desegment = TRUE;
155
156 #define TCP_PORT_LDAP                   389
157 #define UDP_PORT_CLDAP                  389
158 #define TCP_PORT_GLOBALCAT_LDAP         3268 /* Windows 2000 Global Catalog */
159
160 static dissector_handle_t gssapi_handle;
161 static dissector_handle_t gssapi_wrap_handle;
162
163
164 /* different types of rpc calls ontop of ms cldap */
165 #define MSCLDAP_RPC_NETLOGON    1
166
167
168 /*
169  * Data structure attached to a conversation, giving authentication
170  * information from a bind request.
171  * We keep a linked list of them, so that we can free up all the
172  * authentication mechanism strings.
173  */
174 typedef struct ldap_conv_info_t {
175   struct ldap_conv_info_t *next;
176   guint auth_type;              /* authentication type */
177   char *auth_mech;              /* authentication mechanism */
178   guint32 first_auth_frame;     /* first frame that would use a security layer */
179   GHashTable *unmatched;
180   GHashTable *matched;
181 } ldap_conv_info_t;
182 static GMemChunk *ldap_conv_info_chunk = NULL;
183 static guint ldap_conv_info_chunk_count = 20;
184 static ldap_conv_info_t *ldap_info_items;
185
186 static GMemChunk *ldap_call_response_chunk = NULL;
187 static guint ldap_call_response_chunk_count = 200;
188
189 static guint
190 ldap_info_hash_matched(gconstpointer k)
191 {
192   ldap_call_response_t *key = (ldap_call_response_t *)k;
193
194   return key->messageId;
195 }
196
197 static gint
198 ldap_info_equal_matched(gconstpointer k1, gconstpointer k2)
199 {
200   ldap_call_response_t *key1 = (ldap_call_response_t *)k1;
201   ldap_call_response_t *key2 = (ldap_call_response_t *)k2;
202
203   if( key1->req_frame && key2->req_frame && (key1->req_frame!=key2->req_frame) ){
204     return 0;
205   }
206   if( key1->rep_frame && key2->rep_frame && (key1->rep_frame!=key2->rep_frame) ){
207     return 0;
208   }
209
210   return key1->messageId==key2->messageId;
211 }
212
213 static guint
214 ldap_info_hash_unmatched(gconstpointer k)
215 {
216   ldap_call_response_t *key = (ldap_call_response_t *)k;
217
218   return key->messageId;
219 }
220
221 static gint
222 ldap_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
223 {
224   ldap_call_response_t *key1 = (ldap_call_response_t *)k1;
225   ldap_call_response_t *key2 = (ldap_call_response_t *)k2;
226
227   return key1->messageId==key2->messageId;
228 }
229
230
231 static value_string msgTypes [] = {
232   {LDAP_REQ_BIND, "Bind Request"},
233   {LDAP_REQ_UNBIND, "Unbind Request"},
234   {LDAP_REQ_SEARCH, "Search Request"},
235   {LDAP_REQ_MODIFY, "Modify Request"},
236   {LDAP_REQ_ADD, "Add Request"},
237   {LDAP_REQ_DELETE, "Delete Request"},
238   {LDAP_REQ_MODRDN, "Modify RDN Request"},
239   {LDAP_REQ_COMPARE, "Compare Request"},
240   {LDAP_REQ_ABANDON, "Abandon Request"},
241   {LDAP_REQ_EXTENDED, "Extended Request"},
242
243   {LDAP_RES_BIND, "Bind Result"},
244   {LDAP_RES_SEARCH_ENTRY, "Search Entry"},
245   {LDAP_RES_SEARCH_RESULT, "Search Result"},
246   {LDAP_RES_SEARCH_REF, "Search Result Reference"},
247   {LDAP_RES_MODIFY, "Modify Result"},
248   {LDAP_RES_ADD, "Add Result"},
249   {LDAP_RES_DELETE, "Delete Result"},
250   {LDAP_RES_MODRDN, "Modify RDN Result"},
251   {LDAP_RES_COMPARE, "Compare Result"},
252   {LDAP_RES_EXTENDED, "Extended Response"},
253   {0, NULL},
254 };
255
256 static value_string result_codes[] = {
257     {0, "Success"},
258     {1, "Operations error"},
259     {2, "Protocol error"},
260     {3, "Time limit exceeded"},
261     {4, "Size limit exceeded"},
262     {5, "Compare false"},
263     {6, "Compare true"},
264     {7, "Authentication method not supported"},
265     {8, "Strong authentication required"},
266     {10, "Referral"},
267     {11, "Administrative limit exceeded"},
268     {12, "Unavailable critical extension"},
269     {13, "Confidentiality required"},
270     {14, "SASL bind in progress"},
271     {16, "No such attribute"},
272     {17, "Undefined attribute type"},
273     {18, "Inappropriate matching"},
274     {19, "Constraint violation"},
275     {20, "Attribute or value exists"},
276     {21, "Invalid attribute syntax"},
277     {32, "No such object"},
278     {33, "Alias problem"},
279     {34, "Invalid DN syntax"},
280     {36, "Alias derefetencing problem"},
281     {48, "Inappropriate authentication"},
282     {49, "Invalid credentials"},
283     {50, "Insufficient access rights"},
284     {51, "Busy"},
285     {52, "Unavailable"},
286     {53, "Unwilling to perform"},
287     {54, "Loop detected"},
288     {64, "Naming violation"},
289     {65, "Objectclass violation"},
290     {66, "Not allowed on non-leaf"},
291     {67, "Not allowed on RDN"},
292     {68, "Entry already exists"},
293     {69, "Objectclass modification prohibited"},
294     {71, "Affects multiple DSAs"},
295     {80, "Other"},
296     {0,  NULL},
297 };
298
299 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
300 {
301   guint length = 0;
302   gboolean def = FALSE;
303   int start = a->offset;
304   int ret;
305
306   ret = asn1_length_decode(a, &def, &length);
307   if (ret != ASN1_ERR_NOERROR) {
308     if (tree) {
309       proto_tree_add_text(tree, a->tvb, start, 0,
310         "%s: ERROR: Couldn't parse length: %s",
311         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
312     }
313     return ret;
314   }
315
316   if (len)
317     *len = length;
318
319   if (tree)
320     proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, length);
321
322   return ASN1_ERR_NOERROR;
323 }
324
325 static int read_sequence(ASN1_SCK *a, guint *len)
326 {
327   guint cls, con, tag;
328   gboolean def;
329   guint length;
330   int ret;
331
332   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
333   if (ret != ASN1_ERR_NOERROR)
334     return ret;
335   if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
336     return ASN1_ERR_WRONG_TYPE;
337
338   if (len)
339     *len = length;
340
341   return ASN1_ERR_NOERROR;
342 }
343
344 static int read_set(ASN1_SCK *a, guint *len)
345 {
346   guint cls, con, tag;
347   gboolean def;
348   guint length;
349   int ret;
350
351   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
352   if (ret != ASN1_ERR_NOERROR)
353     return ret;
354   if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SET)
355     return ASN1_ERR_WRONG_TYPE;
356
357   if (len)
358     *len = length;
359
360   return ASN1_ERR_NOERROR;
361 }
362
363 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
364         proto_item **new_item, guint *i, int start, guint length)
365 {
366   guint integer = 0;
367   proto_item *temp_item = NULL;
368   int ret;
369
370   ret = asn1_uint32_value_decode(a, length, &integer);
371   if (ret != ASN1_ERR_NOERROR) {
372     if (tree) {
373       proto_tree_add_text(tree, a->tvb, start, 0,
374        "%s: ERROR: Couldn't parse value: %s",
375         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
376     }
377     return ret;
378   }
379
380   if (i)
381     *i = integer;
382
383   if (tree)
384     temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, integer);
385
386   if (new_item)
387     *new_item = temp_item;
388
389   return ASN1_ERR_NOERROR;
390 }
391
392 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
393         proto_item **new_item, guint *i, guint expected_tag)
394 {
395   guint cls, con, tag;
396   gboolean def;
397   guint length;
398   int start = a->offset;
399   int ret;
400
401   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
402   if (ret == ASN1_ERR_NOERROR) {
403     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag)
404       ret = ASN1_ERR_WRONG_TYPE;
405   }
406   if (ret != ASN1_ERR_NOERROR) {
407     if (tree) {
408       proto_tree_add_text(tree, a->tvb, start, 0,
409         "%s: ERROR: Couldn't parse header: %s",
410         (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
411         asn1_err_to_str(ret));
412     }
413     return ret;
414   }
415
416   return read_integer_value(a, tree, hf_id, new_item, i, start, length);
417 }
418
419 static int read_boolean_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
420         proto_item **new_item, guint *i, int start, guint length)
421 {
422   guint integer = 0;
423   proto_item *temp_item = NULL;
424   int ret;
425
426   ret = asn1_uint32_value_decode(a, length, &integer);
427   if (ret != ASN1_ERR_NOERROR) {
428     if (tree) {
429       proto_tree_add_text(tree, a->tvb, start, 0,
430         "%s: ERROR: Couldn't parse value: %s",
431         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
432     }
433     return ret;
434   }
435
436   if (i)
437     *i = integer;
438
439   if (tree)
440     temp_item = proto_tree_add_boolean(tree, hf_id, a->tvb, start, a->offset-start, integer);
441   if (new_item)
442     *new_item = temp_item;
443
444   return ASN1_ERR_NOERROR;
445 }
446
447 static int read_boolean(ASN1_SCK *a, proto_tree *tree, int hf_id,
448         proto_item **new_item, guint *i)
449 {
450   guint cls, con, tag;
451   gboolean def;
452   guint length;
453   int start = a->offset;
454   int ret;
455
456   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
457   if (ret == ASN1_ERR_NOERROR) {
458     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_BOL)
459       ret = ASN1_ERR_WRONG_TYPE;
460   }
461   if (ret != ASN1_ERR_NOERROR) {
462     if (tree) {
463       proto_tree_add_text(tree, a->tvb, start, 0,
464         "%s: ERROR: Couldn't parse header: %s",
465         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
466     }
467     return ret;
468   }
469
470   return read_boolean_value(a, tree, hf_id, new_item, i, start, length);
471 }
472
473 static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
474         proto_item **new_item, char **s, int start, guint length)
475 {
476   guchar *string;
477   proto_item *temp_item = NULL;
478   int ret;
479
480   if (length)
481   {
482     ret = asn1_string_value_decode(a, length, &string);
483     if (ret != ASN1_ERR_NOERROR) {
484       if (tree) {
485         proto_tree_add_text(tree, a->tvb, start, 0,
486           "%s: ERROR: Couldn't parse value: %s",
487           proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
488       }
489       return ret;
490     }
491     string = g_realloc(string, length + 1);
492     string[length] = '\0';
493   }
494   else
495     string = "(null)";
496
497   if (tree)
498     temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset - start, string);
499   if (new_item)
500     *new_item = temp_item;
501
502   if (s && length)
503     *s = string;
504   else if (length)
505     g_free(string);
506
507   return ASN1_ERR_NOERROR;
508 }
509
510 static int read_string(ASN1_SCK *a, proto_tree *tree, int hf_id,
511         proto_item **new_item, char **s, guint *length,
512         guint expected_cls, guint expected_tag)
513 {
514   guint cls, con, tag;
515   gboolean def;
516   guint tmplen;
517   int start = a->offset;
518   int ret;
519
520   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &tmplen);
521   if (ret == ASN1_ERR_NOERROR) {
522     if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
523       ret = ASN1_ERR_WRONG_TYPE;
524   }
525   if (ret != ASN1_ERR_NOERROR) {
526     if (tree) {
527       proto_tree_add_text(tree, a->tvb, start, 0,
528         "%s: ERROR: Couldn't parse header: %s",
529         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
530     }
531     return ret;
532   }
533
534   if(length){
535      *length=tmplen;
536   }
537   return read_string_value(a, tree, hf_id, new_item, s, start, tmplen);
538 }
539
540 static int read_bytestring_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
541         proto_item **new_item, char **s, int start, guint length)
542 {
543   guchar *string;
544   proto_item *temp_item = NULL;
545   int ret;
546
547   if (length)
548   {
549     ret = asn1_string_value_decode(a, length, &string);
550     if (ret != ASN1_ERR_NOERROR) {
551       if (tree) {
552         proto_tree_add_text(tree, a->tvb, start, 0,
553           "%s: ERROR: Couldn't parse value: %s",
554           proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
555       }
556       return ret;
557     }
558     string = g_realloc(string, length + 1);
559     string[length] = '\0';
560   }
561   else
562     string = "(null)";
563
564   if (tree)
565     temp_item = proto_tree_add_bytes(tree, hf_id, a->tvb, start, a->offset - start, string);
566   if (new_item)
567     *new_item = temp_item;
568
569   if (s && length)
570     *s = string;
571   else if (length)
572     g_free(string);
573
574   return ASN1_ERR_NOERROR;
575 }
576
577 static int read_bytestring(ASN1_SCK *a, proto_tree *tree, int hf_id,
578         proto_item **new_item, char **s, guint expected_cls, guint expected_tag)
579 {
580   guint cls, con, tag;
581   gboolean def;
582   guint length;
583   int start = a->offset;
584   int ret;
585
586   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
587   if (ret == ASN1_ERR_NOERROR) {
588     if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
589       ret = ASN1_ERR_WRONG_TYPE;
590   }
591   if (ret != ASN1_ERR_NOERROR) {
592     if (tree) {
593       proto_tree_add_text(tree, a->tvb, start, 0,
594         "%s: ERROR: Couldn't parse header: %s",
595         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
596     }
597     return ret;
598   }
599
600   return read_bytestring_value(a, tree, hf_id, new_item, s, start, length);
601 }
602
603 static int parse_filter_strings(ASN1_SCK *a, char **filter, guint *filter_length, const guchar *operation)
604 {
605   guchar *string;
606   guchar *string2;
607   guint string_length;
608   guint string2_length;
609   guint string_bytes;
610   char *filterp;
611   int ret;
612
613   ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
614   if (ret != ASN1_ERR_NOERROR)
615     return ret;
616   ret = asn1_octet_string_decode(a, &string2, &string2_length, &string_bytes);
617   if (ret != ASN1_ERR_NOERROR)
618     return ret;
619   *filter_length += 2 + strlen(operation) + string_length + string2_length;
620   *filter = g_realloc(*filter, *filter_length);
621   filterp = *filter + strlen(*filter);
622   *filterp++ = '(';
623   if (string_length != 0) {
624         memcpy(filterp, string, string_length);
625         filterp += string_length;
626   }
627   strcpy(filterp, operation);
628   filterp += strlen(operation);
629   if (string2_length != 0) {
630         memcpy(filterp, string2, string2_length);
631         filterp += string2_length;
632   }
633   *filterp++ = ')';
634   *filterp = '\0';
635   g_free(string);
636   g_free(string2);
637   return ASN1_ERR_NOERROR;
638 }
639
640 /* Richard Dawe: To parse substring filters, I added this function. */
641 static int parse_filter_substrings(ASN1_SCK *a, char **filter, guint *filter_length)
642 {
643   int end;
644   guchar *string;
645   char *filterp;
646   guint string_length;
647   guint string_bytes;
648   guint seq_len;
649   guint header_bytes;
650   int ret, any_valued;
651
652   /* For ASN.1 parsing of octet strings */
653   guint        cls;
654   guint        con;
655   guint        tag;
656   gboolean     def;
657
658   ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
659   if (ret != ASN1_ERR_NOERROR)
660     return ret;
661
662   ret = asn1_sequence_decode(a, &seq_len, &header_bytes);
663   if (ret != ASN1_ERR_NOERROR)
664     return ret;
665
666   *filter_length += 2 + 1 + string_length;
667   *filter = g_realloc(*filter, *filter_length);
668
669   filterp = *filter + strlen(*filter);
670   *filterp++ = '(';
671   if (string_length != 0) {
672     memcpy(filterp, string, string_length);
673     filterp += string_length;
674   }
675   *filterp++ = '=';
676   *filterp = '\0';
677   g_free(string);
678
679   /* Now decode seq_len's worth of octet strings. */
680   any_valued = 0;
681   end = a->offset + seq_len;
682
683   while (a->offset < end) {
684     /* Octet strings here are context-specific, which
685      * asn1_octet_string_decode() barfs on. Emulate it, but don't barf. */
686     ret = asn1_header_decode (a, &cls, &con, &tag, &def, &string_length);
687     if (ret != ASN1_ERR_NOERROR)
688       return ret;
689
690     /* XXX - check the tag? */
691     if (cls != ASN1_CTX || con != ASN1_PRI) {
692         /* XXX - handle the constructed encoding? */
693         return ASN1_ERR_WRONG_TYPE;
694     }
695     if (!def)
696         return ASN1_ERR_LENGTH_NOT_DEFINITE;
697
698     ret = asn1_string_value_decode(a, (int) string_length, &string);
699     if (ret != ASN1_ERR_NOERROR)
700       return ret;
701
702     /* If we have an 'any' component with a string value, we need to append
703      * an extra asterisk before final component. */
704     if ((tag == 1) && (string_length != 0))
705       any_valued = 1;
706
707     if ( (tag == 1) || ((tag == 2) && any_valued) )
708       (*filter_length)++;
709     *filter_length += string_length;
710     *filter = g_realloc(*filter, *filter_length);
711
712     filterp = *filter + strlen(*filter);
713     if ( (tag == 1) || ((tag == 2) && any_valued) )
714       *filterp++ = '*';
715     if (tag == 2)
716       any_valued = 0;
717     if (string_length != 0) {
718       memcpy(filterp, string, string_length);
719       filterp += string_length;
720     }
721     *filterp = '\0';
722     g_free(string);
723   }
724
725   if (any_valued)
726   {
727     (*filter_length)++;
728     *filter = g_realloc(*filter, *filter_length);
729     filterp = *filter + strlen(*filter);
730     *filterp++ = '*';
731   }
732
733   /* NB: Allocated byte for this earlier */
734   *filterp++ = ')';
735   *filterp = '\0';
736
737   return ASN1_ERR_NOERROR;
738 }
739
740 /* Returns -1 if we're at the end, returns an ASN1_ERR value otherwise. */
741 static int parse_filter(ASN1_SCK *a, char **filter, guint *filter_length,
742                         int *end)
743 {
744   guint cls, con, tag;
745   guint length;
746   gboolean def;
747   int ret;
748
749   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
750   if (ret != ASN1_ERR_NOERROR)
751     return ret;
752
753   if (*end == 0)
754   {
755     *end = a->offset + length;
756     *filter_length = 1;
757     *filter = g_malloc0(*filter_length);
758   }
759
760   if (cls == ASN1_CTX)  /* XXX - handle other types as errors? */
761   {
762     switch (tag)
763     {
764      case LDAP_FILTER_AND:
765       {
766         int add_end;
767
768         if (con != ASN1_CON)
769           return ASN1_ERR_WRONG_TYPE;
770         add_end = a->offset + length;
771         *filter_length += 3;
772         *filter = g_realloc(*filter, *filter_length);
773         strcat(*filter, "(&");
774         while ((ret = parse_filter(a, filter, filter_length, &add_end))
775                 == ASN1_ERR_NOERROR)
776           continue;
777         if (ret != -1)
778           return ret;
779         strcat(*filter, ")");
780       }
781       break;
782      case LDAP_FILTER_OR:
783       {
784         int or_end;
785
786         if (con != ASN1_CON)
787           return ASN1_ERR_WRONG_TYPE;
788         or_end = a->offset + length;
789         *filter_length += 3;
790         *filter = g_realloc(*filter, *filter_length);
791         strcat(*filter, "(|");
792         while ((ret = parse_filter(a, filter, filter_length, &or_end))
793                 == ASN1_ERR_NOERROR)
794           continue;
795         if (ret != -1)
796           return ret;
797         strcat(*filter, ")");
798       }
799       break;
800      case LDAP_FILTER_NOT:
801       {
802         int not_end;
803
804         if (con != ASN1_CON)
805           return ASN1_ERR_WRONG_TYPE;
806         not_end = a->offset + length;
807         *filter_length += 3;
808         *filter = g_realloc(*filter, *filter_length);
809         strcat(*filter, "(!");
810         ret = parse_filter(a, filter, filter_length, &not_end);
811         if (ret != -1 && ret != ASN1_ERR_NOERROR)
812           return ret;
813         strcat(*filter, ")");
814       }
815       break;
816      case LDAP_FILTER_EQUALITY:
817       if (con != ASN1_CON)
818         return ASN1_ERR_WRONG_TYPE;
819       ret = parse_filter_strings(a, filter, filter_length, "=");
820       if (ret != ASN1_ERR_NOERROR)
821         return ret;
822       break;
823      case LDAP_FILTER_GE:
824       if (con != ASN1_CON)
825         return ASN1_ERR_WRONG_TYPE;
826       ret = parse_filter_strings(a, filter, filter_length, ">=");
827       if (ret != ASN1_ERR_NOERROR)
828         return ret;
829       break;
830      case LDAP_FILTER_LE:
831       if (con != ASN1_CON)
832         return ASN1_ERR_WRONG_TYPE;
833       ret = parse_filter_strings(a, filter, filter_length, "<=");
834       if (ret != -1 && ret != ASN1_ERR_NOERROR)
835         return ret;
836       break;
837      case LDAP_FILTER_APPROX:
838       if (con != ASN1_CON)
839         return ASN1_ERR_WRONG_TYPE;
840       ret = parse_filter_strings(a, filter, filter_length, "~=");
841       if (ret != ASN1_ERR_NOERROR)
842         return ret;
843       break;
844      case LDAP_FILTER_PRESENT:
845       {
846         guchar *string;
847         char *filterp;
848
849         if (con != ASN1_PRI)
850           return ASN1_ERR_WRONG_TYPE;
851         ret = asn1_string_value_decode(a, length, &string);
852         if (ret != ASN1_ERR_NOERROR)
853           return ret;
854         *filter_length += 4 + length;
855         *filter = g_realloc(*filter, *filter_length);
856         filterp = *filter + strlen(*filter);
857         *filterp++ = '(';
858         if (length != 0) {
859           memcpy(filterp, string, length);
860           filterp += length;
861         }
862         *filterp++ = '=';
863         *filterp++ = '*';
864         *filterp++ = ')';
865         *filterp = '\0';
866         g_free(string);
867       }
868       break;
869      case LDAP_FILTER_SUBSTRINGS:
870       if (con != ASN1_CON)
871         return ASN1_ERR_WRONG_TYPE;
872       /* Richard Dawe: Handle substrings */
873       ret = parse_filter_substrings(a, filter, filter_length);
874       if (ret != ASN1_ERR_NOERROR)
875         return ret;
876       break;
877      default:
878       return ASN1_ERR_WRONG_TYPE;
879     }
880   }
881
882   if (a->offset == *end)
883     return -1;
884   else
885     return ASN1_ERR_NOERROR;
886 }
887
888 static gboolean read_filter(ASN1_SCK *a, proto_tree *tree, int hf_id)
889 {
890   int start = a->offset;
891   char *filter = 0;
892   guint filter_length = 0;
893   int end = 0;
894   int ret;
895
896   while ((ret = parse_filter(a, &filter, &filter_length, &end))
897         == ASN1_ERR_NOERROR)
898     continue;
899
900   if (tree) {
901     if (ret != -1) {
902       proto_tree_add_text(tree, a->tvb, start, 0,
903         "%s: ERROR: Can't parse filter: %s",
904         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
905     } else
906       proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset-start, filter);
907   }
908
909   g_free(filter);
910
911   return (ret == -1) ? TRUE : FALSE;
912 }
913
914 /********************************************************************************************/
915
916 static void dissect_ldap_result(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
917 {
918   guint resultCode = 0;
919   int ret;
920   if (read_integer(a, tree, hf_ldap_message_result, 0, &resultCode, ASN1_ENUM) != ASN1_ERR_NOERROR)
921     return;
922
923   if (resultCode != 0) {
924           if (check_col(pinfo->cinfo, COL_INFO))
925                   col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", 
926                                   val_to_str(resultCode, result_codes,
927                                              "Unknown (%u)"));
928   }
929
930   if (read_string(a, tree, hf_ldap_message_result_matcheddn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
931     return;
932   if (read_string(a, tree, hf_ldap_message_result_errormsg, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
933     return;
934
935   if (resultCode == 10)         /* Referral */
936   {
937     int start = a->offset;
938     int end;
939     guint length;
940     proto_item *ti;
941     proto_tree *referralTree;
942
943     ret = read_sequence(a, &length);
944     if (ret != ASN1_ERR_NOERROR) {
945       if (tree) {
946         proto_tree_add_text(tree, a->tvb, start, 0,
947             "ERROR: Couldn't parse referral URL sequence header: %s",
948             asn1_err_to_str(ret));
949       }
950       return;
951     }
952     ti = proto_tree_add_text(tree, a->tvb, start, length, "Referral URLs");
953     referralTree = proto_item_add_subtree(ti, ett_ldap_referrals);
954
955     end = a->offset + length;
956     while (a->offset < end) {
957       if (read_string(a, referralTree, hf_ldap_message_result_referral, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
958         return;
959     }
960   }
961 }
962
963 static void dissect_ldap_request_bind(ASN1_SCK *a, proto_tree *tree,
964     tvbuff_t *tvb, packet_info *pinfo, ldap_conv_info_t *ldap_info)
965 {
966   guint cls, con, tag;
967   gboolean def;
968   guint length;
969   int start;
970   int end;
971   int ret;
972   char *mechanism, *s = NULL;
973   int token_offset;
974   gint available_length, reported_length;
975   tvbuff_t *new_tvb;
976   proto_item *gitem;
977   proto_tree *gtree = NULL;
978
979   if (read_integer(a, tree, hf_ldap_message_bind_version, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
980     return;
981   if (read_string(a, tree, hf_ldap_message_bind_dn, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
982     return;
983
984   if (check_col(pinfo->cinfo, COL_INFO))
985     col_append_fstr(pinfo->cinfo, COL_INFO, ", DN=%s", s != NULL ? s : "(null)");
986   g_free(s);
987
988   start = a->offset;
989   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
990   if (ret == ASN1_ERR_NOERROR) {
991     if (cls != ASN1_CTX) {
992       /* RFCs 1777 and 2251 say these are context-specific types */
993       ret = ASN1_ERR_WRONG_TYPE;
994     }
995   }
996   if (ret != ASN1_ERR_NOERROR) {
997     proto_tree_add_text(tree, a->tvb, start, 0,
998       "%s: ERROR: Couldn't parse header: %s",
999       proto_registrar_get_name(hf_ldap_message_bind_auth),
1000       asn1_err_to_str(ret));
1001     return;
1002   }
1003   proto_tree_add_uint(tree, hf_ldap_message_bind_auth, a->tvb, start,
1004                         a->offset - start, tag);
1005   end = a->offset + length;
1006   switch (tag)
1007   {
1008    case LDAP_AUTH_SIMPLE:
1009     if (read_string_value(a, tree, hf_ldap_message_bind_auth_password, NULL,
1010                           NULL, start, length) != ASN1_ERR_NOERROR)
1011       return;
1012     break;
1013
1014     /* For Kerberos V4, dissect it as a ticket. */
1015
1016    case LDAP_AUTH_SASL:
1017     mechanism = NULL;
1018     if (read_string(a, tree, hf_ldap_message_bind_auth_mechanism, NULL,
1019                     &mechanism, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1020       return;
1021
1022     /*
1023      * We need to remember the authentication type and mechanism for this
1024      * conversation.
1025      *
1026      * XXX - actually, we might need to remember more than one
1027      * type and mechanism, if you can unbind and rebind with a
1028      * different type and/or mechanism.
1029      */
1030     ldap_info->auth_type = tag;
1031     ldap_info->auth_mech = mechanism;
1032     ldap_info->first_auth_frame = 0;    /* not known until we see the bind reply */
1033     /*
1034      * If the mechanism in this request is an empty string (which is
1035      * returned as a null pointer), use the saved mechanism instead.
1036      * Otherwise, if the saved mechanism is an empty string (null),
1037      * save this mechanism.
1038      */
1039     if (mechanism == NULL)
1040         mechanism = ldap_info->auth_mech;
1041     else {
1042       if (ldap_info->auth_mech == NULL) {
1043         g_free(ldap_info->auth_mech);
1044       }
1045       ldap_info->auth_mech = mechanism;
1046     }
1047
1048     if (a->offset < end) {
1049       if (mechanism != NULL && strcmp(mechanism, "GSS-SPNEGO") == 0) {
1050         /*
1051          * This is a GSS-API token ancapsulated within GSS-SPNEGO.
1052          * Find out how big it is by parsing the ASN.1 header for the
1053          * OCTET STREAM that contains it.
1054          */
1055         token_offset = a->offset;
1056         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
1057         if (ret != ASN1_ERR_NOERROR) {
1058           proto_tree_add_text(tree, a->tvb, token_offset, 0,
1059             "%s: ERROR: Couldn't parse header: %s",
1060             proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
1061             asn1_err_to_str(ret));
1062           return;
1063         }
1064         if (tree) {
1065           gitem = proto_tree_add_text(tree, tvb, token_offset,
1066             (a->offset + length) - token_offset, "GSS-API Token");
1067           gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1068         }
1069         available_length = tvb_length_remaining(tvb, token_offset);
1070         reported_length = tvb_reported_length_remaining(tvb, token_offset);
1071         g_assert(available_length >= 0);
1072         g_assert(reported_length >= 0);
1073         if (available_length > reported_length)
1074           available_length = reported_length;
1075         if ((guint)available_length > length)
1076           available_length = length;
1077         if ((guint)reported_length > length)
1078           reported_length = length;
1079         new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
1080         call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1081         a->offset += length;
1082       } else if (mechanism != NULL && strcmp(mechanism, "GSSAPI") == 0) {
1083         /*
1084          * This is a raw GSS-API token.
1085          * Find out how big it is by parsing the ASN.1 header for the
1086          * OCTET STREAM that contains it.
1087          */
1088         token_offset = a->offset;
1089         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
1090         if (ret != ASN1_ERR_NOERROR) {
1091           proto_tree_add_text(tree, a->tvb, token_offset, 0,
1092             "%s: ERROR: Couldn't parse header: %s",
1093             proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
1094             asn1_err_to_str(ret));
1095           return;
1096         }
1097         if (tree) {
1098           gitem = proto_tree_add_text(tree, tvb, token_offset,
1099             (a->offset + length) - token_offset, "GSS-API Token");
1100           gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1101         }
1102         if(length==0){
1103           /* for GSSAPI the third pdu will sometimes be "empty" */
1104           return;
1105         }
1106         available_length = tvb_length_remaining(tvb, token_offset);
1107         reported_length = tvb_reported_length_remaining(tvb, token_offset);
1108         g_assert(available_length >= 0);
1109         g_assert(reported_length >= 0);
1110         if (available_length > reported_length)
1111           available_length = reported_length;
1112         if ((guint)available_length > length)
1113           available_length = length;
1114         if ((guint)reported_length > length)
1115           reported_length = length;
1116         new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
1117         call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1118         a->offset += length;
1119       } else {
1120         if (read_bytestring(a, tree, hf_ldap_message_bind_auth_credentials,
1121                             NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1122           return;
1123       }
1124     }
1125     break;
1126   }
1127 }
1128
1129 static void dissect_ldap_response_bind(ASN1_SCK *a, proto_tree *tree,
1130                 int start, guint length, tvbuff_t *tvb, packet_info *pinfo, ldap_conv_info_t *ldap_info)
1131 {
1132   guint cls, con, tag;
1133   gboolean def;
1134   guint cred_length;
1135   int end;
1136   int ret;
1137   int token_offset;
1138   gint available_length, reported_length;
1139   tvbuff_t *new_tvb;
1140   proto_item *gitem;
1141   proto_tree *gtree = NULL;
1142
1143   end = start + length;
1144   dissect_ldap_result(a, tree, pinfo);
1145   if (a->offset < end) {
1146     switch (ldap_info->auth_type) {
1147
1148       /* For Kerberos V4, dissect it as a ticket. */
1149       /* XXX - what about LDAP_AUTH_SIMPLE? */
1150
1151     case LDAP_AUTH_SASL:
1152       /*
1153        * All frames after this are assumed to use a security layer.
1154        *
1155        * XXX - won't work if there's another reply, with the security
1156        * layer, starting in the same TCP segment that ends this
1157        * reply, but as LDAP is a request/response protocol, and
1158        * as the client probably can't start using authentication until
1159        * it gets the bind reply and the server won't send a reply until
1160        * it gets a request, that probably won't happen.
1161        *
1162        * XXX - that assumption is invalid; it's not clear where the
1163        * hell you find out whether there's any security layer.  In
1164        * one capture, we have two GSS-SPNEGO negotiations, both of
1165        * which select MS KRB5, and the only differences in the tokens
1166        * is in the RC4-HMAC ciphertext.  The various
1167        * draft-ietf--cat-sasl-gssapi-NN.txt drafts seem to imply
1168        * that the RFC 2222 spoo with the bitmask and maximum
1169        * output message size stuff is done - but where does that
1170        * stuff show up?  Is it in the ciphertext, which means it's
1171        * presumably encrypted?
1172        *
1173        * Grrr.  We have to do a gross heuristic, checking whether the
1174        * putative LDAP message begins with 0x00 or not, making the
1175        * assumption that we won't have more than 2^24 bytes of
1176        * encapsulated stuff.
1177        */
1178       ldap_info->first_auth_frame = pinfo->fd->num + 1;
1179       if (ldap_info->auth_mech != NULL &&
1180           strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) {
1181         /*
1182          * This is a GSS-API token.
1183          * Find out how big it is by parsing the ASN.1 header for the
1184          * OCTET STREAM that contains it.
1185          */
1186         token_offset = a->offset;
1187         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &cred_length);
1188         if (ret != ASN1_ERR_NOERROR) {
1189           proto_tree_add_text(tree, a->tvb, token_offset, 0,
1190             "%s: ERROR: Couldn't parse header: %s",
1191             proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
1192             asn1_err_to_str(ret));
1193           return;
1194         }
1195         if (tree) {
1196           gitem = proto_tree_add_text(tree, tvb, token_offset,
1197             (a->offset + cred_length) - token_offset, "GSS-API Token");
1198           gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1199         }
1200         available_length = tvb_length_remaining(tvb, token_offset);
1201         reported_length = tvb_reported_length_remaining(tvb, token_offset);
1202         g_assert(available_length >= 0);
1203         g_assert(reported_length >= 0);
1204         if (available_length > reported_length)
1205           available_length = reported_length;
1206         if ((guint)available_length > cred_length)
1207           available_length = cred_length;
1208         if ((guint)reported_length > cred_length)
1209           reported_length = cred_length;
1210         new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
1211         call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1212         a->offset += cred_length;
1213       } else if (ldap_info->auth_mech != NULL &&
1214           strcmp(ldap_info->auth_mech, "GSSAPI") == 0) {
1215         /*
1216          * This is a GSS-API token.
1217          * Find out how big it is by parsing the ASN.1 header for the
1218          * OCTET STREAM that contains it.
1219          */
1220         token_offset = a->offset;
1221         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &cred_length);
1222         if (ret != ASN1_ERR_NOERROR) {
1223           proto_tree_add_text(tree, a->tvb, token_offset, 0,
1224             "%s: ERROR: Couldn't parse header: %s",
1225             proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
1226             asn1_err_to_str(ret));
1227           return;
1228         }
1229         if (tree) {
1230           gitem = proto_tree_add_text(tree, tvb, token_offset,
1231             (a->offset + cred_length) - token_offset, "GSS-API Token");
1232           gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1233         }
1234         available_length = tvb_length_remaining(tvb, token_offset);
1235         reported_length = tvb_reported_length_remaining(tvb, token_offset);
1236         g_assert(available_length >= 0);
1237         g_assert(reported_length >= 0);
1238         if (available_length > reported_length)
1239           available_length = reported_length;
1240         if ((guint)available_length > cred_length)
1241           available_length = cred_length;
1242         if ((guint)reported_length > cred_length)
1243           reported_length = cred_length;
1244         new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
1245         call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1246         a->offset += cred_length;
1247       } else {
1248         if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1249                             NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1250           return;
1251       }
1252       break;
1253
1254     default:
1255       if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1256                           NULL, NULL, ASN1_CTX, 7) != ASN1_ERR_NOERROR)
1257         return;
1258       break;
1259     }
1260   }
1261 }
1262
1263 static void dissect_ldap_request_search(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
1264 {
1265   guint seq_length;
1266   int end;
1267   int ret;
1268   char *s = NULL;
1269
1270   if (read_string(a, tree, hf_ldap_message_search_base, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1271     return;
1272
1273   if (check_col(pinfo->cinfo, COL_INFO))
1274     col_append_fstr(pinfo->cinfo, COL_INFO, ", Base DN=%s", s != NULL ? s : "(null)");
1275   g_free(s);
1276
1277   if (read_integer(a, tree, hf_ldap_message_search_scope, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
1278     return;
1279   if (read_integer(a, tree, hf_ldap_message_search_deref, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
1280     return;
1281   if (read_integer(a, tree, hf_ldap_message_search_sizeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
1282     return;
1283   if (read_integer(a, tree, hf_ldap_message_search_timeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
1284     return;
1285   if (read_boolean(a, tree, hf_ldap_message_search_typesOnly, 0, 0) != ASN1_ERR_NOERROR)
1286     return;
1287   if (!read_filter(a, tree, hf_ldap_message_search_filter))
1288     return;
1289   ret = read_sequence(a, &seq_length);
1290   if (ret != ASN1_ERR_NOERROR) {
1291     if (tree) {
1292       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1293           "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1294           asn1_err_to_str(ret));
1295     }
1296     return;
1297   }
1298   end = a->offset + seq_length;
1299   while (a->offset < end) {
1300     if (read_string(a, tree, hf_ldap_message_attribute, 0, 0, 0, ASN1_UNI,
1301                     ASN1_OTS) != ASN1_ERR_NOERROR)
1302       return;
1303   }
1304 }
1305
1306 static int dissect_mscldap_string(tvbuff_t *tvb, int offset, char *str, int maxlen, gboolean prepend_dot)
1307 {
1308   guint8 len;
1309
1310   len=tvb_get_guint8(tvb, offset);
1311   offset+=1;
1312   *str=0;
1313
1314   while(len){
1315     /* add potential field separation dot */
1316     if(prepend_dot){
1317       if(!maxlen){
1318         *str=0;
1319         return offset;
1320       }
1321       maxlen--;
1322       *str++='.';
1323       *str=0;
1324     }
1325
1326     if(len==0xc0){
1327       int new_offset;
1328       /* ops its a mscldap compressed string */
1329
1330       new_offset=tvb_get_guint8(tvb, offset);
1331       offset+=1;
1332
1333       dissect_mscldap_string(tvb, new_offset, str, maxlen, FALSE);
1334
1335       return offset;
1336     }
1337
1338     prepend_dot=TRUE;
1339
1340     if(maxlen<=len){
1341       if(maxlen>3){
1342         *str++='.';
1343         *str++='.';
1344         *str++='.';
1345       }
1346       *str=0;
1347       return offset; /* will mess up offset in caller, is unlikely */
1348     }
1349     tvb_memcpy(tvb, str, offset, len);
1350     str+=len;
1351     *str=0;
1352     maxlen-=len;
1353     offset+=len;
1354
1355
1356     len=tvb_get_guint8(tvb, offset);
1357     offset+=1;
1358   }
1359   *str=0;
1360   return offset;
1361 }
1362
1363 static void dissect_mscldap_response_netlogon(proto_tree *tree, tvbuff_t *tvb)
1364 {
1365   int old_offset, offset=0;
1366   char str[256];
1367
1368 /*qqq*/
1369
1370   /* Type */
1371   /*XXX someone that knows what the type means should add that knowledge here*/
1372   proto_tree_add_item(tree, hf_mscldap_netlogon_type, tvb, offset, 4, TRUE);
1373   offset += 4;
1374
1375   /* Flags */
1376   /*XXX someone that knows what these flags are should add that knowledge here*/
1377   proto_tree_add_item(tree, hf_mscldap_netlogon_flags, tvb, offset, 4, TRUE);
1378   offset += 4;
1379
1380   /* Domain GUID */
1381   proto_tree_add_item(tree, hf_mscldap_domain_guid, tvb, offset, 16, TRUE);
1382   offset += 16;
1383
1384   /* Forest */
1385   old_offset=offset;
1386   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1387   proto_tree_add_string(tree, hf_mscldap_forest, tvb, old_offset, offset-old_offset, str);
1388   
1389   /* Domain */
1390   old_offset=offset;
1391   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1392   proto_tree_add_string(tree, hf_mscldap_domain, tvb, old_offset, offset-old_offset, str);
1393   
1394   /* Hostname */
1395   old_offset=offset;
1396   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1397   proto_tree_add_string(tree, hf_mscldap_hostname, tvb, old_offset, offset-old_offset, str);
1398   
1399   /* NetBios Domain */
1400   old_offset=offset;
1401   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1402   proto_tree_add_string(tree, hf_mscldap_nb_domain, tvb, old_offset, offset-old_offset, str);
1403   
1404   /* NetBios Hostname */
1405   old_offset=offset;
1406   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1407   proto_tree_add_string(tree, hf_mscldap_nb_hostname, tvb, old_offset, offset-old_offset, str);
1408   
1409   /* User */
1410   old_offset=offset;
1411   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1412   proto_tree_add_string(tree, hf_mscldap_username, tvb, old_offset, offset-old_offset, str);
1413   
1414   /* Site */
1415   old_offset=offset;
1416   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1417   proto_tree_add_string(tree, hf_mscldap_sitename, tvb, old_offset, offset-old_offset, str);
1418   
1419   /* Client Site */
1420   old_offset=offset;
1421   offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1422   proto_tree_add_string(tree, hf_mscldap_clientsitename, tvb, old_offset, offset-old_offset, str);
1423   
1424   /* Version */
1425   proto_tree_add_item(tree, hf_mscldap_netlogon_version, tvb, offset, 4, TRUE);
1426   offset += 4;
1427
1428   /* LM Token */
1429   proto_tree_add_item(tree, hf_mscldap_netlogon_lm_token, tvb, offset, 2, TRUE);
1430   offset += 2;
1431
1432   /* NT Token */
1433   proto_tree_add_item(tree, hf_mscldap_netlogon_nt_token, tvb, offset, 2, TRUE);
1434   offset += 2;
1435
1436 }
1437
1438 static void dissect_mscldap_response(proto_tree *tree, tvbuff_t *tvb, guint32 rpc)
1439 {
1440   switch(rpc){
1441   case MSCLDAP_RPC_NETLOGON:
1442     dissect_mscldap_response_netlogon(tree, tvb);
1443     break;
1444   default:
1445     proto_tree_add_text(tree, tvb, 0, tvb_length(tvb),
1446       "ERROR: Unknown type of MS-CLDAP RPC call");
1447   }
1448 }
1449
1450
1451 static void dissect_ldap_response_search_entry(ASN1_SCK *a, proto_tree *tree,
1452                 gboolean is_mscldap)
1453 {
1454   guint seq_length;
1455   int end_of_sequence;
1456   int ret;
1457   char *str=NULL;
1458   guint32 len;
1459   guint32 mscldap_rpc;
1460
1461   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1462     return;
1463   ret = read_sequence(a, &seq_length);
1464   if (ret != ASN1_ERR_NOERROR) {
1465     if (tree) {
1466       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1467           "ERROR: Couldn't parse search entry response sequence header: %s",
1468           asn1_err_to_str(ret));
1469     }
1470     return;
1471   }
1472
1473   end_of_sequence = a->offset + seq_length;
1474   while (a->offset < end_of_sequence)
1475   {
1476     proto_item *ti;
1477     proto_tree *attr_tree;
1478     guint set_length;
1479     int end_of_set;
1480
1481     ret = read_sequence(a, 0);
1482     if (ret != ASN1_ERR_NOERROR) {
1483       if (tree) {
1484         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1485             "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1486             asn1_err_to_str(ret));
1487       }
1488       return;
1489     }
1490     if (read_string(a, tree, hf_ldap_message_attribute, &ti, &str, &len, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1491       return;
1492
1493     mscldap_rpc=0;
1494     if(is_mscldap){
1495         if(!strncmp(str, "netlogon", 8)){
1496                 mscldap_rpc=MSCLDAP_RPC_NETLOGON;
1497         }
1498     }
1499     g_free(str);
1500     str=NULL;
1501
1502
1503     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1504
1505     ret = read_set(a, &set_length);
1506     if (ret != ASN1_ERR_NOERROR) {
1507       if (tree) {
1508         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1509             "ERROR: Couldn't parse LDAP value set header: %s",
1510             asn1_err_to_str(ret));
1511       }
1512       return;
1513     }
1514     end_of_set = a->offset + set_length;
1515     while (a->offset < end_of_set) {
1516       if(!is_mscldap){
1517         if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI,
1518                         ASN1_OTS) != ASN1_ERR_NOERROR){
1519           return;
1520         }
1521       } else {
1522         guint cls, con, tag;
1523         gboolean def;
1524         guint len;
1525         int start = a->offset;
1526         int ret;
1527         tvbuff_t *mscldap_tvb=NULL;
1528
1529         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &len);
1530         if (ret == ASN1_ERR_NOERROR) {
1531           if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1532             ret = ASN1_ERR_WRONG_TYPE;
1533         }
1534         if (ret != ASN1_ERR_NOERROR) {
1535           if (tree) {
1536             proto_tree_add_text(tree, a->tvb, start, 0,
1537               "%s: ERROR: Couldn't parse header: %s",
1538             proto_registrar_get_name(hf_ldap_message_value), asn1_err_to_str(ret));
1539           }
1540           return;
1541         }
1542         mscldap_tvb=tvb_new_subset(a->tvb, a->offset, len, len);
1543         dissect_mscldap_response(attr_tree, mscldap_tvb, mscldap_rpc);
1544         a->offset+=len;
1545       }
1546
1547     }
1548   }
1549 }
1550
1551 static void dissect_ldap_response_search_ref(ASN1_SCK *a, proto_tree *tree)
1552 {
1553   read_string(a, tree, hf_ldap_message_search_reference, 0, 0, 0, ASN1_UNI, ASN1_OTS);
1554 }
1555
1556 static void dissect_ldap_request_add(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
1557 {
1558   guint seq_length;
1559   int end_of_sequence;
1560   int ret;
1561   char *s = NULL;
1562
1563   if (read_string(a, tree, hf_ldap_message_dn, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1564     return;
1565
1566   if (check_col(pinfo->cinfo, COL_INFO))
1567     col_append_fstr(pinfo->cinfo, COL_INFO, ", DN=%s", s != NULL ? s : "(null)");
1568   g_free(s);  
1569
1570   ret = read_sequence(a, &seq_length);
1571   if (ret != ASN1_ERR_NOERROR) {
1572     if (tree) {
1573       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1574           "ERROR: Couldn't parse add request sequence header: %s",
1575           asn1_err_to_str(ret));
1576     }
1577     return;
1578   }
1579
1580   end_of_sequence = a->offset + seq_length;
1581   while (a->offset < end_of_sequence)
1582   {
1583     proto_item *ti;
1584     proto_tree *attr_tree;
1585     guint set_length;
1586     int end_of_set;
1587
1588     ret = read_sequence(a, 0);
1589     if (ret != ASN1_ERR_NOERROR) {
1590       if (tree) {
1591         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1592             "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1593             asn1_err_to_str(ret));
1594       }
1595       return;
1596     }
1597     if (read_string(a, tree, hf_ldap_message_attribute, &ti, 0, 0, ASN1_UNI,
1598                     ASN1_OTS) != ASN1_ERR_NOERROR)
1599       return;
1600     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1601
1602     ret = read_set(a, &set_length);
1603     if (ret != ASN1_ERR_NOERROR) {
1604       if (tree) {
1605         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1606             "ERROR: Couldn't parse LDAP value set header: %s",
1607             asn1_err_to_str(ret));
1608       }
1609       return;
1610     }
1611     end_of_set = a->offset + set_length;
1612     while (a->offset < end_of_set) {
1613       if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1614         return;
1615     }
1616   }
1617 }
1618
1619 static void dissect_ldap_request_delete(ASN1_SCK *a, proto_tree *tree,
1620                 int start, guint length)
1621 {
1622   read_string_value(a, tree, hf_ldap_message_dn, NULL, NULL, start, length);
1623 }
1624
1625 static void dissect_ldap_request_modifyrdn(ASN1_SCK *a, proto_tree *tree,
1626                 guint length)
1627 {
1628   int start = a->offset;
1629
1630   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1631     return;
1632   if (read_string(a, tree, hf_ldap_message_modrdn_name, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1633     return;
1634   if (read_boolean(a, tree, hf_ldap_message_modrdn_delete, 0, 0) != ASN1_ERR_NOERROR)
1635     return;
1636
1637   if (a->offset < (int) (start + length)) {
1638     /* LDAP V3 Modify DN operation, with newSuperior */
1639     /*      "newSuperior     [0] LDAPDN OPTIONAL" (0x80) */
1640     if (read_string(a, tree, hf_ldap_message_modrdn_superior, 0, 0, 0, ASN1_CTX, 0) != ASN1_ERR_NOERROR)
1641       return;
1642   }
1643 }
1644
1645 static void dissect_ldap_request_compare(ASN1_SCK *a, proto_tree *tree)
1646 {
1647   int start;
1648   int length;
1649   char *string1 = NULL;
1650   char *string2 = NULL;
1651   char *s1, *s2;
1652   char *compare;
1653   int ret;
1654
1655   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1656     return;
1657   ret = read_sequence(a, 0);
1658   if (ret != ASN1_ERR_NOERROR) {
1659     if (tree) {
1660       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1661           "ERROR: Couldn't parse compare request sequence header: %s",
1662           asn1_err_to_str(ret));
1663     }
1664     return;
1665   }
1666
1667   start = a->offset;
1668   ret = read_string(a, 0, -1, 0, &string1, 0, ASN1_UNI, ASN1_OTS);
1669   if (ret != ASN1_ERR_NOERROR) {
1670     if (tree) {
1671       proto_tree_add_text(tree, a->tvb, start, 0,
1672         "ERROR: Couldn't parse compare type: %s", asn1_err_to_str(ret));
1673     }
1674     return;
1675   }
1676   ret = read_string(a, 0, -1, 0, &string2, 0, ASN1_UNI, ASN1_OTS);
1677   if (ret != ASN1_ERR_NOERROR) {
1678     if (tree) {
1679       proto_tree_add_text(tree, a->tvb, start, 0,
1680         "ERROR: Couldn't parse compare value: %s", asn1_err_to_str(ret));
1681     }
1682     return;
1683   }
1684
1685   s1 = (string1 == NULL) ? "(null)" : string1;
1686   s2 = (string2 == NULL) ? "(null)" : string2;
1687   length = 2 + strlen(s1) + strlen(s2);
1688   compare = g_malloc0(length);
1689   snprintf(compare, length, "%s=%s", s1, s2);
1690   proto_tree_add_string(tree, hf_ldap_message_compare, a->tvb, start,
1691       a->offset-start, compare);
1692
1693   g_free(string1);
1694   g_free(string2);
1695   g_free(compare);
1696
1697   return;
1698 }
1699
1700 static void dissect_ldap_request_modify(ASN1_SCK *a, proto_tree *tree)
1701 {
1702   guint seq_length;
1703   int end_of_sequence;
1704   int ret;
1705
1706   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1707     return;
1708   ret = read_sequence(a, &seq_length);
1709   if (ret != ASN1_ERR_NOERROR) {
1710     if (tree) {
1711       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1712           "ERROR: Couldn't parse modify request sequence header: %s",
1713           asn1_err_to_str(ret));
1714     }
1715     return;
1716   }
1717   end_of_sequence = a->offset + seq_length;
1718   while (a->offset < end_of_sequence)
1719   {
1720     proto_item *ti;
1721     proto_tree *attr_tree;
1722     guint set_length;
1723     int end_of_set;
1724     guint operation;
1725
1726     ret = read_sequence(a, 0);
1727     if (ret != ASN1_ERR_NOERROR) {
1728       if (tree) {
1729         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1730             "ERROR: Couldn't parse modify request item sequence header: %s",
1731             asn1_err_to_str(ret));
1732       }
1733       return;
1734     }
1735     ret = read_integer(a, 0, -1, 0, &operation, ASN1_ENUM);
1736     if (ret != ASN1_ERR_NOERROR) {
1737       if (tree) {
1738         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1739           "ERROR: Couldn't parse modify operation: %s",
1740           asn1_err_to_str(ret));
1741         return;
1742       }
1743     }
1744     ret = read_sequence(a, 0);
1745     if (ret != ASN1_ERR_NOERROR) {
1746       if (tree) {
1747         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1748             "ERROR: Couldn't parse modify request operation sequence header: %s",
1749             asn1_err_to_str(ret));
1750       }
1751       return;
1752     }
1753
1754     switch (operation)
1755     {
1756      case LDAP_MOD_ADD:
1757       if (read_string(a, tree, hf_ldap_message_modify_add, &ti, 0, 0, ASN1_UNI,
1758                       ASN1_OTS) != ASN1_ERR_NOERROR)
1759         return;
1760       break;
1761
1762      case LDAP_MOD_REPLACE:
1763       if (read_string(a, tree, hf_ldap_message_modify_replace, &ti, 0, 0,
1764                       ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1765         return;
1766       break;
1767
1768      case LDAP_MOD_DELETE:
1769       if (read_string(a, tree, hf_ldap_message_modify_delete, &ti, 0, 0,
1770                       ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1771         return;
1772       break;
1773
1774      default:
1775        proto_tree_add_text(tree, a->tvb, a->offset, 0,
1776             "Unknown LDAP modify operation (%u)", operation);
1777        return;
1778     }
1779     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1780
1781     ret = read_set(a, &set_length);
1782     if (ret != ASN1_ERR_NOERROR) {
1783       if (tree) {
1784         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1785             "ERROR: Couldn't parse LDAP value set header: %s",
1786             asn1_err_to_str(ret));
1787       }
1788       return;
1789     }
1790     end_of_set = a->offset + set_length;
1791     while (a->offset < end_of_set) {
1792       if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI,
1793                       ASN1_OTS) != ASN1_ERR_NOERROR)
1794         return;
1795     }
1796   }
1797 }
1798
1799 static void dissect_ldap_request_abandon(ASN1_SCK *a, proto_tree *tree,
1800                 int start, guint length)
1801 {
1802   read_integer_value(a, tree, hf_ldap_message_abandon_msgid, NULL, NULL,
1803                             start, length);
1804 }
1805
1806 static ldap_call_response_t *
1807 ldap_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ldap_conv_info_t *ldap_info, guint messageId, guint protocolOpTag)
1808 {
1809   ldap_call_response_t lcr, *lcrp=NULL;
1810
1811   if (!pinfo->fd->flags.visited) {
1812     switch(protocolOpTag){
1813       case LDAP_REQ_BIND:
1814       case LDAP_REQ_SEARCH:
1815       case LDAP_REQ_MODIFY:
1816       case LDAP_REQ_ADD:
1817       case LDAP_REQ_DELETE:
1818       case LDAP_REQ_MODRDN:
1819       case LDAP_REQ_COMPARE:
1820       /*case LDAP_REQ_ABANDON: we dont match for this one*/
1821       /*case LDAP_REQ_UNBIND: we dont match for this one*/
1822         /* check that we dont already have one of those in the
1823            unmatched list and if so remove it */
1824         lcr.messageId=messageId;
1825         lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
1826         if(lcrp){
1827           g_hash_table_remove(ldap_info->unmatched, lcrp);
1828         }
1829         /* if we cant reuse the old one, grab a new chunk */
1830         if(!lcrp){
1831           lcrp=g_mem_chunk_alloc(ldap_call_response_chunk);
1832         }
1833         lcrp->messageId=messageId;
1834         lcrp->req_frame=pinfo->fd->num;
1835         lcrp->req_time.secs=pinfo->fd->abs_secs;
1836         lcrp->req_time.nsecs=pinfo->fd->abs_usecs*1000;
1837         lcrp->rep_frame=0;
1838         lcrp->protocolOpTag=protocolOpTag;
1839         lcrp->is_request=TRUE;
1840         g_hash_table_insert(ldap_info->unmatched, lcrp, lcrp);
1841         return NULL;
1842         break;
1843       case LDAP_RES_BIND:
1844       case LDAP_RES_SEARCH_ENTRY:
1845       case LDAP_RES_SEARCH_REF:
1846       case LDAP_RES_SEARCH_RESULT:
1847       case LDAP_RES_MODIFY:
1848       case LDAP_RES_ADD:
1849       case LDAP_RES_DELETE:
1850       case LDAP_RES_MODRDN:
1851       case LDAP_RES_COMPARE:
1852         lcr.messageId=messageId;
1853         lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
1854         if(lcrp){
1855           if(!lcrp->rep_frame){
1856             g_hash_table_remove(ldap_info->unmatched, lcrp);
1857             lcrp->rep_frame=pinfo->fd->num;
1858             lcrp->is_request=FALSE;
1859             g_hash_table_insert(ldap_info->matched, lcrp, lcrp);
1860           }
1861         }
1862     }
1863   }
1864
1865   if(!lcrp){
1866     lcr.messageId=messageId;
1867     switch(protocolOpTag){
1868       case LDAP_REQ_BIND:
1869       case LDAP_REQ_SEARCH:
1870       case LDAP_REQ_MODIFY:
1871       case LDAP_REQ_ADD:
1872       case LDAP_REQ_DELETE:
1873       case LDAP_REQ_MODRDN:
1874       case LDAP_REQ_COMPARE:
1875       /*case LDAP_REQ_ABANDON: we dont match for this one*/
1876       /*case LDAP_REQ_UNBIND: we dont match for this one*/
1877         lcr.is_request=TRUE;
1878         lcr.req_frame=pinfo->fd->num;
1879         lcr.rep_frame=0;
1880         break;
1881       case LDAP_RES_BIND:
1882       case LDAP_RES_SEARCH_ENTRY:
1883       case LDAP_RES_SEARCH_REF:
1884       case LDAP_RES_SEARCH_RESULT:
1885       case LDAP_RES_MODIFY:
1886       case LDAP_RES_ADD:
1887       case LDAP_RES_DELETE:
1888       case LDAP_RES_MODRDN:
1889       case LDAP_RES_COMPARE:
1890         lcr.is_request=FALSE;
1891         lcr.req_frame=0;
1892         lcr.rep_frame=pinfo->fd->num;
1893         break;
1894     }
1895     lcrp=g_hash_table_lookup(ldap_info->matched, &lcr);
1896     if(lcrp){
1897       lcrp->is_request=lcr.is_request;
1898     }
1899   }
1900   if(lcrp){
1901     if(lcrp->is_request){
1902       proto_tree_add_uint(tree, hf_ldap_response_in, tvb, 0, 0, lcrp->rep_frame);
1903     } else {
1904       nstime_t ns;
1905       proto_tree_add_uint(tree, hf_ldap_response_to, tvb, 0, 0, lcrp->req_frame);
1906       ns.secs=pinfo->fd->abs_secs-lcrp->req_time.secs;
1907       ns.nsecs=pinfo->fd->abs_usecs*1000-lcrp->req_time.nsecs;
1908       if(ns.nsecs<0){
1909         ns.nsecs+=1000000000;
1910         ns.secs--;
1911       }
1912       proto_tree_add_time(tree, hf_ldap_time, tvb, 0, 0, &ns);
1913     }
1914     return lcrp;
1915   }
1916   return NULL;
1917 }
1918
1919
1920 static void
1921 dissect_ldap_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1922                 proto_tree *ldap_tree, proto_item *ldap_item, 
1923                 gboolean first_time, ldap_conv_info_t *ldap_info,
1924                 gboolean is_mscldap)
1925 {
1926   int message_id_start;
1927   int message_id_length;
1928   guint messageLength;
1929   guint messageId;
1930   int next_offset;
1931   guint protocolOpCls, protocolOpCon, protocolOpTag;
1932   gchar *typestr;
1933   guint opLen;
1934   ASN1_SCK a;
1935   int start;
1936   int ret;
1937   ldap_call_response_t *lcrp;
1938
1939   asn1_open(&a, tvb, offset);
1940
1941   ret = read_sequence(&a, &messageLength);
1942   if (ret != ASN1_ERR_NOERROR)
1943   {
1944     if (first_time)
1945     {
1946       if (check_col(pinfo->cinfo, COL_INFO))
1947       {
1948         col_add_fstr(pinfo->cinfo, COL_INFO,
1949                     "Invalid LDAP message (Can't parse sequence header: %s)",
1950                     asn1_err_to_str(ret));
1951       }
1952     }
1953     if (ldap_tree)
1954     {
1955       proto_tree_add_text(ldap_tree, tvb, offset, -1,
1956                           "Invalid LDAP message (Can't parse sequence header: %s)",
1957                           asn1_err_to_str(ret));
1958     }
1959     return;
1960   }
1961
1962   message_id_start = a.offset;
1963   ret = read_integer(&a, 0, hf_ldap_message_id, 0, &messageId, ASN1_INT);
1964   if (ret != ASN1_ERR_NOERROR)
1965   {
1966     if (first_time && check_col(pinfo->cinfo, COL_INFO))
1967       col_add_fstr(pinfo->cinfo, COL_INFO, "Invalid LDAP packet (Can't parse Message ID: %s)",
1968                    asn1_err_to_str(ret));
1969     if (ldap_tree)
1970       proto_tree_add_text(ldap_tree, tvb, message_id_start, 1,
1971                           "Invalid LDAP packet (Can't parse Message ID: %s)",
1972                           asn1_err_to_str(ret));
1973       return;
1974   }
1975   message_id_length = a.offset - message_id_start;
1976
1977   start = a.offset;
1978   asn1_id_decode(&a, &protocolOpCls, &protocolOpCon, &protocolOpTag);
1979   if (protocolOpCls != ASN1_APL)
1980     typestr = "Bad message type (not Application)";
1981   else
1982     typestr = val_to_str(protocolOpTag, msgTypes, "Unknown message type (%u)");
1983
1984   if (first_time)
1985   {
1986     if (check_col(pinfo->cinfo, COL_INFO))
1987       col_add_fstr(pinfo->cinfo, COL_INFO, "MsgId=%u %s",
1988                    messageId, typestr);
1989   }
1990
1991   if (ldap_item)
1992           proto_item_append_text(ldap_item, ", %s", 
1993                                  val_to_str(protocolOpTag, msgTypes,
1994                                             "Unknown message type (%u)"));
1995
1996   if (ldap_tree)
1997   {
1998     proto_tree_add_uint(ldap_tree, hf_ldap_message_id, tvb, message_id_start, message_id_length, messageId);
1999     if (protocolOpCls == ASN1_APL)
2000     {
2001       proto_tree_add_uint(ldap_tree, hf_ldap_message_type, tvb,
2002                           start, a.offset - start, protocolOpTag);
2003     }
2004     else
2005     {
2006       proto_tree_add_text(ldap_tree, tvb, start, a.offset - start,
2007                           "%s", typestr);
2008     }
2009   }
2010   start = a.offset;
2011   if (read_length(&a, ldap_tree, hf_ldap_message_length, &opLen) != ASN1_ERR_NOERROR)
2012     return;
2013
2014   if (protocolOpCls == ASN1_APL)
2015   {
2016     lcrp=ldap_match_call_response(tvb, pinfo, ldap_tree, ldap_info, messageId, protocolOpTag);
2017     if(lcrp){
2018       tap_queue_packet(ldap_tap, pinfo, lcrp);
2019     }
2020
2021     switch (protocolOpTag)
2022     {
2023      case LDAP_REQ_BIND:
2024       dissect_ldap_request_bind(&a, ldap_tree, tvb, pinfo, ldap_info);
2025       break;
2026      case LDAP_REQ_UNBIND:
2027       /* Nothing to dissect */
2028       break;
2029      case LDAP_REQ_SEARCH:
2030       dissect_ldap_request_search(&a, ldap_tree, pinfo);
2031       break;
2032      case LDAP_REQ_MODIFY:
2033       dissect_ldap_request_modify(&a, ldap_tree);
2034       break;
2035      case LDAP_REQ_ADD:
2036       dissect_ldap_request_add(&a, ldap_tree, pinfo);
2037       break;
2038      case LDAP_REQ_DELETE:
2039       dissect_ldap_request_delete(&a, ldap_tree, start, opLen);
2040       break;
2041      case LDAP_REQ_MODRDN:
2042       dissect_ldap_request_modifyrdn(&a, ldap_tree, opLen);
2043       break;
2044      case LDAP_REQ_COMPARE:
2045       dissect_ldap_request_compare(&a, ldap_tree);
2046       break;
2047      case LDAP_REQ_ABANDON:
2048       dissect_ldap_request_abandon(&a, ldap_tree, start, opLen);
2049       break;
2050      case LDAP_RES_BIND:
2051       dissect_ldap_response_bind(&a, ldap_tree, start, opLen, tvb, pinfo, ldap_info);
2052       break;
2053      case LDAP_RES_SEARCH_ENTRY: {
2054             /*
2055              * XXX - this assumes that the LDAP_RES_SEARCH_ENTRY and
2056              * LDAP_RES_SEARCH_RESULT appear in the same frame.
2057              */
2058             guint32 *num_results = p_get_proto_data(pinfo->fd, proto_ldap);
2059
2060             if (!num_results) {
2061                     num_results = g_malloc(sizeof(guint32));
2062                     *num_results = 0;
2063                     p_add_proto_data(pinfo->fd, proto_ldap, num_results);
2064             }
2065
2066             *num_results += 1;
2067             dissect_ldap_response_search_entry(&a, ldap_tree, is_mscldap);
2068
2069             break;
2070      }
2071      case LDAP_RES_SEARCH_REF:
2072       dissect_ldap_response_search_ref(&a, ldap_tree);
2073       break;
2074
2075      case LDAP_RES_SEARCH_RESULT: {
2076              guint32 *num_results = p_get_proto_data(pinfo->fd, proto_ldap);
2077
2078              if (num_results) {
2079                      if (check_col(pinfo->cinfo, COL_INFO))
2080                              col_append_fstr(pinfo->cinfo, COL_INFO, ", %d result%s", 
2081                                              *num_results, *num_results == 1 ? "" : "s");
2082                      g_free(num_results);
2083                      p_rem_proto_data(pinfo->fd, proto_ldap);
2084              }
2085
2086              dissect_ldap_result(&a, ldap_tree, pinfo);
2087
2088              break;
2089      }
2090
2091      case LDAP_RES_MODIFY:
2092      case LDAP_RES_ADD:
2093      case LDAP_RES_DELETE:
2094      case LDAP_RES_MODRDN:
2095      case LDAP_RES_COMPARE:
2096         dissect_ldap_result(&a, ldap_tree, pinfo);
2097       break;
2098      default:
2099       if (ldap_tree)
2100       {
2101         proto_tree_add_text(ldap_tree, a.tvb, a.offset, opLen,
2102                             "Unknown LDAP operation (%u)", protocolOpTag);
2103       }
2104       break;
2105     }
2106   }
2107
2108   /*
2109    * XXX - what if "next_offset" is past the offset of the next top-level
2110    * sequence?  Show that as an error?
2111    */
2112   asn1_close(&a, &next_offset); /* XXX - use the new value of next_offset? */
2113 }
2114
2115
2116 static void
2117 dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_mscldap)
2118 {
2119   int offset = 0;
2120   gboolean first_time = TRUE;
2121   conversation_t *conversation;
2122   gboolean doing_sasl_security = FALSE;
2123   guint length_remaining;
2124   guint32 sasl_length;
2125   guint32 message_data_len;
2126   proto_item *ti = NULL;
2127   proto_tree *ldap_tree = NULL;
2128   ASN1_SCK a;
2129   int ret;
2130   guint messageLength;
2131   int messageOffset;
2132   guint headerLength;
2133   guint length;
2134   gint available_length, reported_length;
2135   int len;
2136   proto_item *gitem = NULL;
2137   proto_tree *gtree = NULL;
2138   tvbuff_t *next_tvb;
2139   ldap_conv_info_t *ldap_info=NULL;
2140
2141
2142   /*
2143    * Do we have a conversation for this connection?
2144    */
2145   conversation = find_conversation(&pinfo->src, &pinfo->dst,
2146                                    pinfo->ptype, pinfo->srcport,
2147                                    pinfo->destport, 0);
2148   if (conversation == NULL) {
2149     /* We don't yet have a conversation, so create one. */
2150     conversation = conversation_new(&pinfo->src, &pinfo->dst,
2151                                     pinfo->ptype, pinfo->srcport,
2152                                     pinfo->destport, 0);
2153   }
2154   /*
2155    * Do we already have a type and mechanism?
2156    */
2157   ldap_info = conversation_get_proto_data(conversation, proto_ldap);
2158   if (ldap_info == NULL) {
2159     /* No.  Attach that information to the conversation, and add
2160        it to the list of information structures. */
2161     ldap_info = g_mem_chunk_alloc(ldap_conv_info_chunk);
2162     ldap_info->auth_type = 0;
2163     ldap_info->auth_mech = 0;
2164     ldap_info->first_auth_frame = 0;
2165     ldap_info->matched=g_hash_table_new(ldap_info_hash_matched, ldap_info_equal_matched);
2166     ldap_info->unmatched=g_hash_table_new(ldap_info_hash_unmatched, ldap_info_equal_unmatched);
2167     conversation_add_proto_data(conversation, proto_ldap, ldap_info);
2168     ldap_info->next = ldap_info_items;
2169     ldap_info_items = ldap_info;
2170   } 
2171
2172   switch (ldap_info->auth_type) {
2173     case LDAP_AUTH_SASL:
2174       /*
2175        * It's SASL; are we using a security layer?
2176        */
2177       if (ldap_info->first_auth_frame != 0 &&
2178           pinfo->fd->num >= ldap_info->first_auth_frame)
2179         doing_sasl_security = TRUE;     /* yes */
2180   }
2181
2182
2183
2184
2185   while (tvb_reported_length_remaining(tvb, offset) > 0) {
2186     /*
2187      * This will throw an exception if we don't have any data left.
2188      * That's what we want.  (See "tcp_dissect_pdus()", which is
2189      * similar, but doesn't have to deal with the SASL issues.
2190      * XXX - can we make "tcp_dissect_pdus()" provide enough information
2191      * to the "get_pdu_len" routine so that we could have one dealing
2192      * with the SASL issues, have that routine deal with SASL and
2193      * ASN.1, and just use "tcp_dissect_pdus()"?)
2194      */
2195     length_remaining = tvb_ensure_length_remaining(tvb, offset);
2196
2197     /*
2198      * Might we be doing a SASL security layer and, if so, *are* we doing
2199      * one?
2200      *
2201      * Just because we've seen a bind reply for SASL, that doesn't mean
2202      * that we're using a SASL security layer; I've seen captures in
2203      * which some SASL negotiations lead to a security layer being used
2204      * and other negotiations don't, and it's not obvious what's different
2205      * in the two negotiations.  Therefore, we assume that if the first
2206      * byte is 0, it's a length for a SASL security layer (that way, we
2207      * never reassemble more than 16 megabytes, protecting us from
2208      * chewing up *too* much memory), and otherwise that it's an LDAP
2209      * message (actually, if it's an LDAP message it should begin with 0x30,
2210      * but we want to parse garbage as LDAP messages rather than really
2211      * huge lengths).
2212      */
2213     if (doing_sasl_security && tvb_get_guint8(tvb, offset) == 0) {
2214       /*
2215        * Yes.  The frame begins with a 4-byte big-endian length.
2216        * Can we do reassembly?
2217        */
2218       if (ldap_desegment && pinfo->can_desegment) {
2219         /*
2220          * Yes - is the SASL length split across segment boundaries?
2221          */
2222         if (length_remaining < 4) {
2223           /*
2224            * Yes.  Tell the TCP dissector where the data for this message
2225            * starts in the data it handed us, and how many more bytes we
2226            * need, and return.
2227            */
2228           pinfo->desegment_offset = offset;
2229           pinfo->desegment_len = 4 - length_remaining;
2230           return;
2231         }
2232       }
2233
2234       /*
2235        * Get the SASL length, which is the length of data in the buffer
2236        * following the length (i.e., it's 4 less than the total length).
2237        *
2238        * XXX - do we need to reassemble buffers?  For now, we
2239        * assume that each LDAP message is entirely contained within
2240        * a buffer.
2241        */
2242       sasl_length = tvb_get_ntohl(tvb, offset);
2243       message_data_len = sasl_length + 4;
2244       if (message_data_len < 4) {
2245         /*
2246          * The message length was probably so large that the total length
2247          * overflowed.
2248          *
2249          * Report this as an error.
2250          */
2251         show_reported_bounds_error(tvb, pinfo, tree);
2252         return;
2253       }
2254
2255       /*
2256        * Is the buffer split across segment boundaries?
2257        */
2258       if (length_remaining < message_data_len) {
2259         /* provide a hint to TCP where the next PDU starts */
2260         pinfo->want_pdu_tracking=2;
2261         pinfo->bytes_until_next_pdu=message_data_len-length_remaining;
2262         /*
2263          * Can we do reassembly?
2264          */
2265         if (ldap_desegment && pinfo->can_desegment) {
2266           /*
2267            * Yes.  Tell the TCP dissector where the data for this message
2268            * starts in the data it handed us, and how many more bytes we
2269            * need, and return.
2270            */
2271           pinfo->desegment_offset = offset;
2272           pinfo->desegment_len = message_data_len - length_remaining;
2273           return;
2274         }
2275       }
2276
2277       /*
2278        * Construct a tvbuff containing the amount of the payload we have
2279        * available.  Make its reported length the amount of data in the PDU.
2280        *
2281        * XXX - if reassembly isn't enabled. the subdissector will throw a
2282        * BoundsError exception, rather than a ReportedBoundsError exception.
2283        * We really want a tvbuff where the length is "length", the reported
2284        * length is "plen", and the "if the snapshot length were infinite"
2285        * length is the minimum of the reported length of the tvbuff handed
2286        * to us and "plen", with a new type of exception thrown if the offset
2287        * is within the reported length but beyond that third length, with
2288        * that exception getting the "Unreassembled Packet" error.
2289        */
2290       length = length_remaining;
2291       if (length > message_data_len)
2292         length = message_data_len;
2293       next_tvb = tvb_new_subset(tvb, offset, length, message_data_len);
2294
2295       /*
2296        * If this is the first PDU, set the Protocol column and clear the
2297        * Info column.
2298        */
2299       if (first_time)
2300       {
2301         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2302           col_set_str(pinfo->cinfo, COL_PROTOCOL, (gchar *)pinfo->current_proto);
2303         if (check_col(pinfo->cinfo, COL_INFO))
2304           col_clear(pinfo->cinfo, COL_INFO);
2305       }
2306
2307       if (tree)
2308       {
2309         ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
2310         ldap_tree = proto_item_add_subtree(ti, ett_ldap);
2311
2312         proto_tree_add_uint(ldap_tree, hf_ldap_sasl_buffer_length, tvb, 0, 4,
2313                             sasl_length);
2314       }
2315
2316       if (ldap_info->auth_mech != NULL &&
2317           strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) {
2318           /*
2319            * This is GSS-API (using SPNEGO, but we should be done with
2320            * the negotiation by now).
2321            *
2322            * Dissect the GSS_Wrap() token; it'll return the length of
2323            * the token, from which we compute the offset in the tvbuff at
2324            * which the plaintext data, i.e. the LDAP message, begins.
2325            */
2326           available_length = tvb_length_remaining(tvb, 4);
2327           reported_length = tvb_reported_length_remaining(tvb, 4);
2328           g_assert(available_length >= 0);
2329           g_assert(reported_length >= 0);
2330           if (available_length > reported_length)
2331             available_length = reported_length;
2332           if ((guint)available_length > sasl_length - 4)
2333             available_length = sasl_length - 4;
2334           if ((guint)reported_length > sasl_length - 4)
2335             reported_length = sasl_length - 4;
2336           next_tvb = tvb_new_subset(tvb, 4, available_length, reported_length);
2337           if (tree)
2338           {
2339             gitem = proto_tree_add_text(ldap_tree, next_tvb, 0, -1, "GSS-API Token");
2340             gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
2341           }
2342           len = call_dissector(gssapi_wrap_handle, next_tvb, pinfo, gtree);
2343           /*
2344            * if len is 0 it probably mean that we got a PDU that is not
2345            * aligned to the start of the segment.
2346            */
2347           if(len==0){
2348              return;
2349           }
2350           if (gitem != NULL)
2351               proto_item_set_len(gitem, len);
2352
2353           /*
2354            * Now dissect the LDAP message.
2355            */
2356           dissect_ldap_message(tvb, 4 + len, pinfo, ldap_tree, ti, first_time, ldap_info, is_mscldap);
2357       } else {
2358         /*
2359          * We don't know how to handle other authentication mechanisms
2360          * yet, so just put in an entry for the SASL buffer.
2361          */
2362         proto_tree_add_text(ldap_tree, tvb, 4, -1, "SASL buffer");
2363       }
2364       offset += message_data_len;
2365     } else {
2366       /*
2367        * No, we're not doing a SASL security layer.  The frame begins
2368        * with a "Sequence Of" header.
2369        * Can we do reassembly?
2370        */
2371       if (ldap_desegment && pinfo->can_desegment) {
2372         /*
2373          * Yes - is the "Sequence Of" header split across segment
2374          * boundaries?  We require at least 6 bytes for the header
2375          * which allows for a 4 byte length (ASN.1 BER).
2376          */
2377         if (length_remaining < 6) {
2378           pinfo->desegment_offset = offset;
2379           pinfo->desegment_len = 6 - length_remaining;
2380           return;
2381         }
2382       }
2383
2384       /* It might still be a packet containing a SASL security layer
2385        * but its just that we never saw the BIND packet.
2386        * check if it looks like it could be a SASL blob here
2387        * and in that case just assume it is GSS-SPNEGO
2388        */
2389       if( (tvb_bytes_exist(tvb, offset, 5))
2390         &&(tvb_get_ntohl(tvb, offset)<=(guint)(tvb_reported_length_remaining(tvb, offset)-4))
2391         &&(tvb_get_guint8(tvb, offset+4)==0x60) ){
2392          ldap_info->auth_type=LDAP_AUTH_SASL;
2393          ldap_info->first_auth_frame=pinfo->fd->num;
2394          ldap_info->auth_mech=g_strdup("GSS-SPNEGO");
2395          doing_sasl_security=TRUE;
2396          continue;
2397       }
2398
2399
2400       /*
2401        * OK, try to read the "Sequence Of" header; this gets the total
2402        * length of the LDAP message.
2403        */
2404       asn1_open(&a, tvb, offset);
2405       ret = read_sequence(&a, &messageLength);
2406       asn1_close(&a, &messageOffset);
2407
2408       if (ret == ASN1_ERR_NOERROR) {
2409         /*
2410          * Add the length of the "Sequence Of" header to the message
2411          * length.
2412          */
2413         headerLength = messageOffset - offset;
2414         messageLength += headerLength;
2415         if (messageLength < headerLength) {
2416           /*
2417            * The message length was probably so large that the total length
2418            * overflowed.
2419            *
2420            * Report this as an error.
2421            */
2422           show_reported_bounds_error(tvb, pinfo, tree);
2423           return;
2424         }
2425       } else {
2426         /*
2427          * We couldn't parse the header; just make it the amount of data
2428          * remaining in the tvbuff, so we'll give up on this segment
2429          * after attempting to parse the message - there's nothing more
2430          * we can do.  "dissect_ldap_message()" will display the error.
2431          */
2432         messageLength = length_remaining;
2433       }
2434
2435       /*
2436        * Is the message split across segment boundaries?
2437        */
2438       if (length_remaining < messageLength) {
2439         /* provide a hint to TCP where the next PDU starts */
2440         pinfo->want_pdu_tracking=2;
2441         pinfo->bytes_until_next_pdu=messageLength-length_remaining;
2442         /*
2443          * Can we do reassembly?
2444          */
2445         if (ldap_desegment && pinfo->can_desegment) {
2446           /*
2447            * Yes.  Tell the TCP dissector where the data for this message
2448            * starts in the data it handed us, and how many more bytes
2449            * we need, and return.
2450            */
2451           pinfo->desegment_offset = offset;
2452           pinfo->desegment_len = messageLength - length_remaining;
2453           return;
2454         }
2455       }
2456
2457       /*
2458        * If this is the first PDU, set the Protocol column and clear the
2459        * Info column.
2460        */
2461       if (first_time) {
2462         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2463           col_set_str(pinfo->cinfo, COL_PROTOCOL, (gchar *)pinfo->current_proto);
2464         if (check_col(pinfo->cinfo, COL_INFO))
2465           col_clear(pinfo->cinfo, COL_INFO);
2466       }
2467
2468       /*
2469        * Construct a tvbuff containing the amount of the payload we have
2470        * available.  Make its reported length the amount of data in the
2471        * LDAP message.
2472        *
2473        * XXX - if reassembly isn't enabled. the subdissector will throw a
2474        * BoundsError exception, rather than a ReportedBoundsError exception.
2475        * We really want a tvbuff where the length is "length", the reported
2476        * length is "plen", and the "if the snapshot length were infinite"
2477        * length is the minimum of the reported length of the tvbuff handed
2478        * to us and "plen", with a new type of exception thrown if the offset
2479        * is within the reported length but beyond that third length, with
2480        * that exception getting the "Unreassembled Packet" error.
2481        */
2482       length = length_remaining;
2483       if (length > messageLength)
2484         length = messageLength;
2485       next_tvb = tvb_new_subset(tvb, offset, length, messageLength);
2486
2487       /*
2488        * Now dissect the LDAP message.
2489        */
2490       if (tree) {
2491         ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
2492         ldap_tree = proto_item_add_subtree(ti, ett_ldap);
2493       } else
2494         ldap_tree = NULL;
2495       dissect_ldap_message(next_tvb, 0, pinfo, ldap_tree, ti, first_time, ldap_info, is_mscldap);
2496
2497       offset += messageLength;
2498     }
2499
2500     first_time = FALSE;
2501   }
2502 }
2503
2504
2505
2506 static void
2507 dissect_ldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2508 {
2509         dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
2510         return;
2511 }
2512
2513 static void
2514 dissect_mscldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2515 {
2516         dissect_ldap_pdu(tvb, pinfo, tree, TRUE);
2517         return;
2518 }
2519
2520 static void
2521 ldap_reinit(void)
2522 {
2523   ldap_conv_info_t *ldap_info;
2524
2525   /* Free up state attached to the ldap_info structures */
2526   for (ldap_info = ldap_info_items; ldap_info != NULL; ldap_info = ldap_info->next) {
2527     if (ldap_info->auth_mech != NULL) {
2528       g_free(ldap_info->auth_mech);
2529       ldap_info->auth_mech=NULL;
2530     }
2531     g_hash_table_destroy(ldap_info->matched);
2532     ldap_info->matched=NULL;
2533     g_hash_table_destroy(ldap_info->unmatched);
2534     ldap_info->unmatched=NULL;
2535   }
2536
2537   if (ldap_conv_info_chunk != NULL)
2538     g_mem_chunk_destroy(ldap_conv_info_chunk);
2539
2540   ldap_info_items = NULL;
2541
2542   ldap_conv_info_chunk = g_mem_chunk_new("ldap_conv_info_chunk",
2543                 sizeof(ldap_conv_info_t),
2544                 ldap_conv_info_chunk_count * sizeof(ldap_conv_info_t),
2545                 G_ALLOC_ONLY);
2546
2547   if (ldap_call_response_chunk != NULL)
2548     g_mem_chunk_destroy(ldap_call_response_chunk);
2549
2550   ldap_call_response_chunk = g_mem_chunk_new("ldap_call_response_chunk",
2551                 sizeof(ldap_call_response_t),
2552                 ldap_call_response_chunk_count * sizeof(ldap_call_response_t),
2553                 G_ALLOC_ONLY);
2554 }
2555
2556 void
2557 proto_register_ldap(void)
2558 {
2559   static value_string auth_types[] = {
2560     {LDAP_AUTH_SIMPLE,    "Simple"},
2561     {LDAP_AUTH_KRBV4LDAP, "Kerberos V4 to the LDAP server"},
2562     {LDAP_AUTH_KRBV4DSA,  "Kerberos V4 to the DSA"},
2563     {LDAP_AUTH_SASL,      "SASL"},
2564     {0, NULL},
2565   };
2566
2567   static value_string search_scope[] = {
2568     {0x00, "Base"},
2569     {0x01, "Single"},
2570     {0x02, "Subtree"},
2571     {0x00, NULL},
2572   };
2573
2574   static value_string search_dereference[] = {
2575     {0x00, "Never"},
2576     {0x01, "Searching"},
2577     {0x02, "Base Object"},
2578     {0x03, "Always"},
2579     {0x00, NULL},
2580   };
2581
2582   static hf_register_info hf[] = {
2583     { &hf_ldap_response_in,
2584       { "Response In", "ldap.response_in",
2585         FT_FRAMENUM, BASE_DEC, NULL, 0x0,
2586         "The response to this packet is in this frame", HFILL }},
2587
2588     { &hf_ldap_response_to,
2589       { "Response To", "ldap.response_to",
2590         FT_FRAMENUM, BASE_DEC, NULL, 0x0,
2591         "This is a response to the LDAP command in this frame", HFILL }},
2592
2593     { &hf_ldap_time,
2594       { "Time", "ldap.time",
2595         FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2596         "The time between the Call and the Reply", HFILL }},
2597
2598     { &hf_ldap_sasl_buffer_length,
2599       { "SASL Buffer Length",   "ldap.sasl_buffer_length",
2600         FT_UINT32, BASE_DEC, NULL, 0x0,
2601         "SASL Buffer Length", HFILL }},
2602
2603     { &hf_ldap_length,
2604       { "Length",               "ldap.length",
2605         FT_UINT32, BASE_DEC, NULL, 0x0,
2606         "LDAP Length", HFILL }},
2607
2608     { &hf_ldap_message_id,
2609       { "Message Id",           "ldap.message_id",
2610         FT_UINT32, BASE_DEC, NULL, 0x0,
2611         "LDAP Message Id", HFILL }},
2612     { &hf_ldap_message_type,
2613       { "Message Type",         "ldap.message_type",
2614         FT_UINT8, BASE_HEX, &msgTypes, 0x0,
2615         "LDAP Message Type", HFILL }},
2616     { &hf_ldap_message_length,
2617       { "Message Length",               "ldap.message_length",
2618         FT_UINT32, BASE_DEC, NULL, 0x0,
2619         "LDAP Message Length", HFILL }},
2620
2621     { &hf_ldap_message_result,
2622       { "Result Code",          "ldap.result.code",
2623         FT_UINT8, BASE_HEX, result_codes, 0x0,
2624         "LDAP Result Code", HFILL }},
2625     { &hf_ldap_message_result_matcheddn,
2626       { "Matched DN",           "ldap.result.matcheddn",
2627         FT_STRING, BASE_NONE, NULL, 0x0,
2628         "LDAP Result Matched DN", HFILL }},
2629     { &hf_ldap_message_result_errormsg,
2630       { "Error Message",                "ldap.result.errormsg",
2631         FT_STRING, BASE_NONE, NULL, 0x0,
2632         "LDAP Result Error Message", HFILL }},
2633     { &hf_ldap_message_result_referral,
2634       { "Referral",             "ldap.result.referral",
2635         FT_STRING, BASE_NONE, NULL, 0x0,
2636         "LDAP Result Referral URL", HFILL }},
2637
2638     { &hf_ldap_message_bind_version,
2639       { "Version",              "ldap.bind.version",
2640         FT_UINT32, BASE_DEC, NULL, 0x0,
2641         "LDAP Bind Version", HFILL }},
2642     { &hf_ldap_message_bind_dn,
2643       { "DN",                   "ldap.bind.dn",
2644         FT_STRING, BASE_NONE, NULL, 0x0,
2645         "LDAP Bind Distinguished Name", HFILL }},
2646     { &hf_ldap_message_bind_auth,
2647       { "Auth Type",            "ldap.bind.auth_type",
2648         FT_UINT8, BASE_HEX, auth_types, 0x0,
2649         "LDAP Bind Auth Type", HFILL }},
2650     { &hf_ldap_message_bind_auth_password,
2651       { "Password",             "ldap.bind.password",
2652         FT_STRING, BASE_NONE, NULL, 0x0,
2653         "LDAP Bind Password", HFILL }},
2654     { &hf_ldap_message_bind_auth_mechanism,
2655       { "Mechanism",            "ldap.bind.mechanism",
2656         FT_STRING, BASE_NONE, NULL, 0x0,
2657         "LDAP Bind Mechanism", HFILL }},
2658     { &hf_ldap_message_bind_auth_credentials,
2659       { "Credentials",          "ldap.bind.credentials",
2660         FT_BYTES, BASE_NONE, NULL, 0x0,
2661         "LDAP Bind Credentials", HFILL }},
2662     { &hf_ldap_message_bind_server_credentials,
2663       { "Server Credentials",   "ldap.bind.server_credentials",
2664         FT_BYTES, BASE_NONE, NULL, 0x0,
2665         "LDAP Bind Server Credentials", HFILL }},
2666
2667     { &hf_ldap_message_search_base,
2668       { "Base DN",              "ldap.search.basedn",
2669         FT_STRING, BASE_NONE, NULL, 0x0,
2670         "LDAP Search Base Distinguished Name", HFILL }},
2671     { &hf_ldap_message_search_scope,
2672       { "Scope",                        "ldap.search.scope",
2673         FT_UINT8, BASE_HEX, search_scope, 0x0,
2674         "LDAP Search Scope", HFILL }},
2675     { &hf_ldap_message_search_deref,
2676       { "Dereference",          "ldap.search.dereference",
2677         FT_UINT8, BASE_HEX, search_dereference, 0x0,
2678         "LDAP Search Dereference", HFILL }},
2679     { &hf_ldap_message_search_sizeLimit,
2680       { "Size Limit",           "ldap.search.sizelimit",
2681         FT_UINT32, BASE_DEC, NULL, 0x0,
2682         "LDAP Search Size Limit", HFILL }},
2683     { &hf_ldap_message_search_timeLimit,
2684       { "Time Limit",           "ldap.search.timelimit",
2685         FT_UINT32, BASE_DEC, NULL, 0x0,
2686         "LDAP Search Time Limit", HFILL }},
2687     { &hf_ldap_message_search_typesOnly,
2688       { "Attributes Only",      "ldap.search.typesonly",
2689         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2690         "LDAP Search Attributes Only", HFILL }},
2691     { &hf_ldap_message_search_filter,
2692       { "Filter",               "ldap.search.filter",
2693         FT_STRING, BASE_NONE, NULL, 0x0,
2694         "LDAP Search Filter", HFILL }},
2695     { &hf_ldap_message_search_reference,
2696       { "Reference URL",        "ldap.search.reference",
2697         FT_STRING, BASE_NONE, NULL, 0x0,
2698         "LDAP Search Reference URL", HFILL }},
2699     { &hf_ldap_message_dn,
2700       { "Distinguished Name",   "ldap.dn",
2701         FT_STRING, BASE_NONE, NULL, 0x0,
2702         "LDAP Distinguished Name", HFILL }},
2703     { &hf_ldap_message_attribute,
2704       { "Attribute",            "ldap.attribute",
2705         FT_STRING, BASE_NONE, NULL, 0x0,
2706         "LDAP Attribute", HFILL }},
2707     /*
2708      * XXX - not all LDAP values are text strings; we'd need a file
2709      * describing which values (by name) are text strings and which are
2710      * binary.
2711      *
2712      * Some values that are, at least in Microsoft's schema, binary
2713      * are:
2714      *
2715      *  invocationId
2716      *  nTSecurityDescriptor
2717      *  objectGUID
2718      */
2719     { &hf_ldap_message_value,
2720       { "Value",                "ldap.value",
2721         FT_STRING, BASE_NONE, NULL, 0x0,
2722         "LDAP Value", HFILL }},
2723
2724     { &hf_ldap_message_modrdn_name,
2725       { "New Name",             "ldap.modrdn.name",
2726         FT_STRING, BASE_NONE, NULL, 0x0,
2727         "LDAP New Name", HFILL }},
2728     { &hf_ldap_message_modrdn_delete,
2729       { "Delete Values",        "ldap.modrdn.delete",
2730         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2731         "LDAP Modify RDN - Delete original values", HFILL }},
2732     { &hf_ldap_message_modrdn_superior,
2733       { "New Location",         "ldap.modrdn.superior",
2734         FT_STRING, BASE_NONE, NULL, 0x0,
2735         "LDAP Modify RDN - New Location", HFILL }},
2736
2737     { &hf_ldap_message_compare,
2738       { "Test",         "ldap.compare.test",
2739         FT_STRING, BASE_NONE, NULL, 0x0,
2740         "LDAP Compare Test", HFILL }},
2741
2742     { &hf_ldap_message_modify_add,
2743       { "Add",                  "ldap.modify.add",
2744         FT_STRING, BASE_NONE, NULL, 0x0,
2745         "LDAP Add", HFILL }},
2746     { &hf_ldap_message_modify_replace,
2747       { "Replace",              "ldap.modify.replace",
2748         FT_STRING, BASE_NONE, NULL, 0x0,
2749         "LDAP Replace", HFILL }},
2750     { &hf_ldap_message_modify_delete,
2751       { "Delete",               "ldap.modify.delete",
2752         FT_STRING, BASE_NONE, NULL, 0x0,
2753         "LDAP Delete", HFILL }},
2754
2755     { &hf_ldap_message_abandon_msgid,
2756       { "Abandon Msg Id",       "ldap.abandon.msgid",
2757         FT_UINT32, BASE_DEC, NULL, 0x0,
2758         "LDAP Abandon Msg Id", HFILL }},
2759
2760     { &hf_mscldap_netlogon_type,
2761       { "Type", "mscldap.netlogon.type",
2762         FT_UINT32, BASE_DEC, NULL, 0x0,
2763         "Type of <please tell ethereal developers what this type is>", HFILL }},
2764
2765     { &hf_mscldap_netlogon_version,
2766       { "Version", "mscldap.netlogon.version",
2767         FT_UINT32, BASE_DEC, NULL, 0x0,
2768         "Version of <please tell ethereal developers what this type is>", HFILL }},
2769
2770     { &hf_mscldap_netlogon_lm_token,
2771       { "LM Token", "mscldap.netlogon.lm_token",
2772         FT_UINT16, BASE_HEX, NULL, 0x0,
2773         "LM Token", HFILL }},
2774
2775     { &hf_mscldap_netlogon_nt_token,
2776       { "NT Token", "mscldap.netlogon.nt_token",
2777         FT_UINT16, BASE_HEX, NULL, 0x0,
2778         "NT Token", HFILL }},
2779
2780     { &hf_mscldap_netlogon_flags,
2781       { "Flags", "mscldap.netlogon.flags",
2782         FT_UINT32, BASE_HEX, NULL, 0x0,
2783         "Flags <please tell ethereal developers what these flags are>", HFILL }},
2784
2785     { &hf_mscldap_domain_guid,
2786       { "Domain GUID", "mscldap.domain.guid",
2787         FT_BYTES, BASE_HEX, NULL, 0x0,
2788         "Domain GUID", HFILL }},
2789
2790     { &hf_mscldap_forest,
2791       { "Forest", "mscldap.forest",
2792         FT_STRING, BASE_NONE, NULL, 0x0,
2793         "Forest", HFILL }},
2794
2795     { &hf_mscldap_domain,
2796       { "Domain", "mscldap.domain",
2797         FT_STRING, BASE_NONE, NULL, 0x0,
2798         "Domainname", HFILL }},
2799
2800     { &hf_mscldap_hostname,
2801       { "Hostname", "mscldap.hostname",
2802         FT_STRING, BASE_NONE, NULL, 0x0,
2803         "Hostname", HFILL }},
2804
2805     { &hf_mscldap_nb_domain,
2806       { "NetBios Domain", "mscldap.nb_domain",
2807         FT_STRING, BASE_NONE, NULL, 0x0,
2808         "NetBios Domainname", HFILL }},
2809
2810     { &hf_mscldap_nb_hostname,
2811       { "NetBios Hostname", "mscldap.nb_hostname",
2812         FT_STRING, BASE_NONE, NULL, 0x0,
2813         "NetBios Hostname", HFILL }},
2814
2815     { &hf_mscldap_username,
2816       { "User", "mscldap.username",
2817         FT_STRING, BASE_NONE, NULL, 0x0,
2818         "User name", HFILL }},
2819
2820     { &hf_mscldap_sitename,
2821       { "Site", "mscldap.sitename",
2822         FT_STRING, BASE_NONE, NULL, 0x0,
2823         "Site name", HFILL }},
2824
2825     { &hf_mscldap_clientsitename,
2826       { "Client Site", "mscldap.clientsitename",
2827         FT_STRING, BASE_NONE, NULL, 0x0,
2828         "Client Site name", HFILL }},
2829
2830   };
2831
2832   static gint *ett[] = {
2833     &ett_ldap,
2834     &ett_ldap_gssapi_token,
2835     &ett_ldap_referrals,
2836     &ett_ldap_attribute
2837   };
2838   module_t *ldap_module;
2839
2840   proto_ldap = proto_register_protocol("Lightweight Directory Access Protocol",
2841                                        "LDAP", "ldap");
2842   proto_register_field_array(proto_ldap, hf, array_length(hf));
2843   proto_register_subtree_array(ett, array_length(ett));
2844
2845   ldap_module = prefs_register_protocol(proto_ldap, NULL);
2846   prefs_register_bool_preference(ldap_module, "desegment_ldap_messages",
2847     "Desegment all LDAP messages spanning multiple TCP segments",
2848     "Whether the LDAP dissector should desegment all messages spanning multiple TCP segments",
2849     &ldap_desegment);
2850
2851   proto_cldap = proto_register_protocol(
2852           "Connectionless Lightweight Directory Access Protocol",
2853           "CLDAP", "cldap");
2854
2855   register_init_routine(ldap_reinit);
2856   ldap_tap=register_tap("ldap");
2857 }
2858
2859 void
2860 proto_reg_handoff_ldap(void)
2861 {
2862   dissector_handle_t ldap_handle, cldap_handle;
2863
2864   ldap_handle = create_dissector_handle(dissect_ldap, proto_ldap);
2865   dissector_add("tcp.port", TCP_PORT_LDAP, ldap_handle);
2866   dissector_add("tcp.port", TCP_PORT_GLOBALCAT_LDAP, ldap_handle);
2867
2868   cldap_handle = create_dissector_handle(dissect_mscldap, proto_cldap);
2869   dissector_add("udp.port", UDP_PORT_CLDAP, cldap_handle);
2870
2871   gssapi_handle = find_dissector("gssapi");
2872   gssapi_wrap_handle = find_dissector("gssapi_verf");
2873 }