aboutsummaryrefslogtreecommitdiffstats
path: root/asn1/ldap/packet-ldap-template.c
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-06-14 11:51:25 +0000
committerRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-06-14 11:51:25 +0000
commit2f95f76a1ed4126ed982f2778fcd13e8df455b97 (patch)
tree610f59b2737b3e5cce77068e4ebb1fbd5bc1f3f5 /asn1/ldap/packet-ldap-template.c
parent59c8c8065d02c1612c274deb94ba426aaaa02a80 (diff)
fix tcp reassembly to work again for
ldap and ldap+sasl remove a recent ber length validation in packet-ber.c that cant work and breaks reassembly and also makes all ber pacvket sspanning multiple segments show up as malformed packets. svn path=/trunk/; revision=18465
Diffstat (limited to 'asn1/ldap/packet-ldap-template.c')
-rw-r--r--asn1/ldap/packet-ldap-template.c184
1 files changed, 97 insertions, 87 deletions
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
@@ -490,27 +490,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.
*/
@@ -545,29 +524,6 @@ dissect_ldap_payload(tvbuff_t *tvb, packet_info *pinfo,
}
/*
- * 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
* LDAP message.
@@ -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
@@ -768,28 +703,6 @@ dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean i
}
/*
- * 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;
}