r5298: - got rid of pstring.h from includes.h. This at least makes it a bit
[kai/samba.git] / source / libcli / ldap / ldap.c
index 12842b4dc4d2fb991c0d9a1a57a4118d16b080a5..545759c494db5402ecb0744c9d8ab6d6b34d0fd2 100644 (file)
@@ -24,6 +24,9 @@
 */
 
 #include "includes.h"
+#include "system/iconv.h"
+#include "system/filesys.h"
+#include "asn_1.h"
 
 /****************************************************************************
  *
@@ -128,7 +131,7 @@ static struct ldap_parse_tree *ldap_parse_simple(TALLOC_CTX *mem_ctx,
        if (val && strchr("()&|", *val))
                return NULL;
        
-       ret = talloc(mem_ctx, sizeof(*ret));
+       ret = talloc(mem_ctx, struct ldap_parse_tree);
        if (!ret) {
                errno = ENOMEM;
                return NULL;
@@ -155,8 +158,7 @@ static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
 {
        struct ldap_parse_tree *ret, *next;
 
-       ret = talloc(mem_ctx, sizeof(*ret));
-
+       ret = talloc(mem_ctx, struct ldap_parse_tree);
        if (!ret) {
                errno = ENOMEM;
                return NULL;
@@ -164,7 +166,7 @@ static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
 
        ret->operation = op;
        ret->u.list.num_elements = 1;
-       ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
+       ret->u.list.elements = talloc(mem_ctx, struct ldap_parse_tree *);
        if (!ret->u.list.elements) {
                errno = ENOMEM;
                return NULL;
@@ -179,7 +181,7 @@ static struct ldap_parse_tree *ldap_parse_filterlist(TALLOC_CTX *mem_ctx,
 
        while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
                struct ldap_parse_tree **e;
-               e = talloc_realloc_p(ret,
+               e = talloc_realloc(ret,
                                     ret->u.list.elements,
                                     struct ldap_parse_tree *,
                                     ret->u.list.num_elements+1);
@@ -204,7 +206,7 @@ static struct ldap_parse_tree *ldap_parse_not(TALLOC_CTX *mem_ctx, const char *s
 {
        struct ldap_parse_tree *ret;
 
-       ret = talloc(mem_ctx, sizeof(*ret));
+       ret = talloc(mem_ctx, struct ldap_parse_tree);
        if (!ret) {
                errno = ENOMEM;
                return NULL;
@@ -300,7 +302,7 @@ static struct ldap_parse_tree *ldap_parse_tree(TALLOC_CTX *mem_ctx, const char *
        return ldap_parse_simple(mem_ctx, s);
 }
 
-static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
+static BOOL ldap_push_filter(struct asn1_data *data, struct ldap_parse_tree *tree)
 {
        switch (tree->operation) {
        case LDAP_OP_SIMPLE: {
@@ -351,26 +353,25 @@ static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
        return !data->has_error;
 }
 
-static void ldap_encode_response(enum ldap_request_tag tag,
-                                struct ldap_Result *result,
-                                ASN1_DATA *data)
+static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
 {
-       asn1_push_tag(data, ASN1_APPLICATION(tag));
        asn1_write_enumerated(data, result->resultcode);
        asn1_write_OctetString(data, result->dn,
                               (result->dn) ? strlen(result->dn) : 0);
        asn1_write_OctetString(data, result->errormessage,
                               (result->errormessage) ?
                               strlen(result->errormessage) : 0);
-       if (result->referral != NULL)
+       if (result->referral) {
+               asn1_push_tag(data, ASN1_CONTEXT(3));
                asn1_write_OctetString(data, result->referral,
                                       strlen(result->referral));
-       asn1_pop_tag(data);
+               asn1_pop_tag(data);
+       }
 }
 
 BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
 {
-       ASN1_DATA data;
+       struct asn1_data data;
        int i, j;
 
        ZERO_STRUCT(data);
@@ -380,7 +381,7 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        switch (msg->type) {
        case LDAP_TAG_BindRequest: {
                struct ldap_BindRequest *r = &msg->r.BindRequest;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_Integer(&data, r->version);
                asn1_write_OctetString(&data, r->dn,
                                       (r->dn != NULL) ? strlen(r->dn) : 0);
@@ -388,14 +389,14 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
                switch (r->mechanism) {
                case LDAP_AUTH_MECH_SIMPLE:
                        /* context, primitive */
-                       asn1_push_tag(&data, r->mechanism | 0x80);
+                       asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
                        asn1_write(&data, r->creds.password,
                                   strlen(r->creds.password));
                        asn1_pop_tag(&data);
                        break;
                case LDAP_AUTH_MECH_SASL:
                        /* context, constructed */
