Correctly parse the LDAP dereference control
authorAndrew Bartlett <abartlet@samba.org>
Fri, 12 Dec 2008 04:00:48 +0000 (15:00 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 12 Dec 2008 04:00:48 +0000 (15:00 +1100)
This is the final part needed for supporting extended DNs against OpenLDAP

Andrew Bartlett

source4/libcli/ldap/ldap.c
source4/libcli/ldap/ldap_controls.c

index 589b29f..7a65cc5 100644 (file)
@@ -894,7 +894,7 @@ failed:
        return NULL;    
 }
 
-
+/* Decode a single LDAP attribute, possibly containing multiple values */
 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
                               struct ldb_message_element *attrib)
 {
@@ -911,11 +911,11 @@ static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
        
 }
 
-void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
-                        struct ldb_message_element **attributes,
-                        int *num_attributes)
+/* Decode a set of LDAP attributes, as found in the dereference control */
+void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+                             struct ldb_message_element **attributes,
+                             int *num_attributes)
 {
-       asn1_start_tag(data, ASN1_SEQUENCE(0));
        while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
                struct ldb_message_element attrib;
                ZERO_STRUCT(attrib);
@@ -923,6 +923,16 @@ void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
                add_attrib_to_array_talloc(mem_ctx, &attrib,
                                           attributes, num_attributes);
        }
+}
+
+/* Decode a set of LDAP attributes, as found in a search entry */
+void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+                        struct ldb_message_element **attributes,
+                        int *num_attributes)
+{
+       asn1_start_tag(data, ASN1_SEQUENCE(0));
+       ldap_decode_attribs_bare(mem_ctx, data, 
+                                attributes, num_attributes);
        asn1_end_tag(data);
 }
 
index f4adc50..109837c 100644 (file)
@@ -1136,16 +1136,13 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
 {
        struct asn1_data *data = asn1_init(mem_ctx);
        struct dsdb_openldap_dereference_result_control *control;
-       struct dsdb_openldap_dereference_result **r;
+       struct dsdb_openldap_dereference_result **r = NULL;
        int i = 0;
        if (!data) return false;
 
        control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
        if (!control) return false;
 
-       r = control->attributes = talloc_array(control, struct dsdb_openldap_dereference_result *, 0);
-       if (!r) return false;
-               
        if (!asn1_load(data, in)) {
                return false;
        }
@@ -1160,10 +1157,14 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
        }
 
        while (asn1_tag_remaining(data) > 0) {                                  
-               i++;
-               r = talloc_realloc(r, control, struct dsdb_openldap_dereference_result *, i + 1);
-               
-               r[i] = talloc(r, struct dsdb_openldap_dereference_result);
+               r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
+               if (!r) {
+                       return false;
+               }
+               r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
+               if (!r[i]) {
+                       return false;
+               }
 
                if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
                        return false;
@@ -1171,19 +1172,30 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
                
                asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
                asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
-               ldap_decode_attribs(r[i], data, &r[i]->attributes,
-                                   &r[i]->num_attributes);
-               
+               if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
+                       if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
+                               return false;
+                       }
+                       
+                       ldap_decode_attribs_bare(r, data, &r[i]->attributes,
+                                                &r[i]->num_attributes);
+                       
+                       if (!asn1_end_tag(data)) {
+                               return false;
+                       }
+               }
                if (!asn1_end_tag(data)) {
                        return false;
                }
-               r[i+1] = NULL;
+               i++;
+               r[i] = NULL;
        }
 
        if (!asn1_end_tag(data)) {
                return false;
        }
 
+       control->attributes = r;
        *out = control;
 
        return true;