diff --git a/asn1/ldap/packet-ldap-template.c b/asn1/ldap/packet-ldap-template.c index ab6c2ee541..8cdfbfb225 100644 --- a/asn1/ldap/packet-ldap-template.c +++ b/asn1/ldap/packet-ldap-template.c @@ -489,27 +489,6 @@ dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo, if (rest_is_pad && length_remaining < 6) return; - /* - * The frame begins - * with a "Sequence Of" header. - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes - is the "Sequence Of" header split across segment - * boundaries? We require at least 6 bytes for the header - * which allows for a 4 byte length (ASN.1 BER). - */ - if (length_remaining < 6) { - /* stop if the caller says that we are given all data and the rest is padding - * this is for the SASL GSSAPI case when the data is only signed and not sealed - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = 6 - length_remaining; - return; - } - } - /* * OK, try to read the "Sequence Of" header; this gets the total * length of the LDAP message. @@ -544,29 +523,6 @@ dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo, msg_len = length_remaining; } - /* - * Is the message split across segment boundaries? - */ - if (length_remaining < msg_len) { - /* provide a hint to TCP where the next PDU starts */ - pinfo->want_pdu_tracking=2; - pinfo->bytes_until_next_pdu= msg_len - length_remaining; - /* - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes. Tell the TCP dissector where the data for this message - * starts in the data it handed us, and how many more bytes - * we need, and return. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = msg_len - length_remaining; - - return; - } - } - /* * Construct a tvbuff containing the amount of the payload we have * available. Make its reported length the amount of data in the @@ -674,27 +630,6 @@ dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean i */ length_remaining = tvb_ensure_length_remaining(tvb, offset); - /* - * Try to find out if we have a plain LDAP buffer - * with a "Sequence Of" header or a SASL buffer with - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes - is the "Sequence Of" header split across segment - * boundaries? We require at least 6 bytes for the header - * which allows for a 4 byte length (ASN.1 BER). - * For the SASL case we need at least 4 bytes, so this is - * no problem here because we check for 6 bytes ans sasl buffers - * with less than 2 bytes should not exist... - */ - if (length_remaining < 6) { - pinfo->desegment_offset = offset; - pinfo->desegment_len = 6 - length_remaining; - return; - } - } - /* It might still be a packet containing a SASL security layer * but its just that we never saw the BIND packet. * check if it looks like it could be a SASL blob here @@ -767,28 +702,6 @@ dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean i return; } - /* - * Is the buffer split across segment boundaries? - */ - if (length_remaining < sasl_msg_len) { - /* provide a hint to TCP where the next PDU starts */ - pinfo->want_pdu_tracking = 2; - pinfo->bytes_until_next_pdu= sasl_msg_len - length_remaining; - /* - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes. Tell the TCP dissector where the data for this message - * starts in the data it handed us, and how many more bytes we - * need, and return. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = sasl_msg_len - length_remaining; - return; - } - } - /* * Construct a tvbuff containing the amount of the payload we have * available. Make its reported length the amount of data in the PDU. @@ -1157,9 +1070,106 @@ static void dissect_NetLogon_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree * } +static guint +get_sasl_ldap_pdu_len(tvbuff_t *tvb, int offset) +{ + /* sasl encapsulated ldap is 4 bytes plus the length in size */ + return tvb_get_ntohl(tvb, offset)+4; +} + +static void +dissect_sasl_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; +} + +static guint +get_normal_ldap_pdu_len(tvbuff_t *tvb, int offset) +{ + guint32 len; + gboolean ind; + int data_offset; + + /* normal ldap is tag+len bytes plus the length + * offset==0 is where the tag is + * offset==1 is where length starts + */ + data_offset=get_ber_length(NULL, tvb, 1, &len, &ind); + return len+data_offset; +} + +static void +dissect_normal_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; +} + + static void dissect_ldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + /* Here we must take care of reassembly but this is tricky since + * depending on whether SASL is present or not, the heuristics + * will be very different. + */ + if(ldap_desegment && (tvb_length(tvb)==tvb_reported_length(tvb))){ + guint32 len; + + /* check for a SASL header, i.e. four byte integer where the + * first two bytes are 0x00 and the value is <64k and >2 + * (>2 to fight false positives, 0x00000000 is a common + * "random" tcp payload) + * (no SASL ldap PDUs are ever going to be >64k in size?) + * + * Following the SASL header is a GSSAPI blob so the next byte + * is always 0x60. (only true for MS SASL LDAP, there are other + * blobs that may follow in real-world) + */ + len=tvb_get_ntohl(tvb, 0); + if( (len<65535) + && (len>2) + && (tvb_get_guint8(tvb, 4)==0x60)){ + if(len<=tvb_length_remaining(tvb, 4)){ + /* we have a full ldap pdu */ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; + } else { + /* we have to do reassembly */ + tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_sasl_ldap_pdu_len, dissect_sasl_ldap_pdu); + return; + } + } + /* check if it is a normal BER encoded LDAP packet + * i.e. first byte is 0x30 followed by a length that is + * <64k + * (no ldap PDUs are ever >64kb? ) + */ + if(tvb_get_guint8(tvb, 0)==0x30){ + gboolean ind; + int data_offset; + + /* check that length makes sense */ + data_offset=get_ber_length(NULL, tvb, 1, &len, &ind); + + /* dont check ind since indefinite length is never used for ldap (famous last words)*/ + if(len<2 || len>65535){ + return; + } + + if(len<=tvb_length_remaining(tvb, data_offset)){ + /* we have a full ldap pdu */ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; + } else { + /* we have to do reassembly */ + tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_normal_ldap_pdu_len, dissect_normal_ldap_pdu); + return; + } + } + } + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); return; } diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c index c07fb54601..d4f4777358 100644 --- a/epan/dissectors/packet-ber.c +++ b/epan/dissectors/packet-ber.c @@ -106,7 +106,6 @@ static gint ett_ber_unknown = -1; static gint ett_ber_SEQUENCE = -1; static gboolean show_internal_ber_fields = FALSE; -static gboolean verify_ber_length_field = TRUE; proto_item *ber_last_created_item=NULL; @@ -530,16 +529,6 @@ get_ber_length(proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gbo } } - if(verify_ber_length_field){ - /* check that the length is sane */ - if(tmp_length>(guint32)tvb_reported_length_remaining(tvb,offset)){ - proto_tree_add_text(tree, tvb, old_offset, offset-old_offset, "BER: Error length:%u longer than tvb_reported_length_remaining:%d",tmp_length, tvb_reported_length_remaining(tvb, offset)); - /* force the appropriate exception */ - tvb_ensure_bytes_exist(tvb, offset, tmp_length); - /*tmp_length = (guint32)tvb_reported_length_remaining(tvb,offset);*/ - } - } - if (length) *length = tmp_length; if (ind) @@ -2398,10 +2387,6 @@ proto_register_ber(void) "Whether the dissector should also display internal" " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields); - prefs_register_bool_preference(ber_module, "verify_length", - "Verify length", - "Verify that the current packet contains (at least) the number of bytes indicated by the length field", &verify_ber_length_field); - ber_oid_dissector_table = register_dissector_table("ber.oid", "BER OID Dissectors", FT_STRING, BASE_NONE); } diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c index 5cecc00503..8304e86b17 100644 --- a/epan/dissectors/packet-ldap.c +++ b/epan/dissectors/packet-ldap.c @@ -2675,27 +2675,6 @@ dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo, if (rest_is_pad && length_remaining < 6) return; - /* - * The frame begins - * with a "Sequence Of" header. - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes - is the "Sequence Of" header split across segment - * boundaries? We require at least 6 bytes for the header - * which allows for a 4 byte length (ASN.1 BER). - */ - if (length_remaining < 6) { - /* stop if the caller says that we are given all data and the rest is padding - * this is for the SASL GSSAPI case when the data is only signed and not sealed - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = 6 - length_remaining; - return; - } - } - /* * OK, try to read the "Sequence Of" header; this gets the total * length of the LDAP message. @@ -2730,29 +2709,6 @@ dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo, msg_len = length_remaining; } - /* - * Is the message split across segment boundaries? - */ - if (length_remaining < msg_len) { - /* provide a hint to TCP where the next PDU starts */ - pinfo->want_pdu_tracking=2; - pinfo->bytes_until_next_pdu= msg_len - length_remaining; - /* - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes. Tell the TCP dissector where the data for this message - * starts in the data it handed us, and how many more bytes - * we need, and return. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = msg_len - length_remaining; - - return; - } - } - /* * Construct a tvbuff containing the amount of the payload we have * available. Make its reported length the amount of data in the @@ -2860,27 +2816,6 @@ dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean i */ length_remaining = tvb_ensure_length_remaining(tvb, offset); - /* - * Try to find out if we have a plain LDAP buffer - * with a "Sequence Of" header or a SASL buffer with - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes - is the "Sequence Of" header split across segment - * boundaries? We require at least 6 bytes for the header - * which allows for a 4 byte length (ASN.1 BER). - * For the SASL case we need at least 4 bytes, so this is - * no problem here because we check for 6 bytes ans sasl buffers - * with less than 2 bytes should not exist... - */ - if (length_remaining < 6) { - pinfo->desegment_offset = offset; - pinfo->desegment_len = 6 - length_remaining; - return; - } - } - /* It might still be a packet containing a SASL security layer * but its just that we never saw the BIND packet. * check if it looks like it could be a SASL blob here @@ -2953,28 +2888,6 @@ dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean i return; } - /* - * Is the buffer split across segment boundaries? - */ - if (length_remaining < sasl_msg_len) { - /* provide a hint to TCP where the next PDU starts */ - pinfo->want_pdu_tracking = 2; - pinfo->bytes_until_next_pdu= sasl_msg_len - length_remaining; - /* - * Can we do reassembly? - */ - if (ldap_desegment && pinfo->can_desegment) { - /* - * Yes. Tell the TCP dissector where the data for this message - * starts in the data it handed us, and how many more bytes we - * need, and return. - */ - pinfo->desegment_offset = offset; - pinfo->desegment_len = sasl_msg_len - length_remaining; - return; - } - } - /* * Construct a tvbuff containing the amount of the payload we have * available. Make its reported length the amount of data in the PDU. @@ -3343,9 +3256,106 @@ static void dissect_NetLogon_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree * } +static guint +get_sasl_ldap_pdu_len(tvbuff_t *tvb, int offset) +{ + /* sasl encapsulated ldap is 4 bytes plus the length in size */ + return tvb_get_ntohl(tvb, offset)+4; +} + +static void +dissect_sasl_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; +} + +static guint +get_normal_ldap_pdu_len(tvbuff_t *tvb, int offset) +{ + guint32 len; + gboolean ind; + int data_offset; + + /* normal ldap is tag+len bytes plus the length + * offset==0 is where the tag is + * offset==1 is where length starts + */ + data_offset=get_ber_length(NULL, tvb, 1, &len, &ind); + return len+data_offset; +} + +static void +dissect_normal_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; +} + + static void dissect_ldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + /* Here we must take care of reassembly but this is tricky since + * depending on whether SASL is present or not, the heuristics + * will be very different. + */ + if(ldap_desegment && (tvb_length(tvb)==tvb_reported_length(tvb))){ + guint32 len; + + /* check for a SASL header, i.e. four byte integer where the + * first two bytes are 0x00 and the value is <64k and >2 + * (>2 to fight false positives, 0x00000000 is a common + * "random" tcp payload) + * (no SASL ldap PDUs are ever going to be >64k in size?) + * + * Following the SASL header is a GSSAPI blob so the next byte + * is always 0x60. (only true for MS SASL LDAP, there are other + * blobs that may follow in real-world) + */ + len=tvb_get_ntohl(tvb, 0); + if( (len<65535) + && (len>2) + && (tvb_get_guint8(tvb, 4)==0x60)){ + if(len<=tvb_length_remaining(tvb, 4)){ + /* we have a full ldap pdu */ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; + } else { + /* we have to do reassembly */ + tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_sasl_ldap_pdu_len, dissect_sasl_ldap_pdu); + return; + } + } + /* check if it is a normal BER encoded LDAP packet + * i.e. first byte is 0x30 followed by a length that is + * <64k + * (no ldap PDUs are ever >64kb? ) + */ + if(tvb_get_guint8(tvb, 0)==0x30){ + gboolean ind; + int data_offset; + + /* check that length makes sense */ + data_offset=get_ber_length(NULL, tvb, 1, &len, &ind); + + /* dont check ind since indefinite length is never used for ldap (famous last words)*/ + if(len<2 || len>65535){ + return; + } + + if(len<=tvb_length_remaining(tvb, data_offset)){ + /* we have a full ldap pdu */ + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); + return; + } else { + /* we have to do reassembly */ + tcp_dissect_pdus(tvb, pinfo, tree, ldap_desegment, 4, get_normal_ldap_pdu_len, dissect_normal_ldap_pdu); + return; + } + } + } + dissect_ldap_pdu(tvb, pinfo, tree, FALSE); return; } @@ -3922,7 +3932,7 @@ void proto_register_ldap(void) { "ExtendedResponse/response", HFILL }}, /*--- End of included file: packet-ldap-hfarr.c ---*/ -#line 1347 "packet-ldap-template.c" +#line 1357 "packet-ldap-template.c" }; /* List of subtrees */ @@ -3975,7 +3985,7 @@ void proto_register_ldap(void) { &ett_ldap_ExtendedResponse, /*--- End of included file: packet-ldap-ettarr.c ---*/ -#line 1358 "packet-ldap-template.c" +#line 1368 "packet-ldap-template.c" }; module_t *ldap_module;