s4:dsdb: add support for DSDB_OPENLDAP_DEREFERENCE_CONTROL
authorAndrew Bartlett <abartlet@samba.org>
Tue, 16 Dec 2008 07:28:55 +0000 (08:28 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 17 Dec 2008 01:29:24 +0000 (12:29 +1100)
Encode and decode the OpenLDAP dereference control (draft-masarati-ldap-deref-00)

At this time, the ldb_controls infrustructure does not handle request
and reply controls having different formats, so this is purely the
client implementation (ie, there is no decode of the client->server
packet, and no encode of the server->client packet).

Signed-off-by: Stefan Metzmacher <metze@samba.org>
source4/dsdb/samdb/samdb.h
source4/libcli/ldap/ldap_controls.c

index 93068d66ef1dd4b47382c3445cd3bc54cef74c51..570221ee255df0d915992e397decb1f8cf7604cd 100644 (file)
@@ -100,4 +100,26 @@ struct dsdb_pdc_fsmo {
  */
 #define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
 
+#define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16"
+
+struct dsdb_openldap_dereference {
+       const char *source_attribute;
+       const char **dereference_attribute;
+};
+
+struct dsdb_openldap_dereference_control {
+       struct dsdb_openldap_dereference **dereference;
+};
+
+struct dsdb_openldap_dereference_result {
+       const char *source_attribute;
+       const char *dereferenced_dn;
+       int num_attributes;
+       struct ldb_message_element *attributes;
+};
+
+struct dsdb_openldap_dereference_result_control {
+       struct dsdb_openldap_dereference_result **attributes;
+};
+
 #endif /* __SAMDB_H__ */
index 930d97c40d0b2b3a0765c3a3fc27d5bfe596aeee..109837c2bf2f155e675fc6dbca9739cdd3bf401a 100644 (file)
@@ -24,6 +24,7 @@
 #include "libcli/ldap/ldap.h"
 #include "lib/ldb/include/ldb.h"
 #include "libcli/ldap/ldap_proto.h"
+#include "dsdb/samdb/samdb.h"
 
 struct control_handler {
        const char *oid;
@@ -1087,6 +1088,119 @@ static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
        return true;
 }
 
+static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
+{
+       struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
+       int i,j;
+       struct asn1_data *data = asn1_init(mem_ctx);
+
+       if (!data) return false;
+       
+       if (!control) return false;
+       
+       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+       
+       for (i=0; control->dereference && control->dereference[i]; i++) {
+               if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+                       return false;
+               }
+               if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
+                       return false;
+               }
+               if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+                       return false;
+               }
+               for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
+                       if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j], 
+                                                   strlen(control->dereference[i]->dereference_attribute[j]))) {
+                               return false;
+                       }
+               }
+               
+               asn1_pop_tag(data);
+               asn1_pop_tag(data);
+       }
+       asn1_pop_tag(data);
+
+       *out = data_blob_talloc(mem_ctx, data->data, data->length);
+       if (out->data == NULL) {
+               return false;
+       }
+       talloc_free(data);
+       return true;
+}
+
+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 = NULL;
+       int i = 0;
+       if (!data) return false;
+
+       control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
+       if (!control) return false;
+
+       if (!asn1_load(data, in)) {
+               return false;
+       }
+
+       control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
+       if (!control) {
+               return false;
+       }
+
+       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       while (asn1_tag_remaining(data) > 0) {                                  
+               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;
+               }
+               
+               asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
+               asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
+               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;
+               }
+               i++;
+               r[i] = NULL;
+       }
+
+       if (!asn1_end_tag(data)) {
+               return false;
+       }
+
+       control->attributes = r;
+       *out = control;
+
+       return true;
+}
+
 struct control_handler ldap_known_controls[] = {
        { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
        { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
@@ -1107,6 +1221,7 @@ struct control_handler ldap_known_controls[] = {
        { "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
 /* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
        { "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
+       { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
        { NULL, NULL, NULL }
 };