2 * Routines for ldap packet dissection
4 * See RFC 1777 (LDAP v2), RFC 2251 (LDAP v3), and RFC 2222 (SASL).
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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.
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.
32 * There should probably be alot more error checking, I simply assume that if we have a full packet, it will be a complete
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
40 * nazard@dragoninc.on.ca
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
49 * ronald.henderson@cognicaseusa.com
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
61 * 17-DEC-2004 - added basic decoding for LDAP Controls
62 * 20-DEC-2004 - added handling for GSS-API encrypted blobs
64 * Stefan Metzmacher <metze@samba.org>
66 * 15-NOV-2005 - Changed to use the asn2wrs compiler
67 * Anders Broman <anders.broman@ericsson.com>
80 #include <epan/packet.h>
81 #include <epan/conversation.h>
82 #include <epan/prefs.h>
84 #include <epan/emem.h>
85 #include <epan/oid_resolv.h>
86 #include <epan/strutil.h>
87 #include <epan/dissectors/packet-tcp.h>
88 #include <epan/dissectors/packet-windows-common.h>
89 #include <epan/dissectors/packet-dcerpc.h>
91 #include "packet-frame.h"
92 #include "packet-ldap.h"
93 #include "packet-ntlmssp.h"
95 #include "packet-ber.h"
96 #include "packet-per.h"
98 #define PNAME "Lightweight-Directory-Access-Protocol"
100 #define PFNAME "ldap"
102 /* Initialize the protocol and registered fields */
103 static int ldap_tap = -1;
104 static int proto_ldap = -1;
105 static int proto_cldap = -1;
107 static int hf_ldap_sasl_buffer_length = -1;
108 static int hf_ldap_response_in = -1;
109 static int hf_ldap_response_to = -1;
110 static int hf_ldap_time = -1;
111 static int hf_ldap_guid = -1;
113 static int hf_mscldap_netlogon_type = -1;
114 static int hf_mscldap_netlogon_flags = -1;
115 static int hf_mscldap_netlogon_flags_pdc = -1;
116 static int hf_mscldap_netlogon_flags_gc = -1;
117 static int hf_mscldap_netlogon_flags_ldap = -1;
118 static int hf_mscldap_netlogon_flags_ds = -1;
119 static int hf_mscldap_netlogon_flags_kdc = -1;
120 static int hf_mscldap_netlogon_flags_timeserv = -1;
121 static int hf_mscldap_netlogon_flags_closest = -1;
122 static int hf_mscldap_netlogon_flags_writable = -1;
123 static int hf_mscldap_netlogon_flags_good_timeserv = -1;
124 static int hf_mscldap_netlogon_flags_ndnc = -1;
125 static int hf_mscldap_domain_guid = -1;
126 static int hf_mscldap_forest = -1;
127 static int hf_mscldap_domain = -1;
128 static int hf_mscldap_hostname = -1;
129 static int hf_mscldap_nb_domain = -1;
130 static int hf_mscldap_nb_hostname = -1;
131 static int hf_mscldap_username = -1;
132 static int hf_mscldap_sitename = -1;
133 static int hf_mscldap_clientsitename = -1;
134 static int hf_mscldap_netlogon_version = -1;
135 static int hf_mscldap_netlogon_lm_token = -1;
136 static int hf_mscldap_netlogon_nt_token = -1;
137 static int hf_ldap_sid = -1;
138 static int hf_ldap_AccessMask_ADS_CREATE_CHILD = -1;
139 static int hf_ldap_AccessMask_ADS_DELETE_CHILD = -1;
140 static int hf_ldap_AccessMask_ADS_LIST = -1;
141 static int hf_ldap_AccessMask_ADS_SELF_WRITE = -1;
142 static int hf_ldap_AccessMask_ADS_READ_PROP = -1;
143 static int hf_ldap_AccessMask_ADS_WRITE_PROP = -1;
144 static int hf_ldap_AccessMask_ADS_DELETE_TREE = -1;
145 static int hf_ldap_AccessMask_ADS_LIST_OBJECT = -1;
146 static int hf_ldap_AccessMask_ADS_CONTROL_ACCESS = -1;
148 #include "packet-ldap-hf.c"
150 /* Initialize the subtree pointers */
151 static gint ett_ldap = -1;
152 static gint ett_ldap_msg = -1;
153 static gint ett_ldap_sasl_blob = -1;
154 static guint ett_ldap_payload = -1;
155 static gint ett_mscldap_netlogon_flags = -1;
157 #include "packet-ldap-ett.c"
159 static dissector_table_t ldap_name_dissector_table=NULL;
160 static const char *object_identifier_id = NULL; /* LDAP OID */
162 /* desegmentation of LDAP */
163 static gboolean ldap_desegment = TRUE;
164 static guint ldap_tcp_port = 389;
166 static gboolean do_protocolop = FALSE;
167 static gchar *attr_type = NULL;
168 static gboolean is_binary_attr_type = FALSE;
170 #define TCP_PORT_LDAP 389
171 #define UDP_PORT_CLDAP 389
172 #define TCP_PORT_GLOBALCAT_LDAP 3268 /* Windows 2000 Global Catalog */
174 static dissector_handle_t gssapi_handle;
175 static dissector_handle_t gssapi_wrap_handle;
176 static dissector_handle_t ntlmssp_handle = NULL;
179 /* different types of rpc calls ontop of ms cldap */
180 #define MSCLDAP_RPC_NETLOGON 1
182 /* Message type Choice values */
183 static const value_string ldap_ProtocolOp_choice_vals[] = {
184 { 0, "bindRequest" },
185 { 1, "bindResponse" },
186 { 2, "unbindRequest" },
187 { 3, "searchRequest" },
188 { 4, "searchResEntry" },
189 { 5, "searchResDone" },
190 { 6, "searchResRef" },
191 { 7, "modifyRequest" },
192 { 8, "modifyResponse" },
194 { 10, "addResponse" },
195 { 11, "delRequest" },
196 { 12, "delResponse" },
197 { 13, "modDNRequest" },
198 { 14, "modDNResponse" },
199 { 15, "compareRequest" },
200 { 16, "compareResponse" },
201 { 17, "abandonRequest" },
202 { 18, "extendedReq" },
203 { 19, "extendedResp" },
207 * Data structure attached to a conversation, giving authentication
208 * information from a bind request.
209 * We keep a linked list of them, so that we can free up all the
210 * authentication mechanism strings.
212 typedef struct ldap_conv_info_t {
213 struct ldap_conv_info_t *next;
214 guint auth_type; /* authentication type */
215 char *auth_mech; /* authentication mechanism */
216 guint32 first_auth_frame; /* first frame that would use a security layer */
217 GHashTable *unmatched;
222 static ldap_conv_info_t *ldap_info_items;
225 ldap_info_hash_matched(gconstpointer k)
227 const ldap_call_response_t *key = k;
229 return key->messageId;
233 ldap_info_equal_matched(gconstpointer k1, gconstpointer k2)
235 const ldap_call_response_t *key1 = k1;
236 const ldap_call_response_t *key2 = k2;
238 if( key1->req_frame && key2->req_frame && (key1->req_frame!=key2->req_frame) ){
241 /* a response may span multiple frames
242 if( key1->rep_frame && key2->rep_frame && (key1->rep_frame!=key2->rep_frame) ){
247 return key1->messageId==key2->messageId;
251 ldap_info_hash_unmatched(gconstpointer k)
253 const ldap_call_response_t *key = k;
255 return key->messageId;
259 ldap_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
261 const ldap_call_response_t *key1 = k1;
262 const ldap_call_response_t *key2 = k2;
264 return key1->messageId==key2->messageId;
267 /* This string contains the last LDAPString that was decoded */
268 static char *attributedesc_string=NULL;
270 /* This string contains the last AssertionValue that was decoded */
271 static char *ldapvalue_string=NULL;
273 /* if the octet string contain all printable ASCII characters, then
274 * display it as a string, othervise just display it in hex.
277 dissect_ldap_AssertionValue(gboolean implicit_tag, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index)
280 gboolean pc, ind, is_ascii;
286 offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
287 offset=get_ber_length(NULL, tvb, offset, &len, &ind);
289 len=tvb_length_remaining(tvb,offset);
298 * Some special/wellknown attributes in common LDAP (read AD)
299 * are neither ascii strings nor blobs of hex data.
300 * Special case these attributes and decode them more nicely.
302 * Add more special cases as required to prettify further
303 * (there cant be that many ones that are truly interesting)
305 if(attributedesc_string && !strncmp("DomainSid", attributedesc_string, 9)){
309 /* this octet string contains an NT SID */
310 sid_tvb=tvb_new_subset(tvb, offset, len, len);
311 dissect_nt_sid(sid_tvb, 0, tree, "SID", &tmpstr, hf_index);
312 ldapvalue_string=tmpstr;
315 } else if ( (len==16) /* GUIDs are always 16 bytes */
316 && (attributedesc_string && !strncmp("DomainGuid", attributedesc_string, 10))) {
317 guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
320 /* This octet string contained a GUID */
321 dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, hf_ldap_guid, &uuid);
323 ldapvalue_string=ep_alloc(1024);
324 g_snprintf(ldapvalue_string, 1023, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
325 uuid.Data1, uuid.Data2, uuid.Data3,
326 uuid.Data4[0], uuid.Data4[1],
327 uuid.Data4[2], uuid.Data4[3],
328 uuid.Data4[4], uuid.Data4[5],
329 uuid.Data4[6], uuid.Data4[7]);
335 * It was not one of our "wellknown" attributes so make the best
336 * we can and just try to see if it is an ascii string or if it
339 * XXX - should we support reading RFC 2252-style schemas
340 * for LDAP, and using that to determine how to display
341 * attribute values and assertion values?
343 * -- I dont think there are full schemas available that describe the
344 * interesting cases i.e. AD -- ronnie
346 str=tvb_get_ptr(tvb, offset, len);
349 if(!isascii(str[i]) || !isprint(str[i])){
355 /* convert the string into a printable string */
357 ldapvalue_string=ep_alloc(len+1);
358 memcpy(ldapvalue_string,str,len);
359 ldapvalue_string[i]=0;
361 ldapvalue_string=ep_alloc(3*len);
363 g_snprintf(ldapvalue_string+i*3,3,"%02x",str[i]&0xff);
364 ldapvalue_string[3*i+2]=':';
366 ldapvalue_string[3*len-1]=0;
369 proto_tree_add_string(tree, hf_index, tvb, offset, len, ldapvalue_string);
377 /* This string contains the last Filter item that was decoded */
378 static char *Filter_string=NULL;
379 static char *and_filter_string=NULL;
380 static char *or_filter_string=NULL;
381 static char *substring_value=NULL;
382 static char *substring_item_init=NULL;
383 static char *substring_item_any=NULL;
384 static char *substring_item_final=NULL;
385 static char *matching_rule_string=NULL;
386 static gboolean matching_rule_dnattr=FALSE;
388 /* Global variables */
389 char *mechanism = NULL;
390 static gint MessageID =-1;
391 static gint ProtocolOp = -1;
392 static gint result = 0;
393 static proto_item *ldm_tree = NULL; /* item to add text to */
395 static void ldap_do_protocolop(packet_info *pinfo)
401 valstr = val_to_str(ProtocolOp, ldap_ProtocolOp_choice_vals, "Unknown (%%u)");
403 if(check_col(pinfo->cinfo, COL_INFO))
404 col_append_fstr(pinfo->cinfo, COL_INFO, "%s(%u) ", valstr, MessageID);
407 proto_item_append_text(ldm_tree, " %s(%d)", valstr, MessageID);
409 do_protocolop = FALSE;
414 static ldap_call_response_t *
415 ldap_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint messageId, guint protocolOpTag)
417 ldap_call_response_t lcr, *lcrp=NULL;
418 ldap_conv_info_t *ldap_info = (ldap_conv_info_t *)pinfo->private_data;
420 /* first see if we have already matched this */
422 lcr.messageId=messageId;
423 switch(protocolOpTag){
425 case LDAP_REQ_SEARCH:
426 case LDAP_REQ_MODIFY:
428 case LDAP_REQ_DELETE:
429 case LDAP_REQ_MODRDN:
430 case LDAP_REQ_COMPARE:
432 lcr.req_frame=pinfo->fd->num;
436 case LDAP_RES_SEARCH_ENTRY:
437 case LDAP_RES_SEARCH_REF:
438 case LDAP_RES_SEARCH_RESULT:
439 case LDAP_RES_MODIFY:
441 case LDAP_RES_DELETE:
442 case LDAP_RES_MODRDN:
443 case LDAP_RES_COMPARE:
444 lcr.is_request=FALSE;
446 lcr.rep_frame=pinfo->fd->num;
449 lcrp=g_hash_table_lookup(ldap_info->matched, &lcr);
453 lcrp->is_request=lcr.is_request;
457 /* we haven't found a match - try and match it up */
459 switch(protocolOpTag){
461 case LDAP_REQ_SEARCH:
462 case LDAP_REQ_MODIFY:
464 case LDAP_REQ_DELETE:
465 case LDAP_REQ_MODRDN:
466 case LDAP_REQ_COMPARE:
468 /* this a a request - add it to the unmatched list */
470 /* check that we dont already have one of those in the
471 unmatched list and if so remove it */
473 lcr.messageId=messageId;
474 lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
476 g_hash_table_remove(ldap_info->unmatched, lcrp);
478 /* if we cant reuse the old one, grab a new chunk */
480 lcrp=se_alloc(sizeof(ldap_call_response_t));
482 lcrp->messageId=messageId;
483 lcrp->req_frame=pinfo->fd->num;
484 lcrp->req_time=pinfo->fd->abs_ts;
486 lcrp->protocolOpTag=protocolOpTag;
487 lcrp->is_request=TRUE;
488 g_hash_table_insert(ldap_info->unmatched, lcrp, lcrp);
492 case LDAP_RES_SEARCH_ENTRY:
493 case LDAP_RES_SEARCH_REF:
494 case LDAP_RES_SEARCH_RESULT:
495 case LDAP_RES_MODIFY:
497 case LDAP_RES_DELETE:
498 case LDAP_RES_MODRDN:
499 case LDAP_RES_COMPARE:
501 /* this is a result - it should be in our unmatched list */
503 lcr.messageId=messageId;
504 lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
508 if(!lcrp->rep_frame){
509 g_hash_table_remove(ldap_info->unmatched, lcrp);
510 lcrp->rep_frame=pinfo->fd->num;
511 lcrp->is_request=FALSE;
512 g_hash_table_insert(ldap_info->matched, lcrp, lcrp);
520 /* we have found a match */
525 if(lcrp->is_request){
526 it=proto_tree_add_uint(tree, hf_ldap_response_in, tvb, 0, 0, lcrp->rep_frame);
527 PROTO_ITEM_SET_GENERATED(it);
530 it=proto_tree_add_uint(tree, hf_ldap_response_to, tvb, 0, 0, lcrp->req_frame);
531 PROTO_ITEM_SET_GENERATED(it);
532 nstime_delta(&ns, &pinfo->fd->abs_ts, &lcrp->req_time);
533 it=proto_tree_add_time(tree, hf_ldap_time, tvb, 0, 0, &ns);
534 PROTO_ITEM_SET_GENERATED(it);
541 #include "packet-ldap-fn.c"
544 dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo,
545 proto_tree *tree, ldap_conv_info_t *ldap_info,
546 gboolean rest_is_pad, gboolean is_mscldap)
549 guint length_remaining;
551 int messageOffset = 0;
552 guint headerLength = 0;
554 tvbuff_t *msg_tvb = NULL;
556 gboolean pc, ind = 0;
559 length_remaining = tvb_ensure_length_remaining(tvb, offset);
561 if (rest_is_pad && length_remaining < 6) return;
564 * OK, try to read the "Sequence Of" header; this gets the total
565 * length of the LDAP message.
567 messageOffset = get_ber_identifier(tvb, offset, &class, &pc, &ber_tag);
568 messageOffset = get_ber_length(tree, tvb, messageOffset, &msg_len, &ind);
570 if (ber_tag == BER_UNI_TAG_SEQUENCE) {
572 * Add the length of the "Sequence Of" header to the message
575 headerLength = messageOffset - offset;
576 msg_len += headerLength;
577 if (msg_len < headerLength) {
579 * The message length was probably so large that the total length
582 * Report this as an error.
584 show_reported_bounds_error(tvb, pinfo, tree);
589 * We couldn't parse the header; just make it the amount of data
590 * remaining in the tvbuff, so we'll give up on this segment
591 * after attempting to parse the message - there's nothing more
592 * we can do. "dissect_ldap_message()" will display the error.
594 msg_len = length_remaining;
598 * Construct a tvbuff containing the amount of the payload we have
599 * available. Make its reported length the amount of data in the
602 * XXX - if reassembly isn't enabled. the subdissector will throw a
603 * BoundsError exception, rather than a ReportedBoundsError exception.
604 * We really want a tvbuff where the length is "length", the reported
605 * length is "plen", and the "if the snapshot length were infinite"
606 * length is the minimum of the reported length of the tvbuff handed
607 * to us and "plen", with a new type of exception thrown if the offset
608 * is within the reported length but beyond that third length, with
609 * that exception getting the "Unreassembled Packet" error.
611 length = length_remaining;
612 if (length > msg_len) length = msg_len;
613 msg_tvb = tvb_new_subset(tvb, offset, length, msg_len);
616 * Now dissect the LDAP message.
619 ldap_info->is_mscldap = is_mscldap;
620 pinfo->private_data = ldap_info;
621 dissect_LDAPMessage_PDU(msg_tvb, pinfo, tree);
629 dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_mscldap)
632 conversation_t *conversation;
633 gboolean doing_sasl_security = FALSE;
634 guint length_remaining;
635 ldap_conv_info_t *ldap_info = NULL;
636 proto_item *ldap_item = NULL;
637 proto_tree *ldap_tree = NULL;
642 * Do we have a conversation for this connection?
644 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
645 pinfo->ptype, pinfo->srcport,
647 if (conversation == NULL) {
648 /* We don't yet have a conversation, so create one. */
649 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
650 pinfo->ptype, pinfo->srcport,
656 * Do we already have a type and mechanism?
658 ldap_info = conversation_get_proto_data(conversation, proto_ldap);
659 if (ldap_info == NULL) {
660 /* No. Attach that information to the conversation, and add
661 * it to the list of information structures.
663 ldap_info = se_alloc(sizeof(ldap_conv_info_t));
664 ldap_info->auth_type = 0;
665 ldap_info->auth_mech = 0;
666 ldap_info->first_auth_frame = 0;
667 ldap_info->matched=g_hash_table_new(ldap_info_hash_matched, ldap_info_equal_matched);
668 ldap_info->unmatched=g_hash_table_new(ldap_info_hash_unmatched, ldap_info_equal_unmatched);
669 ldap_info->num_results = 0;
671 conversation_add_proto_data(conversation, proto_ldap, ldap_info);
673 ldap_info->next = ldap_info_items;
674 ldap_info_items = ldap_info;
678 switch (ldap_info->auth_type) {
681 * It's SASL; are we using a security layer?
683 if (ldap_info->first_auth_frame != 0 &&
684 pinfo->fd->num >= ldap_info->first_auth_frame) {
685 doing_sasl_security = TRUE; /* yes */
689 length_remaining = tvb_ensure_length_remaining(tvb, offset);
691 /* It might still be a packet containing a SASL security layer
692 * but its just that we never saw the BIND packet.
693 * check if it looks like it could be a SASL blob here
694 * and in that case just assume it is GSS-SPNEGO
696 if(!doing_sasl_security && (tvb_bytes_exist(tvb, offset, 5))
697 &&(tvb_get_ntohl(tvb, offset)<=(guint)(tvb_reported_length_remaining(tvb, offset)-4))
698 &&(tvb_get_guint8(tvb, offset+4)==0x60) ){
699 ldap_info->auth_type=LDAP_AUTH_SASL;
700 ldap_info->first_auth_frame=pinfo->fd->num;
701 ldap_info->auth_mech=g_strdup("GSS-SPNEGO");
702 doing_sasl_security=TRUE;
706 * This is the first PDU, set the Protocol column and clear the
709 if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, pinfo->current_proto);
710 if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO);
712 ldap_item = proto_tree_add_item(tree, is_mscldap?proto_cldap:proto_ldap, tvb, 0, -1, FALSE);
713 ldap_tree = proto_item_add_subtree(ldap_item, ett_ldap);
716 * Might we be doing a SASL security layer and, if so, *are* we doing
719 * Just because we've seen a bind reply for SASL, that doesn't mean
720 * that we're using a SASL security layer; I've seen captures in
721 * which some SASL negotiations lead to a security layer being used
722 * and other negotiations don't, and it's not obvious what's different
723 * in the two negotiations. Therefore, we assume that if the first
724 * byte is 0, it's a length for a SASL security layer (that way, we
725 * never reassemble more than 16 megabytes, protecting us from
726 * chewing up *too* much memory), and otherwise that it's an LDAP
727 * message (actually, if it's an LDAP message it should begin with 0x30,
728 * but we want to parse garbage as LDAP messages rather than really
732 if (doing_sasl_security && tvb_get_guint8(tvb, offset) == 0) {
733 proto_item *sasl_item = NULL;
734 proto_tree *sasl_tree = NULL;
736 guint sasl_len, sasl_msg_len, length;
738 * Yes. The frame begins with a 4-byte big-endian length.
739 * And we know we have at least 6 bytes
743 * Get the SASL length, which is the length of data in the buffer
744 * following the length (i.e., it's 4 less than the total length).
746 * XXX - do we need to reassemble buffers? For now, we
747 * assume that each LDAP message is entirely contained within
750 sasl_len = tvb_get_ntohl(tvb, offset);
751 sasl_msg_len = sasl_len + 4;
752 if (sasl_msg_len < 4) {
754 * The message length was probably so large that the total length
757 * Report this as an error.
759 show_reported_bounds_error(tvb, pinfo, tree);
764 * Construct a tvbuff containing the amount of the payload we have
765 * available. Make its reported length the amount of data in the PDU.
767 * XXX - if reassembly isn't enabled. the subdissector will throw a
768 * BoundsError exception, rather than a ReportedBoundsError exception.
769 * We really want a tvbuff where the length is "length", the reported
770 * length is "plen", and the "if the snapshot length were infinite"
771 * length is the minimum of the reported length of the tvbuff handed
772 * to us and "plen", with a new type of exception thrown if the offset
773 * is within the reported length but beyond that third length, with
774 * that exception getting the "Unreassembled Packet" error.
776 length = length_remaining;
777 if (length > sasl_msg_len) length = sasl_msg_len;
778 sasl_tvb = tvb_new_subset(tvb, offset, length, sasl_msg_len);
781 proto_tree_add_uint(ldap_tree, hf_ldap_sasl_buffer_length, sasl_tvb, 0, 4,
784 sasl_item = proto_tree_add_text(ldap_tree, sasl_tvb, 0, sasl_msg_len, "SASL buffer");
785 sasl_tree = proto_item_add_subtree(sasl_item, ett_ldap_sasl_blob);
788 if (ldap_info->auth_mech != NULL &&
789 strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) {
790 tvbuff_t *gssapi_tvb, *plain_tvb = NULL, *decr_tvb= NULL;
795 * This is GSS-API (using SPNEGO, but we should be done with
796 * the negotiation by now).
798 * Dissect the GSS_Wrap() token; it'll return the length of
799 * the token, from which we compute the offset in the tvbuff at
800 * which the plaintext data, i.e. the LDAP message, begins.
802 length = tvb_length_remaining(sasl_tvb, 4);
803 if ((guint)length > sasl_len)
805 gssapi_tvb = tvb_new_subset(sasl_tvb, 4, length, sasl_len);
807 /* Attempt decryption of the GSSAPI wrapped data if possible */
808 pinfo->decrypt_gssapi_tvb=DECRYPT_GSSAPI_NORMAL;
809 pinfo->gssapi_wrap_tvb=NULL;
810 pinfo->gssapi_encrypted_tvb=NULL;
811 pinfo->gssapi_decrypted_tvb=NULL;
812 ver_len = call_dissector(gssapi_wrap_handle, gssapi_tvb, pinfo, sasl_tree);
813 /* if we could unwrap, do a tvb shuffle */
814 if(pinfo->gssapi_decrypted_tvb){
815 decr_tvb=pinfo->gssapi_decrypted_tvb;
818 pinfo->decrypt_gssapi_tvb=0;
819 pinfo->gssapi_wrap_tvb=NULL;
820 pinfo->gssapi_encrypted_tvb=NULL;
821 pinfo->gssapi_decrypted_tvb=NULL;
824 * if len is 0 it probably mean that we got a PDU that is not
825 * aligned to the start of the segment.
832 * if we don't have unwrapped data,
833 * see if the wrapping involved encryption of the
834 * data; if not, just use the plaintext data.
837 if(!pinfo->gssapi_data_encrypted){
838 plain_tvb = tvb_new_subset(gssapi_tvb, ver_len, -1, -1);
843 proto_item *enc_item = NULL;
844 proto_tree *enc_tree = NULL;
847 * The LDAP message was encrypted in the packet, and has
848 * been decrypted; dissect the decrypted LDAP message.
851 enc_item = proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
852 "GSS-API Encrypted payload (%d byte%s)",
854 plurality(sasl_len - ver_len, "", "s"));
855 enc_tree = proto_item_add_subtree(enc_item, ett_ldap_payload);
857 dissect_ldap_payload(decr_tvb, pinfo, enc_tree, ldap_info, TRUE, is_mscldap);
858 } else if (plain_tvb) {
859 proto_item *plain_item = NULL;
860 proto_tree *plain_tree = NULL;
863 * The LDAP message wasn't encrypted in the packet;
864 * dissect the plain LDAP message.
867 plain_item = proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
868 "GSS-API payload (%d byte%s)",
870 plurality(sasl_len - ver_len, "", "s"));
871 plain_tree = proto_item_add_subtree(plain_item, ett_ldap_payload);
874 dissect_ldap_payload(plain_tvb, pinfo, plain_tree, ldap_info, TRUE, is_mscldap);
877 * The LDAP message was encrypted in the packet, and was
878 * not decrypted; just show it as encrypted data.
880 if (check_col(pinfo->cinfo, COL_INFO)) {
881 col_add_fstr(pinfo->cinfo, COL_INFO, "LDAP GSS-API Encrypted payload (%d byte%s)",
883 plurality(sasl_len - ver_len, "", "s"));
886 proto_tree_add_text(sasl_tree, gssapi_tvb, ver_len, -1,
887 "GSS-API Encrypted payload (%d byte%s)",
889 plurality(sasl_len - ver_len, "", "s"));
893 offset += sasl_msg_len;
895 /* plain LDAP, so dissect the payload */
896 dissect_ldap_payload(tvb, pinfo, ldap_tree, ldap_info, FALSE, is_mscldap);
900 static int dissect_mscldap_string(tvbuff_t *tvb, int offset, char *str, int maxlen, gboolean prepend_dot)
904 len=tvb_get_guint8(tvb, offset);
909 /* add potential field separation dot */
922 /* ops its a mscldap compressed string */
924 new_offset=tvb_get_guint8(tvb, offset);
925 if (new_offset == offset - 1)
926 THROW(ReportedBoundsError);
929 dissect_mscldap_string(tvb, new_offset, str, maxlen, FALSE);
943 return offset; /* will mess up offset in caller, is unlikely */
945 tvb_memcpy(tvb, str, offset, len);
952 len=tvb_get_guint8(tvb, offset);
959 /* These flag bits were found to be defined in the samba sources.
960 * I hope they are correct (but have serious doubts about the CLOSEST
961 * bit being used or being meaningful).
963 static const true_false_string tfs_ads_pdc = {
967 static const true_false_string tfs_ads_gc = {
968 "This is a GLOBAL CATALOGUE of forest",
969 "This is NOT a global catalog of forest"
971 static const true_false_string tfs_ads_ldap = {
972 "This is an LDAP server",
973 "This is NOT an ldap server"
975 static const true_false_string tfs_ads_ds = {
976 "This dc supports DS",
977 "This dc does NOT support ds"
979 static const true_false_string tfs_ads_kdc = {
980 "This is a KDC (kerberos)",
981 "This is NOT a kdc (kerberos)"
983 static const true_false_string tfs_ads_timeserv = {
984 "This dc is running TIME SERVICES (ntp)",
985 "This dc is NOT running time services (ntp)"
987 static const true_false_string tfs_ads_closest = {
988 "This is the CLOSEST dc (unreliable?)",
989 "This is NOT the closest dc"
991 static const true_false_string tfs_ads_writable = {
992 "This dc is WRITABLE",
993 "This dc is NOT writable"
995 static const true_false_string tfs_ads_good_timeserv = {
996 "This dc has a GOOD TIME SERVICE (i.e. hardware clock)",
997 "This dc does NOT have a good time service (i.e. no hardware clock)"
999 static const true_false_string tfs_ads_ndnc = {
1000 "Domain is NON-DOMAIN NC serviced by ldap server",
1001 "Domain is NOT non-domain nc serviced by ldap server"
1003 static int dissect_mscldap_netlogon_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
1007 proto_tree *tree=NULL;
1008 guint fields[] = { hf_mscldap_netlogon_flags_ndnc,
1009 hf_mscldap_netlogon_flags_good_timeserv,
1010 hf_mscldap_netlogon_flags_writable,
1011 hf_mscldap_netlogon_flags_closest,
1012 hf_mscldap_netlogon_flags_timeserv,
1013 hf_mscldap_netlogon_flags_kdc,
1014 hf_mscldap_netlogon_flags_ds,
1015 hf_mscldap_netlogon_flags_ldap,
1016 hf_mscldap_netlogon_flags_gc,
1017 hf_mscldap_netlogon_flags_pdc,
1020 header_field_info *hfi;
1021 gboolean one_bit_set = FALSE;
1023 flags=tvb_get_letohl(tvb, offset);
1024 item=proto_tree_add_item(parent_tree, hf_mscldap_netlogon_flags, tvb, offset, 4, TRUE);
1026 tree = proto_item_add_subtree(item, ett_mscldap_netlogon_flags);
1029 proto_item_append_text(item, " (");
1031 for(field = fields; *field; field++) {
1032 proto_tree_add_boolean(tree, *field, tvb, offset, 4, flags);
1033 hfi = proto_registrar_get_nth(*field);
1035 if(flags & hfi->bitmask) {
1038 proto_item_append_text(item, ", ");
1042 proto_item_append_text(item, hfi->name);
1047 proto_item_append_text(item, ")");
1054 static void dissect_NetLogon_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1056 int old_offset, offset=0;
1064 /*XXX someone that knows what the type means should add that knowledge here*/
1065 proto_tree_add_item(tree, hf_mscldap_netlogon_type, tvb, offset, 4, TRUE);
1069 offset = dissect_mscldap_netlogon_flags(tree, tvb, offset);
1072 proto_tree_add_item(tree, hf_mscldap_domain_guid, tvb, offset, 16, TRUE);
1077 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1078 proto_tree_add_string(tree, hf_mscldap_forest, tvb, old_offset, offset-old_offset, str);
1082 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1083 proto_tree_add_string(tree, hf_mscldap_domain, tvb, old_offset, offset-old_offset, str);
1087 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1088 proto_tree_add_string(tree, hf_mscldap_hostname, tvb, old_offset, offset-old_offset, str);
1090 /* NetBios Domain */
1092 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1093 proto_tree_add_string(tree, hf_mscldap_nb_domain, tvb, old_offset, offset-old_offset, str);
1095 /* NetBios Hostname */
1097 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1098 proto_tree_add_string(tree, hf_mscldap_nb_hostname, tvb, old_offset, offset-old_offset, str);
1102 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1103 proto_tree_add_string(tree, hf_mscldap_username, tvb, old_offset, offset-old_offset, str);
1107 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1108 proto_tree_add_string(tree, hf_mscldap_sitename, tvb, old_offset, offset-old_offset, str);
1112 offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
1113 proto_tree_add_string(tree, hf_mscldap_clientsitename, tvb, old_offset, offset-old_offset, str);
1116 proto_tree_add_item(tree, hf_mscldap_netlogon_version, tvb, offset, 4, TRUE);
1120 proto_tree_add_item(tree, hf_mscldap_netlogon_lm_token, tvb, offset, 2, TRUE);
1124 proto_tree_add_item(tree, hf_mscldap_netlogon_nt_token, tvb, offset, 2, TRUE);
1131 get_sasl_ldap_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1133 /* sasl encapsulated ldap is 4 bytes plus the length in size */
1134 return tvb_get_ntohl(tvb, offset)+4;
1138 dissect_sasl_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1140 dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
1145 get_normal_ldap_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1151 /* normal ldap is tag+len bytes plus the length
1152 * offset is where the tag is
1153 * offset+1 is where length starts
1155 data_offset=get_ber_length(NULL, tvb, offset+1, &len, &ind);
1156 return len+data_offset-offset;
1160 dissect_normal_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1162 dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
1167 dissect_ldap_oid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1170 const char *oidname;
1172 /* tvb here contains an ascii string that is really an oid */
1173 /* XXX we should convert the string oid into a real oid so we can use
1174 * proto_tree_add_oid() instead.
1177 oid=tvb_get_ephemeral_string(tvb, 0, tvb_length(tvb));
1182 oidname=get_oid_str_name(oid);
1185 proto_tree_add_text(tree, tvb, 0, tvb_length(tvb), "OID: %s (%s)",oid,oidname);
1187 proto_tree_add_text(tree, tvb, 0, tvb_length(tvb), "OID: %s",oid);
1191 #define LDAP_ACCESSMASK_ADS_CREATE_CHILD 0x00000001
1192 static const true_false_string ldap_AccessMask_ADS_CREATE_CHILD_tfs = {
1193 "ADS CREATE CHILD is SET",
1194 "Ads create child is NOT set",
1197 #define LDAP_ACCESSMASK_ADS_DELETE_CHILD 0x00000002
1198 static const true_false_string ldap_AccessMask_ADS_DELETE_CHILD_tfs = {
1199 "ADS DELETE CHILD is SET",
1200 "Ads delete child is NOT set",
1202 #define LDAP_ACCESSMASK_ADS_LIST 0x00000004
1203 static const true_false_string ldap_AccessMask_ADS_LIST_tfs = {
1205 "Ads list is NOT set",
1207 #define LDAP_ACCESSMASK_ADS_SELF_WRITE 0x00000008
1208 static const true_false_string ldap_AccessMask_ADS_SELF_WRITE_tfs = {
1209 "ADS SELF WRITE is SET",
1210 "Ads self write is NOT set",
1212 #define LDAP_ACCESSMASK_ADS_READ_PROP 0x00000010
1213 static const true_false_string ldap_AccessMask_ADS_READ_PROP_tfs = {
1214 "ADS READ PROP is SET",
1215 "Ads read prop is NOT set",
1217 #define LDAP_ACCESSMASK_ADS_WRITE_PROP 0x00000020
1218 static const true_false_string ldap_AccessMask_ADS_WRITE_PROP_tfs = {
1219 "ADS WRITE PROP is SET",
1220 "Ads write prop is NOT set",
1222 #define LDAP_ACCESSMASK_ADS_DELETE_TREE 0x00000040
1223 static const true_false_string ldap_AccessMask_ADS_DELETE_TREE_tfs = {
1224 "ADS DELETE TREE is SET",
1225 "Ads delete tree is NOT set",
1227 #define LDAP_ACCESSMASK_ADS_LIST_OBJECT 0x00000080
1228 static const true_false_string ldap_AccessMask_ADS_LIST_OBJECT_tfs = {
1229 "ADS LIST OBJECT is SET",
1230 "Ads list object is NOT set",
1232 #define LDAP_ACCESSMASK_ADS_CONTROL_ACCESS 0x00000100
1233 static const true_false_string ldap_AccessMask_ADS_CONTROL_ACCESS_tfs = {
1234 "ADS CONTROL ACCESS is SET",
1235 "Ads control access is NOT set",
1239 ldap_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree, guint32 access)
1241 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_CONTROL_ACCESS, tvb, offset, 4, access);
1243 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_LIST_OBJECT, tvb, offset, 4, access);
1245 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_DELETE_TREE, tvb, offset, 4, access);
1247 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_WRITE_PROP, tvb, offset, 4, access);
1249 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_READ_PROP, tvb, offset, 4, access);
1251 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_SELF_WRITE, tvb, offset, 4, access);
1253 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_LIST, tvb, offset, 4, access);
1255 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_DELETE_CHILD, tvb, offset, 4, access);
1257 proto_tree_add_boolean(tree, hf_ldap_AccessMask_ADS_CREATE_CHILD, tvb, offset, 4, access);
1259 struct access_mask_info ldap_access_mask_info = {
1260 "LDAP", /* Name of specific rights */
1261 ldap_specific_rights, /* Dissection function */
1262 NULL, /* Generic mapping table */
1263 NULL /* Standard mapping table */
1267 dissect_ldap_nt_sec_desc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1269 dissect_nt_sec_desc(tvb, 0, pinfo, tree, NULL, TRUE, tvb_length(tvb), &ldap_access_mask_info);
1273 dissect_ldap_sid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1277 /* this octet string contains an NT SID */
1278 dissect_nt_sid(tvb, 0, tree, "SID", &tmpstr, hf_ldap_sid);
1279 ldapvalue_string=tmpstr;
1283 dissect_ldap_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1285 guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1288 /* This octet string contained a GUID */
1289 dissect_dcerpc_uuid_t(tvb, 0, pinfo, tree, drep, hf_ldap_guid, &uuid);
1291 ldapvalue_string=ep_alloc(1024);
1292 g_snprintf(ldapvalue_string, 1023, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1293 uuid.Data1, uuid.Data2, uuid.Data3,
1294 uuid.Data4[0], uuid.Data4[1],
1295 uuid.Data4[2], uuid.Data4[3],
1296 uuid.Data4[4], uuid.Data4[5],
1297 uuid.Data4[6], uuid.Data4[7]);
1301 dissect_ldap_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1311 /* This is a bit tricky. We have to find out whether SASL is used
1312 * so that we know how big a header we are supposed to pass
1313 * to tcp_dissect_pdus()
1315 /* check for a SASL header, i.e. assume it is SASL if
1316 * 1, first four bytes (SASL length) is an integer
1317 * with a value that must be <64k and >2
1318 * (>2 to fight false positives, 0x00000000 is a common
1319 * "random" tcp payload)
1320 * (no SASL ldap PDUs are ever going to be >64k in size?)
1322 * Following the SASL header is a GSSAPI blob so the next byte
1323 * is always 0x60. (only true for MS SASL LDAP, there are other
1324 * blobs that may follow in real-world)
1326 * 2, Then one byte with the value 0x60 indicating the GSSAPI blob
1328 * 3, Then X bytes describing the BER encoded lengtyh of the blob.
1329 * This length should point to the same end-of-pdu as 1,
1331 * 4, finally a byte 0x06 indicating that the next object is an OID
1333 sasl_len=tvb_get_ntohl(tvb, 0);
1336 goto this_was_not_sasl;
1339 if(tvb_get_guint8(tvb, 4)!=0x60){
1340 goto this_was_not_sasl;
1343 offset=get_ber_length(NULL, tvb, 5, &gss_len, &ind);
1344 if(sasl_len!=(gss_len+offset-4)){
1345 goto this_was_not_sasl;
1348 if(tvb_get_guint8(tvb, offset)!=0x06){
1349 goto this_was_not_sasl;
1352 tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_sasl_ldap_pdu_len, dissect_sasl_ldap_pdu);
1356 /* check if it is a normal BER encoded LDAP packet
1357 * i.e. first byte is 0x30 followed by a length that is
1359 * (no ldap PDUs are ever >64kb? )
1361 if(tvb_get_guint8(tvb, 0)!=0x30){
1362 goto this_was_not_normal_ldap;
1365 /* check that length makes sense */
1366 offset=get_ber_length(NULL, tvb, 1, &ldap_len, &ind);
1368 /* dont check ind since indefinite length is never used for ldap (famous last words)*/
1370 goto this_was_not_normal_ldap;
1373 tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_normal_ldap_pdu_len, dissect_normal_ldap_pdu);
1376 this_was_not_normal_ldap:
1382 dissect_mscldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1384 dissect_ldap_pdu(tvb, pinfo, tree, TRUE);
1392 ldap_conv_info_t *ldap_info;
1394 /* Free up state attached to the ldap_info structures */
1395 for (ldap_info = ldap_info_items; ldap_info != NULL; ldap_info = ldap_info->next) {
1396 if (ldap_info->auth_mech != NULL) {
1397 g_free(ldap_info->auth_mech);
1398 ldap_info->auth_mech=NULL;
1400 g_hash_table_destroy(ldap_info->matched);
1401 ldap_info->matched=NULL;
1402 g_hash_table_destroy(ldap_info->unmatched);
1403 ldap_info->unmatched=NULL;
1406 ldap_info_items = NULL;
1411 register_ldap_name_dissector_handle(const char *attr_type, dissector_handle_t dissector)
1413 dissector_add_string("ldap.name", attr_type, dissector);
1417 register_ldap_name_dissector(const char *attr_type, dissector_t dissector, int proto)
1419 dissector_handle_t dissector_handle;
1421 dissector_handle=create_dissector_handle(dissector, proto);
1422 register_ldap_name_dissector_handle(attr_type, dissector_handle);
1426 /*--- proto_register_ldap -------------------------------------------*/
1427 void proto_register_ldap(void) {
1429 /* List of fields */
1431 static hf_register_info hf[] = {
1433 { &hf_ldap_sasl_buffer_length,
1434 { "SASL Buffer Length", "ldap.sasl_buffer_length",
1435 FT_UINT32, BASE_DEC, NULL, 0x0,
1436 "SASL Buffer Length", HFILL }},
1437 { &hf_ldap_response_in,
1438 { "Response In", "ldap.response_in",
1439 FT_FRAMENUM, BASE_DEC, NULL, 0x0,
1440 "The response to this LDAP request is in this frame", HFILL }},
1441 { &hf_ldap_response_to,
1442 { "Response To", "ldap.response_to",
1443 FT_FRAMENUM, BASE_DEC, NULL, 0x0,
1444 "This is a response to the LDAP request in this frame", HFILL }},
1446 { "Time", "ldap.time",
1447 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1448 "The time between the Call and the Reply", HFILL }},
1450 { &hf_mscldap_netlogon_type,
1451 { "Type", "mscldap.netlogon.type",
1452 FT_UINT32, BASE_DEC, NULL, 0x0,
1453 "Type of <please tell Wireshark developers what this type is>", HFILL }},
1455 { &hf_mscldap_netlogon_version,
1456 { "Version", "mscldap.netlogon.version",
1457 FT_UINT32, BASE_DEC, NULL, 0x0,
1458 "Version of <please tell Wireshark developers what this type is>", HFILL }},
1460 { &hf_mscldap_netlogon_lm_token,
1461 { "LM Token", "mscldap.netlogon.lm_token",
1462 FT_UINT16, BASE_HEX, NULL, 0x0,
1463 "LM Token", HFILL }},
1465 { &hf_mscldap_netlogon_nt_token,
1466 { "NT Token", "mscldap.netlogon.nt_token",
1467 FT_UINT16, BASE_HEX, NULL, 0x0,
1468 "NT Token", HFILL }},
1470 { &hf_mscldap_netlogon_flags,
1471 { "Flags", "mscldap.netlogon.flags",
1472 FT_UINT32, BASE_HEX, NULL, 0x0,
1473 "Netlogon flags describing the DC properties", HFILL }},
1475 { &hf_mscldap_domain_guid,
1476 { "Domain GUID", "mscldap.domain.guid",
1477 FT_BYTES, BASE_HEX, NULL, 0x0,
1478 "Domain GUID", HFILL }},
1480 { &hf_mscldap_forest,
1481 { "Forest", "mscldap.forest",
1482 FT_STRING, BASE_NONE, NULL, 0x0,
1485 { &hf_mscldap_domain,
1486 { "Domain", "mscldap.domain",
1487 FT_STRING, BASE_NONE, NULL, 0x0,
1488 "Domainname", HFILL }},
1490 { &hf_mscldap_hostname,
1491 { "Hostname", "mscldap.hostname",
1492 FT_STRING, BASE_NONE, NULL, 0x0,
1493 "Hostname", HFILL }},
1495 { &hf_mscldap_nb_domain,
1496 { "NetBios Domain", "mscldap.nb_domain",
1497 FT_STRING, BASE_NONE, NULL, 0x0,
1498 "NetBios Domainname", HFILL }},
1500 { &hf_mscldap_nb_hostname,
1501 { "NetBios Hostname", "mscldap.nb_hostname",
1502 FT_STRING, BASE_NONE, NULL, 0x0,
1503 "NetBios Hostname", HFILL }},
1505 { &hf_mscldap_username,
1506 { "User", "mscldap.username",
1507 FT_STRING, BASE_NONE, NULL, 0x0,
1508 "User name", HFILL }},
1510 { &hf_mscldap_sitename,
1511 { "Site", "mscldap.sitename",
1512 FT_STRING, BASE_NONE, NULL, 0x0,
1513 "Site name", HFILL }},
1515 { &hf_mscldap_clientsitename,
1516 { "Client Site", "mscldap.clientsitename",
1517 FT_STRING, BASE_NONE, NULL, 0x0,
1518 "Client Site name", HFILL }},
1521 { "Sid", "ldap.sid",
1522 FT_STRING, BASE_NONE, NULL, 0x0,
1525 { &hf_mscldap_netlogon_flags_pdc,
1526 { "PDC", "mscldap.netlogon.flags.pdc", FT_BOOLEAN, 32,
1527 TFS(&tfs_ads_pdc), 0x00000001, "Is this DC a PDC or not?", HFILL }},
1529 { &hf_mscldap_netlogon_flags_gc,
1530 { "GC", "mscldap.netlogon.flags.gc", FT_BOOLEAN, 32,
1531 TFS(&tfs_ads_gc), 0x00000004, "Does this dc service as a GLOBAL CATALOGUE?", HFILL }},
1533 { &hf_mscldap_netlogon_flags_ldap,
1534 { "LDAP", "mscldap.netlogon.flags.ldap", FT_BOOLEAN, 32,
1535 TFS(&tfs_ads_ldap), 0x00000008, "Does this DC act as an LDAP server?", HFILL }},
1537 { &hf_mscldap_netlogon_flags_ds,
1538 { "DS", "mscldap.netlogon.flags.ds", FT_BOOLEAN, 32,
1539 TFS(&tfs_ads_ds), 0x00000010, "Does this dc provide DS services?", HFILL }},
1541 { &hf_mscldap_netlogon_flags_kdc,
1542 { "KDC", "mscldap.netlogon.flags.kdc", FT_BOOLEAN, 32,
1543 TFS(&tfs_ads_kdc), 0x00000020, "Does this dc act as a KDC?", HFILL }},
1545 { &hf_mscldap_netlogon_flags_timeserv,
1546 { "Time Serv", "mscldap.netlogon.flags.timeserv", FT_BOOLEAN, 32,
1547 TFS(&tfs_ads_timeserv), 0x00000040, "Does this dc provide time services (ntp) ?", HFILL }},
1549 { &hf_mscldap_netlogon_flags_closest,
1550 { "Closest", "mscldap.netlogon.flags.closest", FT_BOOLEAN, 32,
1551 TFS(&tfs_ads_closest), 0x00000080, "Is this the closest dc? (is this used at all?)", HFILL }},
1553 { &hf_mscldap_netlogon_flags_writable,
1554 { "Writable", "mscldap.netlogon.flags.writable", FT_BOOLEAN, 32,
1555 TFS(&tfs_ads_writable), 0x00000100, "Is this dc writable? (i.e. can it update the AD?)", HFILL }},
1557 { &hf_mscldap_netlogon_flags_good_timeserv,
1558 { "Good Time Serv", "mscldap.netlogon.flags.good_timeserv", FT_BOOLEAN, 32,
1559 TFS(&tfs_ads_good_timeserv), 0x00000200, "Is this a Good Time Server? (i.e. does it have a hardware clock)", HFILL }},
1561 { &hf_mscldap_netlogon_flags_ndnc,
1562 { "NDNC", "mscldap.netlogon.flags.ndnc", FT_BOOLEAN, 32,
1563 TFS(&tfs_ads_ndnc), 0x00000400, "Is this an NDNC dc?", HFILL }},
1566 { "GUID", "ldap.guid", FT_GUID, BASE_NONE,
1567 NULL, 0, "GUID", HFILL }},
1569 { &hf_ldap_AccessMask_ADS_CREATE_CHILD,
1570 { "Create Child", "ldap.AccessMask.ADS_CREATE_CHILD", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_CREATE_CHILD_tfs), LDAP_ACCESSMASK_ADS_CREATE_CHILD, "", HFILL }},
1572 { &hf_ldap_AccessMask_ADS_DELETE_CHILD,
1573 { "Delete Child", "ldap.AccessMask.ADS_DELETE_CHILD", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_DELETE_CHILD_tfs), LDAP_ACCESSMASK_ADS_DELETE_CHILD, "", HFILL }},
1575 { &hf_ldap_AccessMask_ADS_LIST,
1576 { "List", "ldap.AccessMask.ADS_LIST", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_LIST_tfs), LDAP_ACCESSMASK_ADS_LIST, "", HFILL }},
1578 { &hf_ldap_AccessMask_ADS_SELF_WRITE,
1579 { "Self Write", "ldap.AccessMask.ADS_SELF_WRITE", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_SELF_WRITE_tfs), LDAP_ACCESSMASK_ADS_SELF_WRITE, "", HFILL }},
1581 { &hf_ldap_AccessMask_ADS_READ_PROP,
1582 { "Read Prop", "ldap.AccessMask.ADS_READ_PROP", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_READ_PROP_tfs), LDAP_ACCESSMASK_ADS_READ_PROP, "", HFILL }},
1584 { &hf_ldap_AccessMask_ADS_WRITE_PROP,
1585 { "Write Prop", "ldap.AccessMask.ADS_WRITE_PROP", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_WRITE_PROP_tfs), LDAP_ACCESSMASK_ADS_WRITE_PROP, "", HFILL }},
1587 { &hf_ldap_AccessMask_ADS_DELETE_TREE,
1588 { "Delete Tree", "ldap.AccessMask.ADS_DELETE_TREE", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_DELETE_TREE_tfs), LDAP_ACCESSMASK_ADS_DELETE_TREE, "", HFILL }},
1590 { &hf_ldap_AccessMask_ADS_LIST_OBJECT,
1591 { "List Object", "ldap.AccessMask.ADS_LIST_OBJECT", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_LIST_OBJECT_tfs), LDAP_ACCESSMASK_ADS_LIST_OBJECT, "", HFILL }},
1593 { &hf_ldap_AccessMask_ADS_CONTROL_ACCESS,
1594 { "Control Access", "ldap.AccessMask.ADS_CONTROL_ACCESS", FT_BOOLEAN, 32, TFS(&ldap_AccessMask_ADS_CONTROL_ACCESS_tfs), LDAP_ACCESSMASK_ADS_CONTROL_ACCESS, "", HFILL }},
1596 #include "packet-ldap-hfarr.c"
1599 /* List of subtrees */
1600 static gint *ett[] = {
1603 &ett_ldap_sasl_blob,
1605 &ett_mscldap_netlogon_flags,
1607 #include "packet-ldap-ettarr.c"
1610 module_t *ldap_module;
1612 /* Register protocol */
1613 proto_ldap = proto_register_protocol(PNAME, PSNAME, PFNAME);
1614 /* Register fields and subtrees */
1615 proto_register_field_array(proto_ldap, hf, array_length(hf));
1616 proto_register_subtree_array(ett, array_length(ett));
1619 register_dissector("ldap", dissect_ldap_tcp, proto_ldap);
1621 ldap_module = prefs_register_protocol(proto_ldap, NULL);
1622 prefs_register_bool_preference(ldap_module, "desegment_ldap_messages",
1623 "Reassemble LDAP messages spanning multiple TCP segments",
1624 "Whether the LDAP dissector should reassemble messages spanning multiple TCP segments."
1625 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1628 prefs_register_uint_preference(ldap_module, "tcp.port", "LDAP TCP Port",
1629 "Set the port for LDAP operations",
1630 10, &ldap_tcp_port);
1632 prefs_register_obsolete_preference(ldap_module, "max_pdu");
1634 proto_cldap = proto_register_protocol(
1635 "Connectionless Lightweight Directory Access Protocol",
1638 register_init_routine(ldap_reinit);
1639 ldap_tap=register_tap("ldap");
1641 ldap_name_dissector_table = register_dissector_table("ldap.name", "LDAP Attribute Type Dissectors", FT_STRING, BASE_NONE);
1646 /*--- proto_reg_handoff_ldap ---------------------------------------*/
1648 proto_reg_handoff_ldap(void)
1650 dissector_handle_t ldap_handle, cldap_handle;
1651 ldap_handle = create_dissector_handle(dissect_ldap_tcp, proto_ldap);
1653 dissector_add("tcp.port", ldap_tcp_port, ldap_handle);
1654 dissector_add("tcp.port", TCP_PORT_GLOBALCAT_LDAP, ldap_handle);
1656 cldap_handle = create_dissector_handle(dissect_mscldap, proto_cldap);
1657 dissector_add("udp.port", UDP_PORT_CLDAP, cldap_handle);
1659 gssapi_handle = find_dissector("gssapi");
1660 gssapi_wrap_handle = find_dissector("gssapi_verf");
1662 ntlmssp_handle = find_dissector("ntlmssp");
1664 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dsml/dsml/ldap_controls_and_session_support.asp */
1665 add_oid_str_name("1.2.840.113556.1.4.319","LDAP_PAGED_RESULT_OID_STRING");
1666 add_oid_str_name("1.2.840.113556.1.4.417","LDAP_SERVER_SHOW_DELETED_OID");
1667 add_oid_str_name("1.2.840.113556.1.4.473","LDAP_SERVER_SORT_OID");
1668 add_oid_str_name("1.2.840.113556.1.4.474","LDAP_CONTROL_SORT_RESP_OID");
1669 add_oid_str_name("1.2.840.113556.1.4.521","LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID");
1670 add_oid_str_name("1.2.840.113556.1.4.528","LDAP_SERVER_NOTIFICATION_OID");
1671 add_oid_str_name("1.2.840.113556.1.4.529","LDAP_SERVER_EXTENDED_DN_OID");
1672 add_oid_str_name("1.2.840.113556.1.4.619","LDAP_SERVER_LAZY_COMMIT_OID");
1673 add_oid_str_name("1.2.840.113556.1.4.800","LDAP_CAP_ACTIVE_DIRECTORY_OID");
1674 add_oid_str_name("1.2.840.113556.1.4.801","LDAP_SERVER_SD_FLAGS_OID");
1675 add_oid_str_name("1.2.840.113556.1.4.804","LDAP_OID_COMPARATOR_OR");
1676 add_oid_str_name("1.2.840.113556.1.4.805","LDAP_SERVER_TREE_DELETE_OID");
1677 add_oid_str_name("1.2.840.113556.1.4.841","LDAP_SERVER_DIRSYNC_OID");
1678 add_oid_str_name("1.2.840.113556.1.4.970 ","None");
1679 add_oid_str_name("1.2.840.113556.1.4.1338","LDAP_SERVER_VERIFY_NAME_OID");
1680 add_oid_str_name("1.2.840.113556.1.4.1339","LDAP_SERVER_DOMAIN_SCOPE_OID");
1681 add_oid_str_name("1.2.840.113556.1.4.1340","LDAP_SERVER_SEARCH_OPTIONS_OID");
1682 add_oid_str_name("1.2.840.113556.1.4.1413","LDAP_SERVER_PERMISSIVE_MODIFY_OID");
1683 add_oid_str_name("1.2.840.113556.1.4.1504","LDAP_SERVER_ASQ_OID");
1684 add_oid_str_name("1.2.840.113556.1.4.1670","LDAP_CAP_ACTIVE_DIRECTORY_V51_OID");
1685 add_oid_str_name("1.2.840.113556.1.4.1781","LDAP_SERVER_FAST_BIND_OID");
1686 add_oid_str_name("1.2.840.113556.1.4.1791","LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID");
1687 add_oid_str_name("1.2.840.113556.1.4.1851","LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID");
1688 add_oid_str_name("1.3.6.1.4.1.1466.101.119.1","None");
1689 add_oid_str_name("1.3.6.1.4.1.1466.20037","LDAP_START_TLS_OID");
1690 add_oid_str_name("2.16.840.1.113730.3.4.9","LDAP_CONTROL_VLVREQUEST VLV");
1691 add_oid_str_name("2.16.840.1.113730.3.4.10","LDAP_CONTROL_VLVRESPONSE VLV");
1693 register_ldap_name_dissector("netlogon", dissect_NetLogon_PDU, proto_cldap);
1694 register_ldap_name_dissector("objectGUID", dissect_ldap_guid, proto_ldap);
1695 register_ldap_name_dissector("supportedControl", dissect_ldap_oid, proto_ldap);
1696 register_ldap_name_dissector("supportedCapabilities", dissect_ldap_oid, proto_ldap);
1697 register_ldap_name_dissector("objectSid", dissect_ldap_sid, proto_ldap);
1698 register_ldap_name_dissector("nTSecurityDescriptor", dissect_ldap_nt_sec_desc, proto_ldap);
1700 #include "packet-ldap-dis-tab.c"