-                       asn1_push_tag(&data, r->mechanism | 0xa0);
+                       asn1_push_tag(&data, ASN1_CONTEXT(3));
                        asn1_write_OctetString(&data, r->creds.SASL.mechanism,
                                               strlen(r->creds.SASL.mechanism));
                        asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
@@ -412,7 +413,12 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_BindResponse: {
                struct ldap_BindResponse *r = &msg->r.BindResponse;
-               ldap_encode_response(msg->type, &r->response, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, &r->response);
+               if (r->SASL.secblob.length > 0) {
+                       asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
+               }
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_UnbindRequest: {
@@ -421,7 +427,7 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_SearchRequest: {
                struct ldap_SearchRequest *r = &msg->r.SearchRequest;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
                asn1_write_enumerated(&data, r->scope);
                asn1_write_enumerated(&data, r->deref);
@@ -443,7 +449,7 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
 
                        ldap_push_filter(&data, tree);
 
-                       talloc_destroy(mem_ctx);
+                       talloc_free(mem_ctx);
                }
 
                asn1_push_tag(&data, ASN1_SEQUENCE(0));
@@ -458,7 +464,7 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_SearchResultEntry: {
                struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->dn, strlen(r->dn));
                asn1_push_tag(&data, ASN1_SEQUENCE(0));
                for (i=0; i<r->num_attributes; i++) {
@@ -481,12 +487,14 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_SearchResultDone: {
                struct ldap_Result *r = &msg->r.SearchResultDone;
-               ldap_encode_response(msg->type, r, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_ModifyRequest: {
                struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->dn, strlen(r->dn));
                asn1_push_tag(&data, ASN1_SEQUENCE(0));
 
@@ -515,12 +523,14 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_ModifyResponse: {
                struct ldap_Result *r = &msg->r.ModifyResponse;
-               ldap_encode_response(msg->type, r, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_AddRequest: {
                struct ldap_AddRequest *r = &msg->r.AddRequest;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->dn, strlen(r->dn));
                asn1_push_tag(&data, ASN1_SEQUENCE(0));
 
@@ -544,26 +554,28 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_AddResponse: {
                struct ldap_Result *r = &msg->r.AddResponse;
-               ldap_encode_response(msg->type, r, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
-       case LDAP_TAG_DeleteRequest: {
-               struct ldap_DeleteRequest *r = &msg->r.DeleteRequest;
-               asn1_push_tag(&data,
-                             ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest));
+       case LDAP_TAG_DelRequest: {
+               struct ldap_DelRequest *r = &msg->r.DelRequest;
+               asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
                asn1_write(&data, r->dn, strlen(r->dn));
                asn1_pop_tag(&data);
                break;
        }
-       case LDAP_TAG_DeleteResponse: {
-               struct ldap_Result *r = &msg->r.DeleteResponse;
-               ldap_encode_response(msg->type, r, &data);
+       case LDAP_TAG_DelResponse: {
+               struct ldap_Result *r = &msg->r.DelResponse;
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_ModifyDNRequest: {
                struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
-               asn1_push_tag(&data,
-                             ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->dn, strlen(r->dn));
                asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
                asn1_write_BOOLEAN(&data, r->deleteolddn);
@@ -578,42 +590,48 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_ModifyDNResponse: {
                struct ldap_Result *r = &msg->r.ModifyDNResponse;
-               ldap_encode_response(msg->type, r, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_CompareRequest: {
                struct ldap_CompareRequest *r = &msg->r.CompareRequest;
-               asn1_push_tag(&data,
-                             ASN1_APPLICATION(LDAP_TAG_CompareRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_write_OctetString(&data, r->dn, strlen(r->dn));
                asn1_push_tag(&data, ASN1_SEQUENCE(0));
                asn1_write_OctetString(&data, r->attribute,
                                       strlen(r->attribute));
-               asn1_write_OctetString(&data, r->value,
-                                      strlen(r->value));
+               asn1_write_OctetString(&data, r->value.data,
+                                      r->value.length);
                asn1_pop_tag(&data);
                asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_CompareResponse: {
-/*             struct ldap_Result *r = &msg->r.CompareResponse; */
+               struct ldap_Result *r = &msg->r.ModifyDNResponse;
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, r);
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_AbandonRequest: {
                struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
-               asn1_push_tag(&data,
-                             ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
                asn1_write_implicit_Integer(&data, r->messageid);
                asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_SearchResultReference: {
-/*             struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
+               struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               asn1_write_OctetString(&data, r->referral, strlen(r->referral));
+               asn1_pop_tag(&data);
                break;
        }
        case LDAP_TAG_ExtendedRequest: {
                struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
-               asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
                asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
                asn1_write(&data, r->oid, strlen(r->oid));
                asn1_pop_tag(&data);
@@ -625,7 +643,9 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
        }
        case LDAP_TAG_ExtendedResponse: {
                struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
-               ldap_encode_response(msg->type, &r->response, &data);
+               asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+               ldap_encode_response(&data, &r->response);
+               asn1_pop_tag(&data);
                break;
        }
        default:
@@ -641,14 +661,14 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
                                      DATA_BLOB blob)
 {
-       char *result = talloc(mem_ctx, blob.length+1);
+       char *result = talloc_size(mem_ctx, blob.length+1);
        memcpy(result, blob.data, blob.length);
        result[blob.length] = '\0';
        return result;
 }
 
 static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
-                                        ASN1_DATA *data,
+                                        struct asn1_data *data,
                                         const char **result)
 {
        DATA_BLOB string;
@@ -660,11 +680,9 @@ static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
 }
 
 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
-                                ASN1_DATA *data,
-                                enum ldap_request_tag tag,
+                                struct asn1_data *data,
                                 struct ldap_Result *result)
 {
-       asn1_start_tag(data, ASN1_APPLICATION(tag));
        asn1_read_enumerated(data, &result->resultcode);
        asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
        asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
@@ -675,13 +693,12 @@ static void ldap_decode_response(TALLOC_CTX *mem_ctx,
        } else {
                result->referral = NULL;
        }
-       asn1_end_tag(data);
 }
 
-static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data,
                               char **filter)
 {
-       uint8 filter_tag, tag_desc;
+       uint8_t filter_tag, tag_desc;
 
        if (!asn1_peek_uint8(data, &filter_tag))
                return False;
@@ -783,7 +800,7 @@ static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
        return True;
 }
 
-static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
                               struct ldap_attribute *attrib)
 {
        asn1_start_tag(data, ASN1_SEQUENCE(0));
@@ -803,7 +820,7 @@ static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
        
 }
 
-static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
                                struct ldap_attribute **attributes,
                                int *num_attributes)
 {
@@ -818,9 +835,9 @@ static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
        asn1_end_tag(data);
 }
 
-BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
+BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
 {
-       uint8 tag;
+       uint8_t tag;
 
        asn1_start_tag(data, ASN1_SEQUENCE(0));
        asn1_read_Integer(data, &msg->messageid);
@@ -833,22 +850,31 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
                struct ldap_BindRequest *r = &msg->r.BindRequest;
                msg->type = LDAP_TAG_BindRequest;
-               asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
+               asn1_start_tag(data, tag);
                asn1_read_Integer(data, &r->version);
                asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
-               if (asn1_peek_tag(data, 0x80)) {
+               if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
                        int pwlen;
                        r->creds.password = "";
-                       /* Mechanism 0 (SIMPLE) */
-                       asn1_start_tag(data, 0x80);
+                       r->mechanism = LDAP_AUTH_MECH_SIMPLE;
+                       asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
                        pwlen = asn1_tag_remaining(data);
                        if (pwlen != 0) {
-                               char *pw = talloc(msg->mem_ctx, pwlen+1);
+                               char *pw = talloc_size(msg->mem_ctx, pwlen+1);
                                asn1_read(data, pw, pwlen);
                                pw[pwlen] = '\0';
                                r->creds.password = pw;
                        }
                        asn1_end_tag(data);
+               } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
+                       asn1_start_tag(data, ASN1_CONTEXT(3));
+                       r->mechanism = LDAP_AUTH_MECH_SASL;
+                       asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
+                       asn1_read_OctetString(data, &r->creds.SASL.secblob);
+                       if (r->creds.SASL.secblob.data) {
+                               talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
+                       }
+                       asn1_end_tag(data);
                }
                asn1_end_tag(data);
                break;
@@ -857,17 +883,8 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
                struct ldap_BindResponse *r = &msg->r.BindResponse;
                msg->type = LDAP_TAG_BindResponse;
-               asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindResponse));
-               asn1_read_enumerated(data, &r->response.resultcode);
-               asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.dn);
-               asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.errormessage);
-               if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
-                       asn1_start_tag(data, ASN1_CONTEXT(3));
-                       asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.referral);
-                       asn1_end_tag(data);
-               } else {
-                       r->response.referral = NULL;
-               }
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, &r->response);
                if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
                        DATA_BLOB tmp_blob = data_blob(NULL, 0);
                        asn1_read_ContextSimple(data, 7, &tmp_blob);
@@ -882,7 +899,7 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
 
        case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
                msg->type = LDAP_TAG_UnbindRequest;
-               asn1_start_tag(data, ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest));
+               asn1_start_tag(data, tag);
                asn1_end_tag(data);
                break;
        }
@@ -890,7 +907,7 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
                struct ldap_SearchRequest *r = &msg->r.SearchRequest;
                msg->type = LDAP_TAG_SearchRequest;
-               asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
+               asn1_start_tag(data, tag);
                asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
                asn1_read_enumerated(data, (int *)&(r->scope));
                asn1_read_enumerated(data, (int *)&(r->deref));
@@ -928,8 +945,7 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
                msg->type = LDAP_TAG_SearchResultEntry;
                r->attributes = NULL;
                r->num_attributes = 0;
-               asn1_start_tag(data,
-                              ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
+               asn1_start_tag(data, tag);
                asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
                ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
                                    &r->num_attributes);
@@ -940,14 +956,18 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
                struct ldap_Result *r = &msg->r.SearchResultDone;
                msg->type = LDAP_TAG_SearchResultDone;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_SearchResultDone, r);
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
        case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
-/*             struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
+               struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
                msg->type = LDAP_TAG_SearchResultReference;
+               asn1_start_tag(data, tag);
+               asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->referral);
+               asn1_end_tag(data);
                break;
        }
 
@@ -963,9 +983,11 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
 
                while (asn1_tag_remaining(data) > 0) {
                        struct ldap_mod mod;
+                       int v;
                        ZERO_STRUCT(mod);
                        asn1_start_tag(data, ASN1_SEQUENCE(0));
-                       asn1_read_enumerated(data, &mod.type);
+                       asn1_read_enumerated(data, &v);
+                       mod.type = v;
                        ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
                        asn1_end_tag(data);
                        if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
@@ -981,15 +1003,16 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
                struct ldap_Result *r = &msg->r.ModifyResponse;
                msg->type = LDAP_TAG_ModifyResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_ModifyResponse, r);
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
        case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
                struct ldap_AddRequest *r = &msg->r.AddRequest;
                msg->type = LDAP_TAG_AddRequest;
-               asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
+               asn1_start_tag(data, tag);
                asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
 
                r->attributes = NULL;
@@ -1004,20 +1027,21 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
                struct ldap_Result *r = &msg->r.AddResponse;
                msg->type = LDAP_TAG_AddResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_AddResponse, r);
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
-       case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest): {
-               struct ldap_DeleteRequest *r = &msg->r.DeleteRequest;
+       case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
+               struct ldap_DelRequest *r = &msg->r.DelRequest;
                int len;
                char *dn;
-               msg->type = LDAP_TAG_DeleteRequest;
+               msg->type = LDAP_TAG_DelRequest;
                asn1_start_tag(data,
-                              ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest));
+                              ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
                len = asn1_tag_remaining(data);
-               dn = talloc(msg->mem_ctx, len+1);
+               dn = talloc_size(msg->mem_ctx, len+1);
                if (dn == NULL)
                        break;
                asn1_read(data, dn, len);
@@ -1027,11 +1051,12 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
                break;
        }
 
-       case ASN1_APPLICATION(LDAP_TAG_DeleteResponse): {
-               struct ldap_Result *r = &msg->r.DeleteResponse;
-               msg->type = LDAP_TAG_DeleteResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_DeleteResponse, r);
+       case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
+               struct ldap_Result *r = &msg->r.DelResponse;
+               msg->type = LDAP_TAG_DelResponse;
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
@@ -1049,7 +1074,7 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
                        char *newsup;
                        asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
                        len = asn1_tag_remaining(data);
-                       newsup = talloc(msg->mem_ctx, len+1);
+                       newsup = talloc_size(msg->mem_ctx, len+1);
                        if (newsup == NULL)
                                break;
                        asn1_read(data, newsup, len);
@@ -1064,28 +1089,44 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
                struct ldap_Result *r = &msg->r.ModifyDNResponse;
                msg->type = LDAP_TAG_ModifyDNResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_ModifyDNResponse, r);
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
        case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
-/*             struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
+               struct ldap_CompareRequest *r = &msg->r.CompareRequest;
                msg->type = LDAP_TAG_CompareRequest;
+               asn1_start_tag(data,
+                              ASN1_APPLICATION(LDAP_TAG_CompareRequest));
+               asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
+               asn1_start_tag(data, ASN1_SEQUENCE(0));
+               asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
+               asn1_read_OctetString(data, &r->value);
+               if (r->value.data) {
+                       talloc_steal(msg->mem_ctx, r->value.data);
+               }
+               asn1_end_tag(data);
+               asn1_end_tag(data);
                break;
        }
 
        case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
                struct ldap_Result *r = &msg->r.CompareResponse;
                msg->type = LDAP_TAG_CompareResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_CompareResponse, r);
+               asn1_start_tag(data, tag);
+               ldap_decode_response(msg->mem_ctx, data, r);
+               asn1_end_tag(data);
                break;
        }
 
-       case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
-/*             struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
+       case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
+               struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
                msg->type = LDAP_TAG_AbandonRequest;
+               asn1_start_tag(data, tag);
+               asn1_read_implicit_Integer(data, &r->messageid);
+               asn1_end_tag(data);
                break;
        }
 
@@ -1094,7 +1135,7 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
                DATA_BLOB tmp_blob = data_blob(NULL, 0);
 
                msg->type = LDAP_TAG_ExtendedRequest;
-               asn1_start_tag(data,ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
+               asn1_start_tag(data,tag);
                if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
                        return False;
                }
@@ -1119,31 +1160,74 @@ BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
        case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
                struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
                msg->type = LDAP_TAG_ExtendedResponse;
-               ldap_decode_response(msg->mem_ctx, data,
-                                    LDAP_TAG_ExtendedResponse, &r->response);
+               asn1_start_tag(data, tag);              
+               ldap_decode_response(msg->mem_ctx, data, &r->response);
                /* I have to come across an operation that actually sends
                 * something back to really see what's going on. The currently
                 * needed pwdchange does not send anything back. */
                r->name = NULL;
                r->value.data = NULL;
                r->value.length = 0;
+               asn1_end_tag(data);
                break;
        }
        default: 
                return False;
        }
 
+       msg->num_controls = 0;
+       msg->controls = NULL;
+
+       if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
+               int i;
+               struct ldap_Control *ctrl = NULL;
+
+               asn1_start_tag(data, ASN1_CONTEXT(0));
+
+               for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
+                       asn1_start_tag(data, ASN1_SEQUENCE(0));
+
+                       ctrl = talloc_realloc(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
+                       if (!ctrl) {
+                               return False;
+                       }
+                       ctrl[i].oid = NULL;
+                       ctrl[i].critical = False;
+                       ctrl[i].value = data_blob(NULL, 0);
+
+                       asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
+
+                       if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
+                               asn1_read_BOOLEAN(data, &ctrl[i].critical);
+                       }
+
+                       if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
+                               asn1_read_OctetString(data, &ctrl[i].value);
+                               if (ctrl[i].value.data) {
+                                       talloc_steal(msg->mem_ctx, ctrl[i].value.data);
+                               }
+                       }
+
+                       asn1_end_tag(data);
+               }
+               msg->num_controls = i;
+               msg->controls = ctrl;
+
+               asn1_end_tag(data);
+       }
+
        asn1_end_tag(data);
        return ((!data->has_error) && (data->nesting == NULL));
 }
 
 BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
-                         char **host, uint16 *port, BOOL *ldaps)
+                         char **host, uint16_t *port, BOOL *ldaps)
 {
        int tmp_port = 0;
-       fstring protocol;
-       fstring tmp_host;
+       char protocol[11];
+       char tmp_host[255];
        const char *p = url;
+       int ret;
 
        /* skip leading "URL:" (if any) */
        if (strncasecmp( p, "URL:", 4) == 0) {
@@ -1153,7 +1237,10 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
        /* Paranoia check */
        SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
                
-       sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
+       ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
+       if (ret < 2) {
+               return False;
+       }
 
        if (strequal(protocol, "ldap")) {
                *port = 389;
@@ -1168,651 +1255,8 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
 
        if (tmp_port != 0)
                *port = tmp_port;
-       
+
        *host = talloc_strdup(mem_ctx, tmp_host);
 
        return (*host != NULL);
 }
-
-struct ldap_connection *new_ldap_connection(void)
-{
-       TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
-       struct ldap_connection *result;
-
-       if (mem_ctx == NULL)
-               return NULL;
-
-       result = talloc(mem_ctx, sizeof(*result));
-
-       if (result == NULL)
-               return NULL;
-
-       result->mem_ctx = mem_ctx;
-       result->next_msgid = 1;
-       result->outstanding = NULL;
-       result->searchid = 0;
-       result->search_entries = NULL;
-       result->auth_dn = NULL;
-       result->simple_pw = NULL;
-       result->gensec = NULL;
-
-       return result;
-}
-
-BOOL ldap_connect(struct ldap_connection *conn, const char *url)
-{
-       struct hostent *hp;
-       struct in_addr ip;
-
-       if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
-                                 &conn->port, &conn->ldaps))
-               return False;
-
-       hp = sys_gethostbyname(conn->host);
-
-       if ((hp == NULL) || (hp->h_addr == NULL))
-               return False;
-
-       putip((char *)&ip, (char *)hp->h_addr);
-
-       conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
-
-       return (conn->sock >= 0);
-}
-
-BOOL ldap_set_simple_creds(struct ldap_connection *conn,
-                          const char *dn, const char *password)
-{
-       conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
-       conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
-
-       return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
-}
-
-struct ldap_message *new_ldap_message(void)
-{
-       TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
-       struct ldap_message *result;
-
-       if (mem_ctx == NULL)
-               return NULL;
-
-       result = talloc(mem_ctx, sizeof(*result));
-
-       if (result == NULL)
-               return NULL;
-
-       result->mem_ctx = mem_ctx;
-       return result;
-}
-
-void destroy_ldap_message(struct ldap_message *msg)
-{
-       if (msg != NULL)
-               talloc_destroy(msg->mem_ctx);
-}
-
-BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
-                  const struct timeval *endtime)
-{
-       DATA_BLOB request;
-       BOOL result;
-       struct ldap_queue_entry *entry;
-
-       msg->messageid = conn->next_msgid++;
-
-       if (!ldap_encode(msg, &request))
-               return False;
-
-       result = (write_data_until(conn->sock, request.data, request.length,
-                                  endtime) == request.length);
-
-       data_blob_free(&request);
-
-       if (!result)
-               return result;
-
-       /* abandon and unbind don't expect results */
-
-       if ((msg->type == LDAP_TAG_AbandonRequest) ||
-           (msg->type == LDAP_TAG_UnbindRequest))
-               return True;
-
-       entry = malloc(sizeof(*entry)); 
-
-       if (entry == NULL)
-               return False;
-
-       entry->msgid = msg->messageid;
-       entry->msg = NULL;
-       DLIST_ADD(conn->outstanding, entry);
-
-       return True;
-}
-
-BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
-                     const struct timeval *endtime)
-{
-        struct asn1_data data;
-        BOOL result;
-
-        if (!asn1_read_sequence_until(conn->sock, &data, endtime))
-                return False;
-
-        result = ldap_decode(&data, msg);
-
-        asn1_free(&data);
-        return result;
-}
-
-static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
-                                           int msgid)
-{
-       struct ldap_queue_entry *e;
-
-       for (e = conn->outstanding; e != NULL; e = e->next) {
-
-               if (e->msgid == msgid) {
-                       struct ldap_message *result = e->msg;
-                       DLIST_REMOVE(conn->outstanding, e);
-                       SAFE_FREE(e);
-                       return result;
-               }
-       }
-
-       return NULL;
-}
-
-static void add_search_entry(struct ldap_connection *conn,
-                            struct ldap_message *msg)
-{
-       struct ldap_queue_entry *e = malloc(sizeof *e);
-
-       if (e == NULL)
-               return;
-
-       e->msg = msg;
-       DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
-       return;
-}
-
-static void fill_outstanding_request(struct ldap_connection *conn,
-                                    struct ldap_message *msg)
-{
-       struct ldap_queue_entry *e;
-
-       for (e = conn->outstanding; e != NULL; e = e->next) {
-               if (e->msgid == msg->messageid) {
-                       e->msg = msg;
-                       return;
-               }
-       }
-
-       /* This reply has not been expected, destroy the incoming msg */
-       destroy_ldap_message(msg);
-       return;
-}
-
-struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
-                                 const struct timeval *endtime)
-{
-       struct ldap_message *result = recv_from_queue(conn, msgid);
-
-       if (result != NULL)
-               return result;
-
-       while (True) {
-               struct asn1_data data;
-               BOOL res;
-
-               result = new_ldap_message();
-
-               if (!asn1_read_sequence_until(conn->sock, &data, endtime))
-                       return NULL;
-
-               res = ldap_decode(&data, result);
-               asn1_free(&data);
-
-               if (!res)
-                       return NULL;
-
-               if (result->messageid == msgid)
-                       return result;
-
-               if (result->type == LDAP_TAG_SearchResultEntry) {
-                       add_search_entry(conn, result);
-               } else {
-                       fill_outstanding_request(conn, result);
-               }
-       }
-
-       return NULL;
-}
-
-struct ldap_message *ldap_transaction(struct ldap_connection *conn,
-                                     struct ldap_message *request)
-{
-       if (!ldap_send_msg(conn, request, NULL))
-               return False;
-
-       return ldap_receive(conn, request->messageid, NULL);
-}
-
-int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
-{
-       struct ldap_message *response;
-       struct ldap_message *msg;
-       const char *dn, *pw;
-       int result = LDAP_OTHER;
-
-       if (conn == NULL)
-               return result;
-
-       if (userdn) {
-               dn = userdn;
-       } else {
-               if (conn->auth_dn) {
-                       dn = conn->auth_dn;
-               } else {
-                       dn = "";
-               }
-       }
-
-       if (password) {
-               pw = password;
-       } else {
-               if (conn->simple_pw) {
-                       pw = conn->simple_pw;
-               } else {
-                       pw = "";
-               }
-       }
-
-       msg =  new_ldap_simple_bind_msg(dn, pw);
-       if (!msg)
-               return result;
-
-       response = ldap_transaction(conn, msg);
-       if (!response) {
-               destroy_ldap_message(msg);
-               return result;
-       }
-               
-       result = response->r.BindResponse.response.resultcode;
-
-       destroy_ldap_message(msg);
-       destroy_ldap_message(response);
-
-       return result;
-}
-
-int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
-{
-       NTSTATUS status;
-       TALLOC_CTX *mem_ctx = NULL;
-       struct ldap_message *response;
-       struct ldap_message *msg;
-       DATA_BLOB input = data_blob(NULL, 0);
-       DATA_BLOB output = data_blob(NULL, 0);
-       int result = LDAP_OTHER;
-
-       if (conn == NULL)
-               return result;
-
-       status = gensec_client_start(conn, &conn->gensec);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
-               return result;
-       }
-
-       status = gensec_set_domain(conn->gensec, domain);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", 
-                         domain, nt_errstr(status)));
-               goto done;
-       }
-
-       status = gensec_set_username(conn->gensec, username);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", 
-                         username, nt_errstr(status)));
-               goto done;
-       }
-
-       status = gensec_set_password(conn->gensec, password);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start set GENSEC client password: %s\n", 
-                         nt_errstr(status)));
-               goto done;
-       }
-
-       status = gensec_set_target_hostname(conn->gensec, conn->host);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
-                         nt_errstr(status)));
-               goto done;
-       }
-
-       status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
-                         nt_errstr(status)));
-               goto done;
-       }
-
-       mem_ctx = talloc_init("ldap_bind_sasl");
-       if (!mem_ctx)
-               goto done;
-
-       status = gensec_update(conn->gensec, mem_ctx,
-                              input,
-                              &output);
-
-       while(1) {
-               if (NT_STATUS_IS_OK(status) && output.length == 0) {
-                       break;
-               }
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
-                       break;
-               }
-
-               msg =  new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
-               if (!msg)
-                       goto done;
-
-               response = ldap_transaction(conn, msg);
-               destroy_ldap_message(msg);
-
-               if (!response) {
-                       goto done;
-               }
-
-               result = response->r.BindResponse.response.resultcode;
-
-               if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
-                       break;
-               }
-
-               status = gensec_update(conn->gensec, mem_ctx,
-                                      response->r.BindResponse.SASL.secblob,
-                                      &output);
-
-               destroy_ldap_message(response);
-       }
-
-done:
-       if (conn->gensec)
-               gensec_end(&conn->gensec);
-       if (mem_ctx)
-               talloc_destroy(mem_ctx);
-
-       return result;
-}
-
-BOOL ldap_setup_connection(struct ldap_connection *conn,
-                          const char *url, const char *userdn, const char *password)
-{
-       int result;
-
-       if (!ldap_connect(conn, url)) {
-               return False;
-       }
-
-       result = ldap_bind_simple(conn, userdn, password);
-       if (result == LDAP_SUCCESS) {
-               return True;
-       }
-
-       return False;
-}
-
-BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
-{
-       int result;
-
-       if (!ldap_connect(conn, url)) {
-               return False;
-       }
-
-       result = ldap_bind_sasl(conn, username, domain, password);
-       if (result == LDAP_SUCCESS) {
-               return True;
-       }
-
-       return False;
-}
-
-static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
-                                const struct timeval *endtime)
-{
-       struct ldap_message *msg = new_ldap_message();
-       BOOL result;
-
-       if (msg == NULL)
-               return False;
-
-       msg->type = LDAP_TAG_AbandonRequest;
-       msg->r.AbandonRequest.messageid = msgid;
-
-       result = ldap_send_msg(conn, msg, endtime);
-       destroy_ldap_message(msg);
-       return result;
-}
-
-struct ldap_message *new_ldap_search_message(const char *base,
-                                            enum ldap_scope scope,
-                                            char *filter,
-                                            int num_attributes,
-                                            const char **attributes)
-{
-       struct ldap_message *res = new_ldap_message();
-
-       if (res == NULL)
-               return NULL;
-
-       res->type = LDAP_TAG_SearchRequest;
-       res->r.SearchRequest.basedn = base;
-       res->r.SearchRequest.scope = scope;
-       res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
-       res->r.SearchRequest.timelimit = 0;
-       res->r.SearchRequest.sizelimit = 0;
-       res->r.SearchRequest.attributesonly = False;
-       res->r.SearchRequest.filter = filter;
-       res->r.SearchRequest.num_attributes = num_attributes;
-       res->r.SearchRequest.attributes = attributes;
-       return res;
-}
-
-struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
-{
-       struct ldap_message *res = new_ldap_message();
-
-       if (res == NULL)
-               return NULL;
-
-       res->type = LDAP_TAG_BindRequest;
-       res->r.BindRequest.version = 3;
-       res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
-       res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
-       res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
-       return res;
-}
-
-struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
-{
-       struct ldap_message *res = new_ldap_message();
-
-       if (res == NULL)
-               return NULL;
-
-       res->type = LDAP_TAG_BindRequest;
-       res->r.BindRequest.version = 3;
-       res->r.BindRequest.dn = "";
-       res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
-       res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
-       res->r.BindRequest.creds.SASL.secblob = *secblob;
-       return res;
-}
-
-BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
-                      const struct timeval *endtime)
-{
-       if ((conn->searchid != 0) &&
-           (!ldap_abandon_message(conn, conn->searchid, endtime)))
-               return False;
-
-       conn->searchid = conn->next_msgid;
-       return ldap_send_msg(conn, msg, endtime);
-}
-
-struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
-                                      const struct timeval *endtime)
-{
-       struct ldap_message *result;
-
-       if (conn->search_entries != NULL) {
-               struct ldap_queue_entry *e = conn->search_entries;
-
-               result = e->msg;
-               DLIST_REMOVE(conn->search_entries, e);
-               SAFE_FREE(e);
-               return result;
-       }
-
-       result = ldap_receive(conn, conn->searchid, endtime);
-
-       if (result->type == LDAP_TAG_SearchResultEntry)
-               return result;
-
-       if (result->type == LDAP_TAG_SearchResultDone) {
-               /* TODO: Handle Paged Results */
-               destroy_ldap_message(result);
-               return NULL;
-       }
-
-       /* TODO: Handle Search References here */
-       return NULL;
-}
-
-void ldap_endsearchent(struct ldap_connection *conn,
-                      const struct timeval *endtime)
-{
-       struct ldap_queue_entry *e;
-
-       e = conn->search_entries;
-
-       while (e != NULL) {
-               struct ldap_queue_entry *next = e->next;
-               DLIST_REMOVE(conn->search_entries, e);
-               SAFE_FREE(e);
-               e = next;
-       }
-}
-
-struct ldap_message *ldap_searchone(struct ldap_connection *conn,
-                                   struct ldap_message *msg,
-                                   const struct timeval *endtime)
-{
-       struct ldap_message *res1, *res2 = NULL;
-       if (!ldap_setsearchent(conn, msg, endtime))
-               return NULL;
-
-       res1 = ldap_getsearchent(conn, endtime);
-
-       if (res1 != NULL)
-               res2 = ldap_getsearchent(conn, endtime);
-
-       ldap_endsearchent(conn, endtime);
-
-       if (res1 == NULL)
-               return NULL;
-
-       if (res2 != NULL) {
-               /* More than one entry */
-               destroy_ldap_message(res1);
-               destroy_ldap_message(res2);
-               return NULL;
-       }
-
-       return res1;
-}
-
-BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
-                           DATA_BLOB *value)
-{
-       int i;
-       struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
-
-       if (msg->type != LDAP_TAG_SearchResultEntry)
-               return False;
-
-       for (i=0; i<r->num_attributes; i++) {
-               if (strequal(attr, r->attributes[i].name)) {
-                       if (r->attributes[i].num_values != 1)
-                               return False;
-
-                       *value = r->attributes[i].values[0];
-                       return True;
-               }
-       }
-       return False;
-}
-
-BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
-                            TALLOC_CTX *mem_ctx, char **value)
-{
-       DATA_BLOB blob;
-
-       if (!ldap_find_single_value(msg, attr, &blob))
-               return False;
-
-       *value = talloc(mem_ctx, blob.length+1);
-
-       if (*value == NULL)
-               return False;
-
-       memcpy(*value, blob.data, blob.length);
-       (*value)[blob.length] = '\0';
-       return True;
-}
-
-BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
-                         int *value)
-{
-       DATA_BLOB blob;
-       char *val;
-       int errno_save;
-       BOOL res;
-
-       if (!ldap_find_single_value(msg, attr, &blob))
-               return False;
-
-       val = malloc(blob.length+1);
-       if (val == NULL)
-               return False;
-
-       memcpy(val, blob.data, blob.length);
-       val[blob.length] = '\0';
-
-       errno_save = errno;
-       errno = 0;
-
-       *value = strtol(val, NULL, 10);
-
-       res = (errno == 0);
-
-       free(val);
-       errno = errno_save;
-
-       return res;
-}
-
-int ldap_error(struct ldap_connection *conn)
-{
-       return 0;
-}
-
-NTSTATUS ldap2nterror(int ldaperror)
-{
-       return NT_STATUS_OK;
-}