From Jean-Baptiste Marchand: put the LDAP message ID and message type
[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.53 2003/04/21 07:58:16 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 #ifdef HAVE_CONFIG_H
52 # include "config.h"
53 #endif
54
55 #include <stdio.h>
56
57 #include <string.h>
58 #include <glib.h>
59
60 #ifdef NEED_SNPRINTF_H
61 # include "snprintf.h"
62 #endif
63
64 #include <epan/packet.h>
65
66 #include "packet-ldap.h"
67 #include "asn1.h"
68 #include "prefs.h"
69 #include <epan/conversation.h>
70 #include "packet-frame.h"
71
72 static int proto_ldap = -1;
73 static int hf_ldap_sasl_buffer_length = -1;
74 static int hf_ldap_length = -1;
75 static int hf_ldap_message_id = -1;
76 static int hf_ldap_message_type = -1;
77 static int hf_ldap_message_length = -1;
78
79 static int hf_ldap_message_result = -1;
80 static int hf_ldap_message_result_matcheddn = -1;
81 static int hf_ldap_message_result_errormsg = -1;
82 static int hf_ldap_message_result_referral = -1;
83
84 static int hf_ldap_message_bind_version = -1;
85 static int hf_ldap_message_bind_dn = -1;
86 static int hf_ldap_message_bind_auth = -1;
87 static int hf_ldap_message_bind_auth_password = -1;
88 static int hf_ldap_message_bind_auth_mechanism = -1;
89 static int hf_ldap_message_bind_auth_credentials = -1;
90 static int hf_ldap_message_bind_server_credentials = -1;
91
92 static int hf_ldap_message_search_base = -1;
93 static int hf_ldap_message_search_scope = -1;
94 static int hf_ldap_message_search_deref = -1;
95 static int hf_ldap_message_search_sizeLimit = -1;
96 static int hf_ldap_message_search_timeLimit = -1;
97 static int hf_ldap_message_search_typesOnly = -1;
98 static int hf_ldap_message_search_filter = -1;
99
100 static int hf_ldap_message_dn = -1;
101 static int hf_ldap_message_attribute = -1;
102 static int hf_ldap_message_value = -1;
103
104 static int hf_ldap_message_modrdn_name = -1;
105 static int hf_ldap_message_modrdn_delete = -1;
106 static int hf_ldap_message_modrdn_superior = -1;
107
108 static int hf_ldap_message_compare = -1;
109
110 static int hf_ldap_message_modify_add = -1;
111 static int hf_ldap_message_modify_replace = -1;
112 static int hf_ldap_message_modify_delete = -1;
113
114 static int hf_ldap_message_abandon_msgid = -1;
115
116 static gint ett_ldap = -1;
117 static gint ett_ldap_message = -1;
118 static gint ett_ldap_gssapi_token = -1;
119 static gint ett_ldap_referrals = -1;
120 static gint ett_ldap_attribute = -1;
121
122 /* desegmentation of LDAP */
123 static gboolean ldap_desegment = TRUE;
124
125 #define TCP_PORT_LDAP                   389
126 #define UDP_PORT_CLDAP                  389
127
128 static dissector_handle_t gssapi_handle;
129 static dissector_handle_t gssapi_wrap_handle;
130
131 /*
132  * Data structure attached to a conversation, giving authentication
133  * information from a bind request.
134  * We keep a linked list of them, so that we can free up all the
135  * authentication mechanism strings.
136  */
137 typedef struct ldap_auth_info_t {
138   guint auth_type;              /* authentication type */
139   char *auth_mech;              /* authentication mechanism */
140   guint32 first_auth_frame;     /* first frame that would use a security layer */
141   struct ldap_auth_info_t *next;
142 } ldap_auth_info_t;
143
144 static GMemChunk *ldap_auth_info_chunk = NULL;
145
146 static guint ldap_auth_info_chunk_count = 200;
147
148 static ldap_auth_info_t *auth_info_items;
149
150 static value_string msgTypes [] = {
151   {LDAP_REQ_BIND, "Bind Request"},
152   {LDAP_REQ_UNBIND, "Unbind Request"},
153   {LDAP_REQ_SEARCH, "Search Request"},
154   {LDAP_REQ_MODIFY, "Modify Request"},
155   {LDAP_REQ_ADD, "Add Request"},
156   {LDAP_REQ_DELETE, "Delete Request"},
157   {LDAP_REQ_MODRDN, "Modify RDN Request"},
158   {LDAP_REQ_COMPARE, "Compare Request"},
159   {LDAP_REQ_ABANDON, "Abandon Request"},
160   {LDAP_REQ_EXTENDED, "Extended Request"},
161
162   {LDAP_RES_BIND, "Bind Result"},
163   {LDAP_RES_SEARCH_ENTRY, "Search Entry"},
164   {LDAP_RES_SEARCH_RESULT, "Search Result"},
165   {LDAP_RES_SEARCH_REF, "Search Result Reference"},
166   {LDAP_RES_MODIFY, "Modify Result"},
167   {LDAP_RES_ADD, "Add Result"},
168   {LDAP_RES_DELETE, "Delete Result"},
169   {LDAP_RES_MODRDN, "Modify RDN Result"},
170   {LDAP_RES_COMPARE, "Compare Result"},
171   {LDAP_REQ_EXTENDED, "Extended Response"},
172   {0, NULL},
173 };
174
175 static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
176 {
177   guint length = 0;
178   gboolean def = FALSE;
179   int start = a->offset;
180   int ret;
181
182   ret = asn1_length_decode(a, &def, &length);
183   if (ret != ASN1_ERR_NOERROR) {
184     if (tree) {
185       proto_tree_add_text(tree, a->tvb, start, 0,
186         "%s: ERROR: Couldn't parse length: %s",
187         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
188     }
189     return ret;
190   }
191
192   if (len)
193     *len = length;
194
195   if (tree)
196     proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, length);
197
198   return ASN1_ERR_NOERROR;
199 }
200
201 static int read_sequence(ASN1_SCK *a, guint *len)
202 {
203   guint cls, con, tag;
204   gboolean def;
205   guint length;
206   int ret;
207
208   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
209   if (ret != ASN1_ERR_NOERROR)
210     return ret;
211   if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
212     return ASN1_ERR_WRONG_TYPE;
213
214   if (len)
215     *len = length;
216
217   return ASN1_ERR_NOERROR;
218 }
219
220 static int read_set(ASN1_SCK *a, guint *len)
221 {
222   guint cls, con, tag;
223   gboolean def;
224   guint length;
225   int ret;
226
227   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
228   if (ret != ASN1_ERR_NOERROR)
229     return ret;
230   if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SET)
231     return ASN1_ERR_WRONG_TYPE;
232
233   if (len)
234     *len = length;
235
236   return ASN1_ERR_NOERROR;
237 }
238
239 static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
240         proto_item **new_item, guint *i, int start, guint length)
241 {
242   guint integer = 0;
243   proto_item *temp_item = NULL;
244   int ret;
245
246   ret = asn1_uint32_value_decode(a, length, &integer);
247   if (ret != ASN1_ERR_NOERROR) {
248     if (tree) {
249       proto_tree_add_text(tree, a->tvb, start, 0,
250        "%s: ERROR: Couldn't parse value: %s",
251         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
252     }
253     return ret;
254   }
255
256   if (i)
257     *i = integer;
258
259   if (tree)
260     temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, integer);
261
262   if (new_item)
263     *new_item = temp_item;
264
265   return ASN1_ERR_NOERROR;
266 }
267
268 static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
269         proto_item **new_item, guint *i, guint expected_tag)
270 {
271   guint cls, con, tag;
272   gboolean def;
273   guint length;
274   int start = a->offset;
275   int ret;
276
277   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
278   if (ret == ASN1_ERR_NOERROR) {
279     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag)
280       ret = ASN1_ERR_WRONG_TYPE;
281   }
282   if (ret != ASN1_ERR_NOERROR) {
283     if (tree) {
284       proto_tree_add_text(tree, a->tvb, start, 0,
285         "%s: ERROR: Couldn't parse header: %s",
286         (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
287         asn1_err_to_str(ret));
288     }
289     return ret;
290   }
291
292   return read_integer_value(a, tree, hf_id, new_item, i, start, length);
293 }
294
295 static int read_boolean_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
296         proto_item **new_item, guint *i, int start, guint length)
297 {
298   guint integer = 0;
299   proto_item *temp_item = NULL;
300   int ret;
301
302   ret = asn1_uint32_value_decode(a, length, &integer);
303   if (ret != ASN1_ERR_NOERROR) {
304     if (tree) {
305       proto_tree_add_text(tree, a->tvb, start, 0,
306         "%s: ERROR: Couldn't parse value: %s",
307         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
308     }
309     return ret;
310   }
311
312   if (i)
313     *i = integer;
314
315   if (tree)
316     temp_item = proto_tree_add_boolean(tree, hf_id, a->tvb, start, a->offset-start, integer);
317   if (new_item)
318     *new_item = temp_item;
319
320   return ASN1_ERR_NOERROR;
321 }
322
323 static int read_boolean(ASN1_SCK *a, proto_tree *tree, int hf_id,
324         proto_item **new_item, guint *i)
325 {
326   guint cls, con, tag;
327   gboolean def;
328   guint length;
329   int start = a->offset;
330   int ret;
331
332   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
333   if (ret == ASN1_ERR_NOERROR) {
334     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_BOL)
335       ret = ASN1_ERR_WRONG_TYPE;
336   }
337   if (ret != ASN1_ERR_NOERROR) {
338     if (tree) {
339       proto_tree_add_text(tree, a->tvb, start, 0,
340         "%s: ERROR: Couldn't parse header: %s",
341         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
342     }
343     return ret;
344   }
345
346   return read_boolean_value(a, tree, hf_id, new_item, i, start, length);
347 }
348
349 static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
350         proto_item **new_item, char **s, int start, guint length)
351 {
352   guchar *string;
353   proto_item *temp_item = NULL;
354   int ret;
355
356   if (length)
357   {
358     ret = asn1_string_value_decode(a, length, &string);
359     if (ret != ASN1_ERR_NOERROR) {
360       if (tree) {
361         proto_tree_add_text(tree, a->tvb, start, 0,
362           "%s: ERROR: Couldn't parse value: %s",
363           proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
364       }
365       return ret;
366     }
367     string = g_realloc(string, length + 1);
368     string[length] = '\0';
369   }
370   else
371     string = "(null)";
372
373   if (tree)
374     temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset - start, string);
375   if (new_item)
376     *new_item = temp_item;
377
378   if (s && length)
379     *s = string;
380   else if (length)
381     g_free(string);
382
383   return ASN1_ERR_NOERROR;
384 }
385
386 static int read_string(ASN1_SCK *a, proto_tree *tree, int hf_id,
387         proto_item **new_item, char **s, guint expected_cls, guint expected_tag)
388 {
389   guint cls, con, tag;
390   gboolean def;
391   guint length;
392   int start = a->offset;
393   int ret;
394
395   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
396   if (ret == ASN1_ERR_NOERROR) {
397     if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
398       ret = ASN1_ERR_WRONG_TYPE;
399   }
400   if (ret != ASN1_ERR_NOERROR) {
401     if (tree) {
402       proto_tree_add_text(tree, a->tvb, start, 0,
403         "%s: ERROR: Couldn't parse header: %s",
404         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
405     }
406     return ret;
407   }
408
409   return read_string_value(a, tree, hf_id, new_item, s, start, length);
410 }
411
412 static int read_bytestring_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
413         proto_item **new_item, char **s, int start, guint length)
414 {
415   guchar *string;
416   proto_item *temp_item = NULL;
417   int ret;
418
419   if (length)
420   {
421     ret = asn1_string_value_decode(a, length, &string);
422     if (ret != ASN1_ERR_NOERROR) {
423       if (tree) {
424         proto_tree_add_text(tree, a->tvb, start, 0,
425           "%s: ERROR: Couldn't parse value: %s",
426           proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
427       }
428       return ret;
429     }
430     string = g_realloc(string, length + 1);
431     string[length] = '\0';
432   }
433   else
434     string = "(null)";
435
436   if (tree)
437     temp_item = proto_tree_add_bytes(tree, hf_id, a->tvb, start, a->offset - start, string);
438   if (new_item)
439     *new_item = temp_item;
440
441   if (s && length)
442     *s = string;
443   else if (length)
444     g_free(string);
445
446   return ASN1_ERR_NOERROR;
447 }
448
449 static int read_bytestring(ASN1_SCK *a, proto_tree *tree, int hf_id,
450         proto_item **new_item, char **s, guint expected_cls, guint expected_tag)
451 {
452   guint cls, con, tag;
453   gboolean def;
454   guint length;
455   int start = a->offset;
456   int ret;
457
458   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
459   if (ret == ASN1_ERR_NOERROR) {
460     if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
461       ret = ASN1_ERR_WRONG_TYPE;
462   }
463   if (ret != ASN1_ERR_NOERROR) {
464     if (tree) {
465       proto_tree_add_text(tree, a->tvb, start, 0,
466         "%s: ERROR: Couldn't parse header: %s",
467         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
468     }
469     return ret;
470   }
471
472   return read_bytestring_value(a, tree, hf_id, new_item, s, start, length);
473 }
474
475 static int parse_filter_strings(ASN1_SCK *a, char **filter, guint *filter_length, const guchar *operation)
476 {
477   guchar *string;
478   guchar *string2;
479   guint string_length;
480   guint string2_length;
481   guint string_bytes;
482   char *filterp;
483   int ret;
484
485   ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
486   if (ret != ASN1_ERR_NOERROR)
487     return ret;
488   ret = asn1_octet_string_decode(a, &string2, &string2_length, &string_bytes);
489   if (ret != ASN1_ERR_NOERROR)
490     return ret;
491   *filter_length += 2 + strlen(operation) + string_length + string2_length;
492   *filter = g_realloc(*filter, *filter_length);
493   filterp = *filter + strlen(*filter);
494   *filterp++ = '(';
495   if (string_length != 0) {
496         memcpy(filterp, string, string_length);
497         filterp += string_length;
498   }
499   strcpy(filterp, operation);
500   filterp += strlen(operation);
501   if (string2_length != 0) {
502         memcpy(filterp, string2, string2_length);
503         filterp += string2_length;
504   }
505   *filterp++ = ')';
506   *filterp = '\0';
507   g_free(string);
508   g_free(string2);
509   return ASN1_ERR_NOERROR;
510 }
511
512 /* Richard Dawe: To parse substring filters, I added this function. */
513 static int parse_filter_substrings(ASN1_SCK *a, char **filter, guint *filter_length)
514 {
515   int end;
516   guchar *string;
517   char *filterp;
518   guint string_length;
519   guint string_bytes;
520   guint seq_len;
521   guint header_bytes;
522   int ret, any_valued;
523
524   /* For ASN.1 parsing of octet strings */
525   guint        cls;
526   guint        con;
527   guint        tag;
528   gboolean     def;
529
530   ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
531   if (ret != ASN1_ERR_NOERROR)
532     return ret;
533
534   ret = asn1_sequence_decode(a, &seq_len, &header_bytes);
535   if (ret != ASN1_ERR_NOERROR)
536     return ret;
537
538   *filter_length += 2 + 1 + string_length;
539   *filter = g_realloc(*filter, *filter_length);
540
541   filterp = *filter + strlen(*filter);
542   *filterp++ = '(';
543   if (string_length != 0) {
544     memcpy(filterp, string, string_length);
545     filterp += string_length;
546   }
547   *filterp++ = '=';
548   *filterp = '\0';
549   g_free(string);
550
551   /* Now decode seq_len's worth of octet strings. */
552   any_valued = 0;
553   end = a->offset + seq_len;
554
555   while (a->offset < end) {
556     /* Octet strings here are context-specific, which
557      * asn1_octet_string_decode() barfs on. Emulate it, but don't barf. */
558     ret = asn1_header_decode (a, &cls, &con, &tag, &def, &string_length);
559     if (ret != ASN1_ERR_NOERROR)
560       return ret;
561
562     /* XXX - check the tag? */
563     if (cls != ASN1_CTX || con != ASN1_PRI) {
564         /* XXX - handle the constructed encoding? */
565         return ASN1_ERR_WRONG_TYPE;
566     }
567     if (!def)
568         return ASN1_ERR_LENGTH_NOT_DEFINITE;
569
570     ret = asn1_string_value_decode(a, (int) string_length, &string);
571     if (ret != ASN1_ERR_NOERROR)
572       return ret;
573
574     /* If we have an 'any' component with a string value, we need to append
575      * an extra asterisk before final component. */
576     if ((tag == 1) && (string_length != 0))
577       any_valued = 1;
578
579     if ( (tag == 1) || ((tag == 2) && any_valued) )
580       (*filter_length)++;
581     *filter_length += string_length;
582     *filter = g_realloc(*filter, *filter_length);
583
584     filterp = *filter + strlen(*filter);
585     if ( (tag == 1) || ((tag == 2) && any_valued) )
586       *filterp++ = '*';
587     if (tag == 2)
588       any_valued = 0;
589     if (string_length != 0) {
590       memcpy(filterp, string, string_length);
591       filterp += string_length;
592     }
593     *filterp = '\0';
594     g_free(string);
595   }
596
597   if (any_valued)
598   {
599     (*filter_length)++;
600     *filter = g_realloc(*filter, *filter_length);
601     filterp = *filter + strlen(*filter);
602     *filterp++ = '*';
603   }
604
605   /* NB: Allocated byte for this earlier */
606   *filterp++ = ')';
607   *filterp = '\0';
608
609   return ASN1_ERR_NOERROR;
610 }
611
612 /* Returns -1 if we're at the end, returns an ASN1_ERR value otherwise. */
613 static int parse_filter(ASN1_SCK *a, char **filter, guint *filter_length,
614                         int *end)
615 {
616   guint cls, con, tag;
617   guint length;
618   gboolean def;
619   int ret;
620
621   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
622   if (ret != ASN1_ERR_NOERROR)
623     return ret;
624
625   if (*end == 0)
626   {
627     *end = a->offset + length;
628     *filter_length = 1;
629     *filter = g_malloc0(*filter_length);
630   }
631
632   if (cls == ASN1_CTX)  /* XXX - handle other types as errors? */
633   {
634     switch (tag)
635     {
636      case LDAP_FILTER_AND:
637       {
638         int add_end;
639
640         if (con != ASN1_CON)
641           return ASN1_ERR_WRONG_TYPE;
642         add_end = a->offset + length;
643         *filter_length += 3;
644         *filter = g_realloc(*filter, *filter_length);
645         strcat(*filter, "(&");
646         while ((ret = parse_filter(a, filter, filter_length, &add_end))
647                 == ASN1_ERR_NOERROR)
648           continue;
649         if (ret != -1)
650           return ret;
651         strcat(*filter, ")");
652       }
653       break;
654      case LDAP_FILTER_OR:
655       {
656         int or_end;
657
658         if (con != ASN1_CON)
659           return ASN1_ERR_WRONG_TYPE;
660         or_end = a->offset + length;
661         *filter_length += 3;
662         *filter = g_realloc(*filter, *filter_length);
663         strcat(*filter, "(|");
664         while ((ret = parse_filter(a, filter, filter_length, &or_end))
665                 == ASN1_ERR_NOERROR)
666           continue;
667         if (ret != -1)
668           return ret;
669         strcat(*filter, ")");
670       }
671       break;
672      case LDAP_FILTER_NOT:
673       {
674         int not_end;
675
676         if (con != ASN1_CON)
677           return ASN1_ERR_WRONG_TYPE;
678         not_end = a->offset + length;
679         *filter_length += 3;
680         *filter = g_realloc(*filter, *filter_length);
681         strcat(*filter, "(!");
682         ret = parse_filter(a, filter, filter_length, &not_end);
683         if (ret != -1 && ret != ASN1_ERR_NOERROR)
684           return ret;
685         strcat(*filter, ")");
686       }
687       break;
688      case LDAP_FILTER_EQUALITY:
689       if (con != ASN1_CON)
690         return ASN1_ERR_WRONG_TYPE;
691       ret = parse_filter_strings(a, filter, filter_length, "=");
692       if (ret != ASN1_ERR_NOERROR)
693         return ret;
694       break;
695      case LDAP_FILTER_GE:
696       if (con != ASN1_CON)
697         return ASN1_ERR_WRONG_TYPE;
698       ret = parse_filter_strings(a, filter, filter_length, ">=");
699       if (ret != ASN1_ERR_NOERROR)
700         return ret;
701       break;
702      case LDAP_FILTER_LE:
703       if (con != ASN1_CON)
704         return ASN1_ERR_WRONG_TYPE;
705       ret = parse_filter_strings(a, filter, filter_length, "<=");
706       if (ret != -1 && ret != ASN1_ERR_NOERROR)
707         return ret;
708       break;
709      case LDAP_FILTER_APPROX:
710       if (con != ASN1_CON)
711         return ASN1_ERR_WRONG_TYPE;
712       ret = parse_filter_strings(a, filter, filter_length, "~=");
713       if (ret != ASN1_ERR_NOERROR)
714         return ret;
715       break;
716      case LDAP_FILTER_PRESENT:
717       {
718         guchar *string;
719         char *filterp;
720
721         if (con != ASN1_PRI)
722           return ASN1_ERR_WRONG_TYPE;
723         ret = asn1_string_value_decode(a, length, &string);
724         if (ret != ASN1_ERR_NOERROR)
725           return ret;
726         *filter_length += 4 + length;
727         *filter = g_realloc(*filter, *filter_length);
728         filterp = *filter + strlen(*filter);
729         *filterp++ = '(';
730         if (length != 0) {
731           memcpy(filterp, string, length);
732           filterp += length;
733         }
734         *filterp++ = '=';
735         *filterp++ = '*';
736         *filterp++ = ')';
737         *filterp = '\0';
738         g_free(string);
739       }
740       break;
741      case LDAP_FILTER_SUBSTRINGS:
742       if (con != ASN1_CON)
743         return ASN1_ERR_WRONG_TYPE;
744       /* Richard Dawe: Handle substrings */
745       ret = parse_filter_substrings(a, filter, filter_length);
746       if (ret != ASN1_ERR_NOERROR)
747         return ret;
748       break;
749      default:
750       return ASN1_ERR_WRONG_TYPE;
751     }
752   }
753
754   if (a->offset == *end)
755     return -1;
756   else
757     return ASN1_ERR_NOERROR;
758 }
759
760 static gboolean read_filter(ASN1_SCK *a, proto_tree *tree, int hf_id)
761 {
762   int start = a->offset;
763   char *filter = 0;
764   guint filter_length = 0;
765   int end = 0;
766   int ret;
767
768   while ((ret = parse_filter(a, &filter, &filter_length, &end))
769         == ASN1_ERR_NOERROR)
770     continue;
771
772   if (tree) {
773     if (ret != -1) {
774       proto_tree_add_text(tree, a->tvb, start, 0,
775         "%s: ERROR: Can't parse filter: %s",
776         proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
777     } else
778       proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset-start, filter);
779   }
780
781   g_free(filter);
782
783   return (ret == -1) ? TRUE : FALSE;
784 }
785
786 /********************************************************************************************/
787
788 static void dissect_ldap_result(ASN1_SCK *a, proto_tree *tree)
789 {
790   guint resultCode = 0;
791   int ret;
792
793   if (read_integer(a, tree, hf_ldap_message_result, 0, &resultCode, ASN1_ENUM) != ASN1_ERR_NOERROR)
794     return;
795   if (read_string(a, tree, hf_ldap_message_result_matcheddn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
796     return;
797   if (read_string(a, tree, hf_ldap_message_result_errormsg, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
798     return;
799
800   if (resultCode == 10)         /* Referral */
801   {
802     int start = a->offset;
803     int end;
804     guint length;
805     proto_item *ti;
806     proto_tree *referralTree;
807
808     ret = read_sequence(a, &length);
809     if (ret != ASN1_ERR_NOERROR) {
810       if (tree) {
811         proto_tree_add_text(tree, a->tvb, start, 0,
812             "ERROR: Couldn't parse referral URL sequence header: %s",
813             asn1_err_to_str(ret));
814       }
815       return;
816     }
817     ti = proto_tree_add_text(tree, a->tvb, start, length, "Referral URLs");
818     referralTree = proto_item_add_subtree(ti, ett_ldap_referrals);
819
820     end = a->offset + length;
821     while (a->offset < end) {
822       if (read_string(a, referralTree, hf_ldap_message_result_referral, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
823         return;
824     }
825   }
826 }
827
828 static void dissect_ldap_request_bind(ASN1_SCK *a, proto_tree *tree,
829     tvbuff_t *tvb, packet_info *pinfo)
830 {
831   guint cls, con, tag;
832   gboolean def;
833   guint length;
834   int start;
835   int end;
836   int ret;
837   conversation_t *conversation;
838   ldap_auth_info_t *auth_info;
839   char *mechanism;
840   int token_offset;
841   gint available_length, reported_length;
842   tvbuff_t *new_tvb;
843   proto_item *gitem;
844   proto_tree *gtree = NULL;
845
846   if (read_integer(a, tree, hf_ldap_message_bind_version, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
847     return;
848   if (read_string(a, tree, hf_ldap_message_bind_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
849     return;
850
851   start = a->offset;
852   ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
853   if (ret == ASN1_ERR_NOERROR) {
854     if (cls != ASN1_CTX) {
855       /* RFCs 1777 and 2251 say these are context-specific types */
856       ret = ASN1_ERR_WRONG_TYPE;
857     }
858   }
859   if (ret != ASN1_ERR_NOERROR) {
860     proto_tree_add_text(tree, a->tvb, start, 0,
861       "%s: ERROR: Couldn't parse header: %s",
862       proto_registrar_get_name(hf_ldap_message_bind_auth),
863       asn1_err_to_str(ret));
864     return;
865   }
866   proto_tree_add_uint(tree, hf_ldap_message_bind_auth, a->tvb, start,
867                         a->offset - start, tag);
868   end = a->offset + length;
869   switch (tag)
870   {
871    case LDAP_AUTH_SIMPLE:
872     if (read_string_value(a, tree, hf_ldap_message_bind_auth_password, NULL,
873                           NULL, start, length) != ASN1_ERR_NOERROR)
874       return;
875     break;
876
877     /* For Kerberos V4, dissect it as a ticket. */
878
879    case LDAP_AUTH_SASL:
880     mechanism = NULL;
881     if (read_string(a, tree, hf_ldap_message_bind_auth_mechanism, NULL,
882                     &mechanism, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
883       return;
884
885     /*
886      * We need to remember the authentication type and mechanism for this
887      * conversation.
888      *
889      * XXX - actually, we might need to remember more than one
890      * type and mechanism, if you can unbind and rebind with a
891      * different type and/or mechanism.
892      */
893     conversation = find_conversation(&pinfo->src, &pinfo->dst,
894                                      pinfo->ptype, pinfo->srcport,
895                                      pinfo->destport, 0);
896     if (conversation == NULL) {
897       /* We don't yet have a conversation, so create one. */
898       conversation = conversation_new(&pinfo->src, &pinfo->dst,
899                                       pinfo->ptype, pinfo->srcport,
900                                       pinfo->destport, 0);
901     }
902
903     /*
904      * Do we already have a type and mechanism?
905      */
906     auth_info = conversation_get_proto_data(conversation, proto_ldap);
907     if (auth_info == NULL) {
908       /* No.  Attach that information to the conversation, and add
909          it to the list of information structures. */
910       auth_info = g_mem_chunk_alloc(ldap_auth_info_chunk);
911       auth_info->auth_type = tag;
912       auth_info->auth_mech = mechanism;
913       auth_info->first_auth_frame = 0;  /* not known until we see the bind reply */
914       conversation_add_proto_data(conversation, proto_ldap, auth_info);
915       auth_info->next = auth_info_items;
916       auth_info_items = auth_info;
917     } else {
918       /*
919        * Yes.
920        *
921        * If the mechanism in this request is an empty string (which is
922        * returned as a null pointer), use the saved mechanism instead.
923        * Otherwise, if the saved mechanism is an empty string (null),
924        * save this mechanism.
925        */
926       if (mechanism == NULL)
927         mechanism = auth_info->auth_mech;
928       else {
929         if (auth_info->auth_mech == NULL)
930           auth_info->auth_mech = mechanism;
931       }
932     }
933
934     if (a->offset < end) {
935       if (mechanism != NULL && strcmp(mechanism, "GSS-SPNEGO") == 0) {
936         /*
937          * This is a GSS-API token.
938          * Find out how big it is by parsing the ASN.1 header for the
939          * OCTET STREAM that contains it.
940          */
941         token_offset = a->offset;
942         ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
943         if (ret != ASN1_ERR_NOERROR) {
944           proto_tree_add_text(tree, a->tvb, token_offset, 0,
945             "%s: ERROR: Couldn't parse header: %s",
946             proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
947             asn1_err_to_str(ret));
948           return;
949         }
950         if (tree) {
951           gitem = proto_tree_add_text(tree, tvb, token_offset,
952             (a->offset + length) - token_offset, "GSS-API Token");
953           gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
954         }
955         available_length = tvb_length_remaining(tvb, token_offset);
956         reported_length = tvb_reported_length_remaining(tvb, token_offset);
957         g_assert(available_length >= 0);
958         g_assert(reported_length >= 0);
959         if (available_length > reported_length)
960           available_length = reported_length;
961         if ((guint)available_length > length)
962           available_length = length;
963         if ((guint)reported_length > length)
964           reported_length = length;
965         new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
966         call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
967         a->offset += length;
968       } else {
969         if (read_bytestring(a, tree, hf_ldap_message_bind_auth_credentials,
970                             NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
971           return;
972       }
973     }
974     break;
975   }
976 }
977
978 static void dissect_ldap_response_bind(ASN1_SCK *a, proto_tree *tree,
979                 int start, guint length, tvbuff_t *tvb, packet_info *pinfo)
980 {
981   guint cls, con, tag;
982   gboolean def;
983   guint cred_length;
984   int end;
985   int ret;
986   conversation_t *conversation;
987   ldap_auth_info_t *auth_info;
988   int token_offset;
989   gint available_length, reported_length;
990   tvbuff_t *new_tvb;
991   proto_item *gitem;
992   proto_tree *gtree = NULL;
993
994   end = start + length;
995   dissect_ldap_result(a, tree);
996   if (a->offset < end) {
997     conversation = find_conversation(&pinfo->src, &pinfo->dst,
998                                      pinfo->ptype, pinfo->srcport,
999                                      pinfo->destport, 0);
1000     if (conversation != NULL) {
1001       auth_info = conversation_get_proto_data(conversation, proto_ldap);
1002       if (auth_info != NULL) {
1003         switch (auth_info->auth_type) {
1004
1005           /* For Kerberos V4, dissect it as a ticket. */
1006           /* XXX - what about LDAP_AUTH_SIMPLE? */
1007
1008         case LDAP_AUTH_SASL:
1009           /*
1010            * All frames after this are assumed to use a security layer.
1011            *
1012            * XXX - won't work if there's another reply, with the security
1013            * layer, starting in the same TCP segment that ends this
1014            * reply, but as LDAP is a request/response protocol, and
1015            * as the client probably can't start using authentication until
1016            * it gets the bind reply and the server won't send a reply until
1017            * it gets a request, that probably won't happen.
1018            *
1019            * XXX - that assumption is invalid; it's not clear where the
1020            * hell you find out whether there's any security layer.  In
1021            * one capture, we have two GSS-SPNEGO negotiations, both of
1022            * which select MS KRB5, and the only differences in the tokens
1023            * is in the RC4-HMAC ciphertext.  The various
1024            * draft-ietf--cat-sasl-gssapi-NN.txt drafts seem to imply
1025            * that the RFC 2222 spoo with the bitmask and maximum
1026            * output message size stuff is done - but where does that
1027            * stuff show up?  Is it in the ciphertext, which means it's
1028            * presumably encrypted?
1029            *
1030            * Grrr.  We have to do a gross heuristic, checking whether the
1031            * putative LDAP message begins with 0x00 or not, making the
1032            * assumption that we won't have more than 2^24 bytes of
1033            * encapsulated stuff.
1034            */
1035           auth_info->first_auth_frame = pinfo->fd->num + 1;
1036           if (auth_info->auth_mech != NULL &&
1037               strcmp(auth_info->auth_mech, "GSS-SPNEGO") == 0) {
1038             /*
1039              * This is a GSS-API token.
1040              * Find out how big it is by parsing the ASN.1 header for the
1041              * OCTET STREAM that contains it.
1042              */
1043             token_offset = a->offset;
1044             ret = asn1_header_decode(a, &cls, &con, &tag, &def, &cred_length);
1045             if (ret != ASN1_ERR_NOERROR) {
1046               proto_tree_add_text(tree, a->tvb, token_offset, 0,
1047                 "%s: ERROR: Couldn't parse header: %s",
1048                 proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
1049                 asn1_err_to_str(ret));
1050               return;
1051             }
1052             if (tree) {
1053               gitem = proto_tree_add_text(tree, tvb, token_offset,
1054                 (a->offset + cred_length) - token_offset, "GSS-API Token");
1055               gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1056             }
1057             available_length = tvb_length_remaining(tvb, token_offset);
1058             reported_length = tvb_reported_length_remaining(tvb, token_offset);
1059             g_assert(available_length >= 0);
1060             g_assert(reported_length >= 0);
1061             if (available_length > reported_length)
1062               available_length = reported_length;
1063             if ((guint)available_length > cred_length)
1064               available_length = cred_length;
1065             if ((guint)reported_length > cred_length)
1066               reported_length = cred_length;
1067             new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
1068             call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1069             a->offset += cred_length;
1070           } else {
1071             if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1072                                 NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1073               return;
1074           }
1075           break;
1076
1077         default:
1078           if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1079                               NULL, NULL, ASN1_CTX, 7) != ASN1_ERR_NOERROR)
1080             return;
1081           break;
1082         }
1083       } else {
1084         if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1085                             NULL, NULL, ASN1_CTX, 7) != ASN1_ERR_NOERROR)
1086           return;
1087       }
1088     } else {
1089       if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
1090                           NULL, NULL, ASN1_CTX, 7) != ASN1_ERR_NOERROR)
1091         return;
1092     }
1093   }
1094 }
1095
1096 static void dissect_ldap_request_search(ASN1_SCK *a, proto_tree *tree)
1097 {
1098   guint seq_length;
1099   int end;
1100   int ret;
1101
1102   if (read_string(a, tree, hf_ldap_message_search_base, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1103     return;
1104   if (read_integer(a, tree, hf_ldap_message_search_scope, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
1105     return;
1106   if (read_integer(a, tree, hf_ldap_message_search_deref, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
1107     return;
1108   if (read_integer(a, tree, hf_ldap_message_search_sizeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
1109     return;
1110   if (read_integer(a, tree, hf_ldap_message_search_timeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
1111     return;
1112   if (read_boolean(a, tree, hf_ldap_message_search_typesOnly, 0, 0) != ASN1_ERR_NOERROR)
1113     return;
1114   if (!read_filter(a, tree, hf_ldap_message_search_filter))
1115     return;
1116   ret = read_sequence(a, &seq_length);
1117   if (ret != ASN1_ERR_NOERROR) {
1118     if (tree) {
1119       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1120           "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1121           asn1_err_to_str(ret));
1122     }
1123     return;
1124   }
1125   end = a->offset + seq_length;
1126   while (a->offset < end) {
1127     if (read_string(a, tree, hf_ldap_message_attribute, 0, 0, ASN1_UNI,
1128                     ASN1_OTS) != ASN1_ERR_NOERROR)
1129       return;
1130   }
1131 }
1132
1133 static void dissect_ldap_response_search_entry(ASN1_SCK *a, proto_tree *tree)
1134 {
1135   guint seq_length;
1136   int end_of_sequence;
1137   int ret;
1138
1139   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1140     return;
1141   ret = read_sequence(a, &seq_length);
1142   if (ret != ASN1_ERR_NOERROR) {
1143     if (tree) {
1144       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1145           "ERROR: Couldn't parse search entry response sequence header: %s",
1146           asn1_err_to_str(ret));
1147     }
1148     return;
1149   }
1150
1151   end_of_sequence = a->offset + seq_length;
1152   while (a->offset < end_of_sequence)
1153   {
1154     proto_item *ti;
1155     proto_tree *attr_tree;
1156     guint set_length;
1157     int end_of_set;
1158
1159     ret = read_sequence(a, 0);
1160     if (ret != ASN1_ERR_NOERROR) {
1161       if (tree) {
1162         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1163             "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1164             asn1_err_to_str(ret));
1165       }
1166       return;
1167     }
1168     if (read_string(a, tree, hf_ldap_message_attribute, &ti, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1169       return;
1170     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1171
1172     ret = read_set(a, &set_length);
1173     if (ret != ASN1_ERR_NOERROR) {
1174       if (tree) {
1175         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1176             "ERROR: Couldn't parse LDAP value set header: %s",
1177             asn1_err_to_str(ret));
1178       }
1179       return;
1180     }
1181     end_of_set = a->offset + set_length;
1182     while (a->offset < end_of_set) {
1183       if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, ASN1_UNI,
1184                       ASN1_OTS) != ASN1_ERR_NOERROR)
1185         return;
1186     }
1187   }
1188 }
1189
1190 static void dissect_ldap_request_add(ASN1_SCK *a, proto_tree *tree)
1191 {
1192   guint seq_length;
1193   int end_of_sequence;
1194   int ret;
1195
1196   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1197     return;
1198
1199   ret = read_sequence(a, &seq_length);
1200   if (ret != ASN1_ERR_NOERROR) {
1201     if (tree) {
1202       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1203           "ERROR: Couldn't parse add request sequence header: %s",
1204           asn1_err_to_str(ret));
1205     }
1206     return;
1207   }
1208
1209   end_of_sequence = a->offset + seq_length;
1210   while (a->offset < end_of_sequence)
1211   {
1212     proto_item *ti;
1213     proto_tree *attr_tree;
1214     guint set_length;
1215     int end_of_set;
1216
1217     ret = read_sequence(a, 0);
1218     if (ret != ASN1_ERR_NOERROR) {
1219       if (tree) {
1220         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1221             "ERROR: Couldn't parse LDAP attribute sequence header: %s",
1222             asn1_err_to_str(ret));
1223       }
1224       return;
1225     }
1226     if (read_string(a, tree, hf_ldap_message_attribute, &ti, 0, ASN1_UNI,
1227                     ASN1_OTS) != ASN1_ERR_NOERROR)
1228       return;
1229     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1230
1231     ret = read_set(a, &set_length);
1232     if (ret != ASN1_ERR_NOERROR) {
1233       if (tree) {
1234         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1235             "ERROR: Couldn't parse LDAP value set header: %s",
1236             asn1_err_to_str(ret));
1237       }
1238       return;
1239     }
1240     end_of_set = a->offset + set_length;
1241     while (a->offset < end_of_set) {
1242       if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1243         return;
1244     }
1245   }
1246 }
1247
1248 static void dissect_ldap_request_delete(ASN1_SCK *a, proto_tree *tree,
1249                 int start, guint length)
1250 {
1251   read_string_value(a, tree, hf_ldap_message_dn, NULL, NULL, start, length);
1252 }
1253
1254 static void dissect_ldap_request_modifyrdn(ASN1_SCK *a, proto_tree *tree,
1255                 guint length)
1256 {
1257   int start = a->offset;
1258
1259   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1260     return;
1261   if (read_string(a, tree, hf_ldap_message_modrdn_name, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1262     return;
1263   if (read_boolean(a, tree, hf_ldap_message_modrdn_delete, 0, 0) != ASN1_ERR_NOERROR)
1264     return;
1265
1266   if (a->offset < (int) (start + length)) {
1267     /* LDAP V3 Modify DN operation, with newSuperior */
1268     /*      "newSuperior     [0] LDAPDN OPTIONAL" (0x80) */
1269     if (read_string(a, tree, hf_ldap_message_modrdn_superior, 0, 0, ASN1_CTX, 0) != ASN1_ERR_NOERROR)
1270       return;
1271   }
1272 }
1273
1274 static void dissect_ldap_request_compare(ASN1_SCK *a, proto_tree *tree)
1275 {
1276   int start;
1277   int length;
1278   char *string1 = NULL;
1279   char *string2 = NULL;
1280   char *s1, *s2;
1281   char *compare;
1282   int ret;
1283
1284   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1285     return;
1286   ret = read_sequence(a, 0);
1287   if (ret != ASN1_ERR_NOERROR) {
1288     if (tree) {
1289       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1290           "ERROR: Couldn't parse compare request sequence header: %s",
1291           asn1_err_to_str(ret));
1292     }
1293     return;
1294   }
1295
1296   start = a->offset;
1297   ret = read_string(a, 0, -1, 0, &string1, ASN1_UNI, ASN1_OTS);
1298   if (ret != ASN1_ERR_NOERROR) {
1299     if (tree) {
1300       proto_tree_add_text(tree, a->tvb, start, 0,
1301         "ERROR: Couldn't parse compare type: %s", asn1_err_to_str(ret));
1302     }
1303     return;
1304   }
1305   ret = read_string(a, 0, -1, 0, &string2, ASN1_UNI, ASN1_OTS);
1306   if (ret != ASN1_ERR_NOERROR) {
1307     if (tree) {
1308       proto_tree_add_text(tree, a->tvb, start, 0,
1309         "ERROR: Couldn't parse compare value: %s", asn1_err_to_str(ret));
1310     }
1311     return;
1312   }
1313
1314   s1 = (string1 == NULL) ? "(null)" : string1;
1315   s2 = (string2 == NULL) ? "(null)" : string2;
1316   length = 2 + strlen(s1) + strlen(s2);
1317   compare = g_malloc0(length);
1318   snprintf(compare, length, "%s=%s", s1, s2);
1319   proto_tree_add_string(tree, hf_ldap_message_compare, a->tvb, start,
1320       a->offset-start, compare);
1321
1322   g_free(string1);
1323   g_free(string2);
1324   g_free(compare);
1325
1326   return;
1327 }
1328
1329 static void dissect_ldap_request_modify(ASN1_SCK *a, proto_tree *tree)
1330 {
1331   guint seq_length;
1332   int end_of_sequence;
1333   int ret;
1334
1335   if (read_string(a, tree, hf_ldap_message_dn, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1336     return;
1337   ret = read_sequence(a, &seq_length);
1338   if (ret != ASN1_ERR_NOERROR) {
1339     if (tree) {
1340       proto_tree_add_text(tree, a->tvb, a->offset, 0,
1341           "ERROR: Couldn't parse modify request sequence header: %s",
1342           asn1_err_to_str(ret));
1343     }
1344     return;
1345   }
1346   end_of_sequence = a->offset + seq_length;
1347   while (a->offset < end_of_sequence)
1348   {
1349     proto_item *ti;
1350     proto_tree *attr_tree;
1351     guint set_length;
1352     int end_of_set;
1353     guint operation;
1354
1355     ret = read_sequence(a, 0);
1356     if (ret != ASN1_ERR_NOERROR) {
1357       if (tree) {
1358         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1359             "ERROR: Couldn't parse modify request item sequence header: %s",
1360             asn1_err_to_str(ret));
1361       }
1362       return;
1363     }
1364     ret = read_integer(a, 0, -1, 0, &operation, ASN1_ENUM);
1365     if (ret != ASN1_ERR_NOERROR) {
1366       if (tree) {
1367         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1368           "ERROR: Couldn't parse modify operation: %s",
1369           asn1_err_to_str(ret));
1370         return;
1371       }
1372     }
1373     ret = read_sequence(a, 0);
1374     if (ret != ASN1_ERR_NOERROR) {
1375       if (tree) {
1376         proto_tree_add_text(tree, a->tvb, a->offset, 0,
1377             "ERROR: Couldn't parse modify request operation sequence header: %s",
1378             asn1_err_to_str(ret));
1379       }
1380       return;
1381     }
1382
1383     switch (operation)
1384     {
1385      case LDAP_MOD_ADD:
1386       if (read_string(a, tree, hf_ldap_message_modify_add, &ti, 0, ASN1_UNI,
1387                       ASN1_OTS) != ASN1_ERR_NOERROR)
1388         return;
1389       break;
1390
1391      case LDAP_MOD_REPLACE:
1392       if (read_string(a, tree, hf_ldap_message_modify_replace, &ti, 0,
1393                       ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1394         return;
1395       break;
1396
1397      case LDAP_MOD_DELETE:
1398       if (read_string(a, tree, hf_ldap_message_modify_delete, &ti, 0,
1399                       ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
1400         return;
1401       break;
1402
1403      default:
1404        proto_tree_add_text(tree, a->tvb, a->offset, 0,
1405             "Unknown LDAP modify operation (%u)", operation);
1406        return;
1407     }
1408     attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
1409
1410     ret = read_set(a, &set_length);
1411     if (ret != ASN1_ERR_NOERROR) {
1412       if (tree) {
1413         proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
1414             "ERROR: Couldn't parse LDAP value set header: %s",
1415             asn1_err_to_str(ret));
1416       }
1417       return;
1418     }
1419     end_of_set = a->offset + set_length;
1420     while (a->offset < end_of_set) {
1421       if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, ASN1_UNI,
1422                       ASN1_OTS) != ASN1_ERR_NOERROR)
1423         return;
1424     }
1425   }
1426 }
1427
1428 static void dissect_ldap_request_abandon(ASN1_SCK *a, proto_tree *tree,
1429                 int start, guint length)
1430 {
1431   read_integer_value(a, tree, hf_ldap_message_abandon_msgid, NULL, NULL,
1432                             start, length);
1433 }
1434
1435 static void
1436 dissect_ldap_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1437                      proto_tree *ldap_tree, gboolean first_time)
1438 {
1439   int message_id_start;
1440   int message_id_length;
1441   proto_item *ti;
1442   proto_tree *msg_tree = NULL;
1443   guint messageLength;
1444   guint messageId;
1445   int next_offset;
1446   guint protocolOpCls, protocolOpCon, protocolOpTag;
1447   gchar *typestr;
1448   guint opLen;
1449   ASN1_SCK a;
1450   int start;
1451   int ret;
1452
1453   asn1_open(&a, tvb, offset);
1454
1455   ret = read_sequence(&a, &messageLength);
1456   if (ret != ASN1_ERR_NOERROR)
1457   {
1458     if (first_time)
1459     {
1460       if (check_col(pinfo->cinfo, COL_INFO))
1461       {
1462         col_add_fstr(pinfo->cinfo, COL_INFO,
1463                     "Invalid LDAP message (Can't parse sequence header: %s)",
1464                     asn1_err_to_str(ret));
1465       }
1466     }
1467     if (ldap_tree)
1468     {
1469       proto_tree_add_text(ldap_tree, tvb, offset, -1,
1470                           "Invalid LDAP message (Can't parse sequence header: %s)",
1471                           asn1_err_to_str(ret));
1472     }
1473     return;
1474   }
1475
1476   message_id_start = a.offset;
1477   ret = read_integer(&a, 0, hf_ldap_message_id, 0, &messageId, ASN1_INT);
1478   if (ret != ASN1_ERR_NOERROR)
1479   {
1480     if (first_time && check_col(pinfo->cinfo, COL_INFO))
1481       col_add_fstr(pinfo->cinfo, COL_INFO, "Invalid LDAP packet (Can't parse Message ID: %s)",
1482                    asn1_err_to_str(ret));
1483     if (ldap_tree)
1484       proto_tree_add_text(ldap_tree, tvb, message_id_start, 1,
1485                           "Invalid LDAP packet (Can't parse Message ID: %s)",
1486                           asn1_err_to_str(ret));
1487       return;
1488   }
1489   message_id_length = a.offset - message_id_start;
1490
1491   start = a.offset;
1492   asn1_id_decode(&a, &protocolOpCls, &protocolOpCon, &protocolOpTag);
1493   if (protocolOpCls != ASN1_APL)
1494     typestr = "Bad message type (not Application)";
1495   else
1496     typestr = val_to_str(protocolOpTag, msgTypes, "Unknown message type (%u)");
1497
1498   if (first_time)
1499   {
1500     if (check_col(pinfo->cinfo, COL_INFO))
1501       col_add_fstr(pinfo->cinfo, COL_INFO, "MsgId=%u MsgType=%s",
1502                    messageId, typestr);
1503   }
1504
1505   if (ldap_tree)
1506   {
1507     ti = proto_tree_add_text(ldap_tree, tvb, message_id_start, messageLength, "Message: Id=%u  %s", messageId, typestr);
1508     msg_tree = proto_item_add_subtree(ti, ett_ldap_message);
1509     proto_tree_add_uint(msg_tree, hf_ldap_message_id, tvb, message_id_start, message_id_length, messageId);
1510     proto_tree_add_uint(msg_tree, hf_ldap_message_type, tvb,
1511                                start, a.offset - start, protocolOpTag);
1512   }
1513   start = a.offset;
1514   if (read_length(&a, msg_tree, hf_ldap_message_length, &opLen) != ASN1_ERR_NOERROR)
1515     return;
1516
1517   if (protocolOpCls != ASN1_APL)
1518   {
1519     if (ldap_tree)
1520     {
1521       proto_tree_add_text(msg_tree, a.tvb, a.offset, opLen,
1522                           "%s", typestr);
1523     }
1524   }
1525   else
1526   {
1527     switch (protocolOpTag)
1528     {
1529      case LDAP_REQ_BIND:
1530       dissect_ldap_request_bind(&a, msg_tree, tvb, pinfo);
1531       break;
1532      case LDAP_REQ_UNBIND:
1533       /* Nothing to dissect */
1534       break;
1535      case LDAP_REQ_SEARCH:
1536       if (ldap_tree)
1537         dissect_ldap_request_search(&a, msg_tree);
1538       break;
1539      case LDAP_REQ_MODIFY:
1540       if (ldap_tree)
1541         dissect_ldap_request_modify(&a, msg_tree);
1542       break;
1543      case LDAP_REQ_ADD:
1544       if (ldap_tree)
1545         dissect_ldap_request_add(&a, msg_tree);
1546       break;
1547      case LDAP_REQ_DELETE:
1548       if (ldap_tree)
1549         dissect_ldap_request_delete(&a, msg_tree, start, opLen);
1550       break;
1551      case LDAP_REQ_MODRDN:
1552       if (ldap_tree)
1553         dissect_ldap_request_modifyrdn(&a, msg_tree, opLen);
1554       break;
1555      case LDAP_REQ_COMPARE:
1556       if (ldap_tree)
1557         dissect_ldap_request_compare(&a, msg_tree);
1558       break;
1559      case LDAP_REQ_ABANDON:
1560       if (ldap_tree)
1561         dissect_ldap_request_abandon(&a, msg_tree, start, opLen);
1562       break;
1563      case LDAP_RES_BIND:
1564       dissect_ldap_response_bind(&a, msg_tree, start, opLen, tvb, pinfo);
1565       break;
1566      case LDAP_RES_SEARCH_ENTRY:
1567       if (ldap_tree)
1568         dissect_ldap_response_search_entry(&a, msg_tree);
1569       break;
1570      case LDAP_RES_SEARCH_RESULT:
1571      case LDAP_RES_MODIFY:
1572      case LDAP_RES_ADD:
1573      case LDAP_RES_DELETE:
1574      case LDAP_RES_MODRDN:
1575      case LDAP_RES_COMPARE:
1576       if (ldap_tree)
1577         dissect_ldap_result(&a, msg_tree);
1578       break;
1579      default:
1580       if (ldap_tree)
1581       {
1582         proto_tree_add_text(msg_tree, a.tvb, a.offset, opLen,
1583                             "Unknown LDAP operation (%u)", protocolOpTag);
1584       }
1585       break;
1586     }
1587   }
1588
1589   /*
1590    * XXX - what if "next_offset" is past the offset of the next top-level
1591    * sequence?  Show that as an error?
1592    */
1593   asn1_close(&a, &next_offset); /* XXX - use the new value of next_offset? */
1594 }
1595
1596 static void
1597 dissect_ldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1598 {
1599   int offset = 0;
1600   gboolean first_time = TRUE;
1601   conversation_t *conversation;
1602   ldap_auth_info_t *auth_info = NULL;
1603   gboolean doing_sasl_security = FALSE;
1604   guint length_remaining;
1605   guint32 sasl_length;
1606   guint32 message_data_len;
1607   proto_item *ti;
1608   proto_tree *ldap_tree = NULL;
1609   ASN1_SCK a;
1610   int ret;
1611   guint messageLength;
1612   int messageOffset;
1613   guint headerLength;
1614   guint length;
1615   gint available_length, reported_length;
1616   int len;
1617   proto_item *gitem = NULL;
1618   proto_tree *gtree = NULL;
1619   tvbuff_t *next_tvb;
1620
1621   /*
1622    * Do we have a conversation for this connection?
1623    */
1624   conversation = find_conversation(&pinfo->src, &pinfo->dst,
1625                                    pinfo->ptype, pinfo->srcport,
1626                                    pinfo->destport, 0);
1627   if (conversation != NULL) {
1628     /*
1629      * Yes - do we have any authentication mechanism for it?
1630      */
1631     auth_info = conversation_get_proto_data(conversation, proto_ldap);
1632     if (auth_info != NULL) {
1633       /*
1634        * Yes - what's the authentication type?
1635        */
1636       switch (auth_info->auth_type) {
1637
1638       case LDAP_AUTH_SASL:
1639         /*
1640          * It's SASL; are we using a security layer?
1641          */
1642         if (auth_info->first_auth_frame != 0 &&
1643             pinfo->fd->num >= auth_info->first_auth_frame)
1644           doing_sasl_security = TRUE;   /* yes */
1645       }
1646     }
1647   }
1648
1649   while (tvb_reported_length_remaining(tvb, offset) > 0) {
1650     /*
1651      * This will throw an exception if we don't have any data left.
1652      * That's what we want.  (See "tcp_dissect_pdus()", which is
1653      * similar, but doesn't have to deal with the SASL issues.
1654      * XXX - can we make "tcp_dissect_pdus()" provide enough information
1655      * to the "get_pdu_len" routine so that we could have one dealing
1656      * with the SASL issues, have that routine deal with SASL and
1657      * ASN.1, and just use "tcp_dissect_pdus()"?)
1658      */
1659     length_remaining = tvb_ensure_length_remaining(tvb, offset);
1660
1661     /*
1662      * Might we be doing a SASL security layer and, if so, *are* we doing
1663      * one?
1664      *
1665      * Just because we've seen a bind reply for SASL, that doesn't mean
1666      * that we're using a SASL security layer; I've seen captures in
1667      * which some SASL negotiations lead to a security layer being used
1668      * and other negotiations don't, and it's not obvious what's different
1669      * in the two negotiations.  Therefore, we assume that if the first
1670      * byte is 0, it's a length for a SASL security layer (that way, we
1671      * never reassemble more than 16 megabytes, protecting us from
1672      * chewing up *too* much memory), and otherwise that it's an LDAP
1673      * message (actually, if it's an LDAP message it should begin with 0x30,
1674      * but we want to parse garbage as LDAP messages rather than really
1675      * huge lengths).
1676      */
1677     if (doing_sasl_security && tvb_get_guint8(tvb, offset) == 0) {
1678       /*
1679        * Yes.  The frame begins with a 4-byte big-endian length.
1680        * Can we do reassembly?
1681        */
1682       if (ldap_desegment && pinfo->can_desegment) {
1683         /*
1684          * Yes - is the SASL length split across segment boundaries?
1685          */
1686         if (length_remaining < 4) {
1687           /*
1688            * Yes.  Tell the TCP dissector where the data for this message
1689            * starts in the data it handed us, and how many more bytes we
1690            * need, and return.
1691            */
1692           pinfo->desegment_offset = offset;
1693           pinfo->desegment_len = 4 - length_remaining;
1694           return;
1695         }
1696       }
1697
1698       /*
1699        * Get the SASL length, which is the length of data in the buffer
1700        * following the length (i.e., it's 4 less than the total length).
1701        *
1702        * XXX - do we need to reassemble buffers?  For now, we
1703        * assume that each LDAP message is entirely contained within
1704        * a buffer.
1705        */
1706       sasl_length = tvb_get_ntohl(tvb, offset);
1707       message_data_len = sasl_length + 4;
1708       if (message_data_len < 4) {
1709         /*
1710          * The message length was probably so large that the total length
1711          * overflowed.
1712          *
1713          * Report this as an error.
1714          */
1715         show_reported_bounds_error(tvb, pinfo, tree);
1716         return;
1717       }
1718
1719       /*
1720        * Can we do reassembly?
1721        */
1722       if (ldap_desegment && pinfo->can_desegment) {
1723         /*
1724          * Yes - is the buffer split across segment boundaries?
1725          */
1726         if (length_remaining < message_data_len) {
1727           /*
1728            * Yes.  Tell the TCP dissector where the data for this message
1729            * starts in the data it handed us, and how many more bytes we
1730            * need, and return.
1731            */
1732           pinfo->desegment_offset = offset;
1733           pinfo->desegment_len = message_data_len - length_remaining;
1734           return;
1735         }
1736       }
1737
1738       /*
1739        * Construct a tvbuff containing the amount of the payload we have
1740        * available.  Make its reported length the amount of data in the PDU.
1741        *
1742        * XXX - if reassembly isn't enabled. the subdissector will throw a
1743        * BoundsError exception, rather than a ReportedBoundsError exception.
1744        * We really want a tvbuff where the length is "length", the reported
1745        * length is "plen", and the "if the snapshot length were infinite"
1746        * length is the minimum of the reported length of the tvbuff handed
1747        * to us and "plen", with a new type of exception thrown if the offset
1748        * is within the reported length but beyond that third length, with
1749        * that exception getting the "Unreassembled Packet" error.
1750        */
1751       length = length_remaining;
1752       if (length > message_data_len)
1753         length = message_data_len;
1754       next_tvb = tvb_new_subset(tvb, offset, length, message_data_len);
1755
1756       /*
1757        * If this is the first PDU, set the Protocol column and clear the
1758        * Info column.
1759        */
1760       if (first_time)
1761       {
1762         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1763           col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDAP");
1764         if (check_col(pinfo->cinfo, COL_INFO))
1765           col_clear(pinfo->cinfo, COL_INFO);
1766       }
1767
1768       if (tree)
1769       {
1770         ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
1771         ldap_tree = proto_item_add_subtree(ti, ett_ldap);
1772
1773         proto_tree_add_uint(ldap_tree, hf_ldap_sasl_buffer_length, tvb, 0, 4,
1774                             sasl_length);
1775       }
1776
1777       if (auth_info->auth_mech != NULL &&
1778           strcmp(auth_info->auth_mech, "GSS-SPNEGO") == 0) {
1779           /*
1780            * This is GSS-API (using SPNEGO, but we should be done with
1781            * the negotiation by now).
1782            *
1783            * Dissect the GSS_Wrap() token; it'll return the length of
1784            * the token, from which we compute the offset in the tvbuff at
1785            * which the plaintext data, i.e. the LDAP message, begins.
1786            */
1787           available_length = tvb_length_remaining(tvb, 4);
1788           reported_length = tvb_reported_length_remaining(tvb, 4);
1789           g_assert(available_length >= 0);
1790           g_assert(reported_length >= 0);
1791           if (available_length > reported_length)
1792             available_length = reported_length;
1793           if ((guint)available_length > sasl_length - 4)
1794             available_length = sasl_length - 4;
1795           if ((guint)reported_length > sasl_length - 4)
1796             reported_length = sasl_length - 4;
1797           next_tvb = tvb_new_subset(tvb, 4, available_length, reported_length);
1798           if (tree)
1799           {
1800             gitem = proto_tree_add_text(ldap_tree, next_tvb, 0, -1, "GSS-API Token");
1801             gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
1802           }
1803           len = call_dissector(gssapi_wrap_handle, next_tvb, pinfo, gtree);
1804           g_assert(len != 0);   /* GSS_Wrap() dissectors can't reject data */
1805           if (gitem != NULL)
1806               proto_item_set_len(gitem, len);
1807
1808           /*
1809            * Now dissect the LDAP message.
1810            */
1811           dissect_ldap_message(tvb, 4 + len, pinfo, ldap_tree, first_time);
1812       } else {
1813         /*
1814          * We don't know how to handle other authentication mechanisms
1815          * yet, so just put in an entry for the SASL buffer.
1816          */
1817         proto_tree_add_text(ldap_tree, tvb, 4, -1, "SASL buffer");
1818       }
1819       offset += message_data_len;
1820     } else {
1821       /*
1822        * No, we're not doing a SASL security layer.  The frame begins
1823        * with a "Sequence Of" header.
1824        * Can we do reassembly?
1825        */
1826       if (ldap_desegment && pinfo->can_desegment) {
1827         /*
1828          * Yes - is the "Sequence Of" header split across segment
1829          * boundaries?  We require at least 6 bytes for the header
1830          * which allows for a 4 byte length (ASN.1 BER).
1831          */
1832         if (length_remaining < 6) {
1833           pinfo->desegment_offset = offset;
1834           pinfo->desegment_len = 6 - length_remaining;
1835           return;
1836         }
1837       }
1838
1839       /*
1840        * OK, try to read the "Sequence Of" header; this gets the total
1841        * length of the LDAP message.
1842        */
1843       asn1_open(&a, tvb, offset);
1844       ret = read_sequence(&a, &messageLength);
1845       asn1_close(&a, &messageOffset);
1846
1847       if (ret == ASN1_ERR_NOERROR) {
1848         /*
1849          * Add the length of the "Sequence Of" header to the message
1850          * length.
1851          */
1852         headerLength = messageOffset - offset;
1853         messageLength += headerLength;
1854         if (messageLength < headerLength) {
1855           /*
1856            * The message length was probably so large that the total length
1857            * overflowed.
1858            *
1859            * Report this as an error.
1860            */
1861           show_reported_bounds_error(tvb, pinfo, tree);
1862           return;
1863         }
1864       } else {
1865         /*
1866          * We couldn't parse the header; just make it the amount of data
1867          * remaining in the tvbuff, so we'll give up on this segment
1868          * after attempting to parse the message - there's nothing more
1869          * we can do.  "dissect_ldap_message()" will display the error.
1870          */
1871         messageLength = length_remaining;
1872       }
1873
1874       /*
1875        * Can we do reassembly?
1876        */
1877       if (ldap_desegment && pinfo->can_desegment) {
1878         /*
1879          * Yes - is the message split across segment boundaries?
1880          */
1881         if (length_remaining < messageLength) {
1882           /*
1883            * Yes.  Tell the TCP dissector where the data for this message
1884            * starts in the data it handed us, and how many more bytes
1885            * we need, and return.
1886            */
1887           pinfo->desegment_offset = offset;
1888           pinfo->desegment_len = messageLength - length_remaining;
1889           return;
1890         }
1891       }
1892
1893       /*
1894        * If this is the first PDU, set the Protocol column and clear the
1895        * Info column.
1896        */
1897       if (first_time) {
1898         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1899           col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDAP");
1900         if (check_col(pinfo->cinfo, COL_INFO))
1901           col_clear(pinfo->cinfo, COL_INFO);
1902       }
1903
1904       /*
1905        * Construct a tvbuff containing the amount of the payload we have
1906        * available.  Make its reported length the amount of data in the
1907        * LDAP message.
1908        *
1909        * XXX - if reassembly isn't enabled. the subdissector will throw a
1910        * BoundsError exception, rather than a ReportedBoundsError exception.
1911        * We really want a tvbuff where the length is "length", the reported
1912        * length is "plen", and the "if the snapshot length were infinite"
1913        * length is the minimum of the reported length of the tvbuff handed
1914        * to us and "plen", with a new type of exception thrown if the offset
1915        * is within the reported length but beyond that third length, with
1916        * that exception getting the "Unreassembled Packet" error.
1917        */
1918       length = length_remaining;
1919       if (length > messageLength)
1920         length = messageLength;
1921       next_tvb = tvb_new_subset(tvb, offset, length, messageLength);
1922
1923       /*
1924        * Now dissect the LDAP message.
1925        */
1926       if (tree) {
1927         ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
1928         ldap_tree = proto_item_add_subtree(ti, ett_ldap);
1929       } else
1930         ldap_tree = NULL;
1931       dissect_ldap_message(next_tvb, 0, pinfo, ldap_tree, first_time);
1932
1933       offset += messageLength;
1934     }
1935
1936     first_time = FALSE;
1937   }
1938 }
1939
1940 static void
1941 ldap_reinit(void)
1942 {
1943   ldap_auth_info_t *auth_info;
1944
1945   /* Free up saved authentication mechanism strings */
1946   for (auth_info = auth_info_items; auth_info != NULL;
1947        auth_info = auth_info->next) {
1948     if (auth_info->auth_mech != NULL)
1949       g_free(auth_info->auth_mech);
1950   }
1951
1952   if (ldap_auth_info_chunk != NULL)
1953     g_mem_chunk_destroy(ldap_auth_info_chunk);
1954
1955   ldap_auth_info_chunk = g_mem_chunk_new("ldap_auth_info_chunk",
1956                 sizeof(ldap_auth_info_t),
1957                 ldap_auth_info_chunk_count * sizeof(ldap_auth_info_t),
1958                 G_ALLOC_ONLY);
1959 }
1960
1961 void
1962 proto_register_ldap(void)
1963 {
1964   static value_string result_codes[] = {
1965     {0, "Success"},
1966     {1, "Operations error"},
1967     {2, "Protocol error"},
1968     {3, "Time limit exceeded"},
1969     {4, "Size limit exceeded"},
1970     {5, "Compare false"},
1971     {6, "Compare true"},
1972     {7, "Authentication method not supported"},
1973     {8, "Strong authentication required"},
1974     {10, "Referral"},
1975     {11, "Administrative limit exceeded"},
1976     {12, "Unavailable critical extension"},
1977     {13, "Confidentiality required"},
1978     {14, "SASL bind in progress"},
1979     {16, "No such attribute"},
1980     {17, "Undefined attribute type"},
1981     {18, "Inappropriate matching"},
1982     {19, "Constraint violation"},
1983     {20, "Attribute or value exists"},
1984     {21, "Invalid attribute syntax"},
1985     {32, "No such object"},
1986     {33, "Alias problem"},
1987     {34, "Invalid DN syntax"},
1988     {36, "Alias derefetencing problem"},
1989     {48, "Inappropriate authentication"},
1990     {49, "Invalid credentials"},
1991     {50, "Insufficient access rights"},
1992     {51, "Busy"},
1993     {52, "Unavailable"},
1994     {53, "Unwilling to perform"},
1995     {54, "Loop detected"},
1996     {64, "Naming violation"},
1997     {65, "Objectclass violation"},
1998     {66, "Not allowed on non-leaf"},
1999     {67, "Not allowed on RDN"},
2000     {68, "Entry already exists"},
2001     {69, "Objectclass modification prohibited"},
2002     {71, "Affects multiple DSAs"},
2003     {80, "Other"},
2004     {0,  NULL},
2005   };
2006
2007   static value_string auth_types[] = {
2008     {LDAP_AUTH_SIMPLE,    "Simple"},
2009     {LDAP_AUTH_KRBV4LDAP, "Kerberos V4 to the LDAP server"},
2010     {LDAP_AUTH_KRBV4DSA,  "Kerberos V4 to the DSA"},
2011     {LDAP_AUTH_SASL,      "SASL"},
2012     {0, NULL},
2013   };
2014
2015   static value_string search_scope[] = {
2016     {0x00, "Base"},
2017     {0x01, "Single"},
2018     {0x02, "Subtree"},
2019     {0x00, NULL},
2020   };
2021
2022   static value_string search_dereference[] = {
2023     {0x00, "Never"},
2024     {0x01, "Searching"},
2025     {0x02, "Base Object"},
2026     {0x03, "Always"},
2027     {0x00, NULL},
2028   };
2029
2030   static hf_register_info hf[] = {
2031     { &hf_ldap_sasl_buffer_length,
2032       { "SASL Buffer Length",   "ldap.sasl_buffer_length",
2033         FT_UINT32, BASE_DEC, NULL, 0x0,
2034         "SASL Buffer Length", HFILL }},
2035
2036     { &hf_ldap_length,
2037       { "Length",               "ldap.length",
2038         FT_UINT32, BASE_DEC, NULL, 0x0,
2039         "LDAP Length", HFILL }},
2040
2041     { &hf_ldap_message_id,
2042       { "Message Id",           "ldap.message_id",
2043         FT_UINT32, BASE_DEC, NULL, 0x0,
2044         "LDAP Message Id", HFILL }},
2045     { &hf_ldap_message_type,
2046       { "Message Type",         "ldap.message_type",
2047         FT_UINT8, BASE_HEX, &msgTypes, 0x0,
2048         "LDAP Message Type", HFILL }},
2049     { &hf_ldap_message_length,
2050       { "Message Length",               "ldap.message_length",
2051         FT_UINT32, BASE_DEC, NULL, 0x0,
2052         "LDAP Message Length", HFILL }},
2053
2054     { &hf_ldap_message_result,
2055       { "Result Code",          "ldap.result.code",
2056         FT_UINT8, BASE_HEX, result_codes, 0x0,
2057         "LDAP Result Code", HFILL }},
2058     { &hf_ldap_message_result_matcheddn,
2059       { "Matched DN",           "ldap.result.matcheddn",
2060         FT_STRING, BASE_NONE, NULL, 0x0,
2061         "LDAP Result Matched DN", HFILL }},
2062     { &hf_ldap_message_result_errormsg,
2063       { "Error Message",                "ldap.result.errormsg",
2064         FT_STRING, BASE_NONE, NULL, 0x0,
2065         "LDAP Result Error Message", HFILL }},
2066     { &hf_ldap_message_result_referral,
2067       { "Referral",             "ldap.result.referral",
2068         FT_STRING, BASE_NONE, NULL, 0x0,
2069         "LDAP Result Referral URL", HFILL }},
2070
2071     { &hf_ldap_message_bind_version,
2072       { "Version",              "ldap.bind.version",
2073         FT_UINT32, BASE_DEC, NULL, 0x0,
2074         "LDAP Bind Version", HFILL }},
2075     { &hf_ldap_message_bind_dn,
2076       { "DN",                   "ldap.bind.dn",
2077         FT_STRING, BASE_NONE, NULL, 0x0,
2078         "LDAP Bind Distinguished Name", HFILL }},
2079     { &hf_ldap_message_bind_auth,
2080       { "Auth Type",            "ldap.bind.auth_type",
2081         FT_UINT8, BASE_HEX, auth_types, 0x0,
2082         "LDAP Bind Auth Type", HFILL }},
2083     { &hf_ldap_message_bind_auth_password,
2084       { "Password",             "ldap.bind.password",
2085         FT_STRING, BASE_NONE, NULL, 0x0,
2086         "LDAP Bind Password", HFILL }},
2087     { &hf_ldap_message_bind_auth_mechanism,
2088       { "Mechanism",            "ldap.bind.mechanism",
2089         FT_STRING, BASE_NONE, NULL, 0x0,
2090         "LDAP Bind Mechanism", HFILL }},
2091     { &hf_ldap_message_bind_auth_credentials,
2092       { "Credentials",          "ldap.bind.credentials",
2093         FT_BYTES, BASE_NONE, NULL, 0x0,
2094         "LDAP Bind Credentials", HFILL }},
2095     { &hf_ldap_message_bind_server_credentials,
2096       { "Server Credentials",   "ldap.bind.server_credentials",
2097         FT_BYTES, BASE_NONE, NULL, 0x0,
2098         "LDAP Bind Server Credentials", HFILL }},
2099
2100     { &hf_ldap_message_search_base,
2101       { "Base DN",              "ldap.search.basedn",
2102         FT_STRING, BASE_NONE, NULL, 0x0,
2103         "LDAP Search Base Distinguished Name", HFILL }},
2104     { &hf_ldap_message_search_scope,
2105       { "Scope",                        "ldap.search.scope",
2106         FT_UINT8, BASE_HEX, search_scope, 0x0,
2107         "LDAP Search Scope", HFILL }},
2108     { &hf_ldap_message_search_deref,
2109       { "Dereference",          "ldap.search.dereference",
2110         FT_UINT8, BASE_HEX, search_dereference, 0x0,
2111         "LDAP Search Dereference", HFILL }},
2112     { &hf_ldap_message_search_sizeLimit,
2113       { "Size Limit",           "ldap.search.sizelimit",
2114         FT_UINT32, BASE_DEC, NULL, 0x0,
2115         "LDAP Search Size Limit", HFILL }},
2116     { &hf_ldap_message_search_timeLimit,
2117       { "Time Limit",           "ldap.search.timelimit",
2118         FT_UINT32, BASE_DEC, NULL, 0x0,
2119         "LDAP Search Time Limit", HFILL }},
2120     { &hf_ldap_message_search_typesOnly,
2121       { "Attributes Only",      "ldap.search.typesonly",
2122         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2123         "LDAP Search Attributes Only", HFILL }},
2124     { &hf_ldap_message_search_filter,
2125       { "Filter",               "ldap.search.filter",
2126         FT_STRING, BASE_NONE, NULL, 0x0,
2127         "LDAP Search Filter", HFILL }},
2128     { &hf_ldap_message_dn,
2129       { "Distinguished Name",   "ldap.dn",
2130         FT_STRING, BASE_NONE, NULL, 0x0,
2131         "LDAP Distinguished Name", HFILL }},
2132     { &hf_ldap_message_attribute,
2133       { "Attribute",            "ldap.attribute",
2134         FT_STRING, BASE_NONE, NULL, 0x0,
2135         "LDAP Attribute", HFILL }},
2136     /*
2137      * XXX - not all LDAP values are text strings; we'd need a file
2138      * describing which values (by name) are text strings and which are
2139      * binary.
2140      *
2141      * Some values that are, at least in Microsoft's schema, binary
2142      * are:
2143      *
2144      *  invocationId
2145      *  nTSecurityDescriptor
2146      *  objectGUID
2147      */
2148     { &hf_ldap_message_value,
2149       { "Value",                "ldap.value",
2150         FT_STRING, BASE_NONE, NULL, 0x0,
2151         "LDAP Value", HFILL }},
2152
2153     { &hf_ldap_message_modrdn_name,
2154       { "New Name",             "ldap.modrdn.name",
2155         FT_STRING, BASE_NONE, NULL, 0x0,
2156         "LDAP New Name", HFILL }},
2157     { &hf_ldap_message_modrdn_delete,
2158       { "Delete Values",        "ldap.modrdn.delete",
2159         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2160         "LDAP Modify RDN - Delete original values", HFILL }},
2161     { &hf_ldap_message_modrdn_superior,
2162       { "New Location",         "ldap.modrdn.superior",
2163         FT_STRING, BASE_NONE, NULL, 0x0,
2164         "LDAP Modify RDN - New Location", HFILL }},
2165
2166     { &hf_ldap_message_compare,
2167       { "Test",         "ldap.compare.test",
2168         FT_STRING, BASE_NONE, NULL, 0x0,
2169         "LDAP Compare Test", HFILL }},
2170
2171     { &hf_ldap_message_modify_add,
2172       { "Add",                  "ldap.modify.add",
2173         FT_STRING, BASE_NONE, NULL, 0x0,
2174         "LDAP Add", HFILL }},
2175     { &hf_ldap_message_modify_replace,
2176       { "Replace",              "ldap.modify.replace",
2177         FT_STRING, BASE_NONE, NULL, 0x0,
2178         "LDAP Replace", HFILL }},
2179     { &hf_ldap_message_modify_delete,
2180       { "Delete",               "ldap.modify.delete",
2181         FT_STRING, BASE_NONE, NULL, 0x0,
2182         "LDAP Delete", HFILL }},
2183
2184     { &hf_ldap_message_abandon_msgid,
2185       { "Abandon Msg Id",       "ldap.abandon.msgid",
2186         FT_UINT32, BASE_DEC, NULL, 0x0,
2187         "LDAP Abandon Msg Id", HFILL }},
2188   };
2189
2190   static gint *ett[] = {
2191     &ett_ldap,
2192     &ett_ldap_message,
2193     &ett_ldap_gssapi_token,
2194     &ett_ldap_referrals,
2195     &ett_ldap_attribute
2196   };
2197   module_t *ldap_module;
2198
2199   proto_ldap = proto_register_protocol("Lightweight Directory Access Protocol",
2200                                        "LDAP", "ldap");
2201   proto_register_field_array(proto_ldap, hf, array_length(hf));
2202   proto_register_subtree_array(ett, array_length(ett));
2203
2204   ldap_module = prefs_register_protocol(proto_ldap, NULL);
2205   prefs_register_bool_preference(ldap_module, "desegment_ldap_messages",
2206     "Desegment all LDAP messages spanning multiple TCP segments",
2207     "Whether the LDAP dissector should desegment all messages spanning multiple TCP segments",
2208     &ldap_desegment);
2209
2210   register_init_routine(ldap_reinit);
2211 }
2212
2213 void
2214 proto_reg_handoff_ldap(void)
2215 {
2216   dissector_handle_t ldap_handle;
2217
2218   ldap_handle = create_dissector_handle(dissect_ldap, proto_ldap);
2219   dissector_add("tcp.port", TCP_PORT_LDAP, ldap_handle);
2220   dissector_add("udp.port", UDP_PORT_CLDAP, ldap_handle);
2221
2222   gssapi_handle = find_dissector("gssapi");
2223   gssapi_wrap_handle = find_dissector("gssapi_verf");
2224 }