libcli/ldap: move generic ldap control encoding code to ldap_message.c
authorStefan Metzmacher <metze@samba.org>
Tue, 24 Feb 2009 15:49:26 +0000 (16:49 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 24 Feb 2009 16:55:41 +0000 (17:55 +0100)
As they can we static there, we pass the specific handlers as parameter
where we need to support controls.

metze

libcli/ldap/ldap_message.c
libcli/ldap/ldap_message.h
source4/ldap_server/ldap_server.c
source4/libcli/cldap/cldap.c
source4/libcli/ldap/ldap_client.c
source4/libcli/ldap/ldap_controls.c

index 06052a936a31d75dee5863bbda082201c090735e..9b00d0188d1ca0cb92071e0b2d1f8bcac2b79899 100644 (file)
@@ -84,6 +84,138 @@ static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
        return true;
 }
 
+static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
+                                     const struct ldap_control_handler *handlers,
+                                     struct ldb_control *ctrl)
+{
+       int i;
+
+       if (!handlers) {
+               return true;
+       }
+
+       for (i = 0; handlers[i].oid != NULL; i++) {
+               if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
+                       if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
+                               return false;
+                       }
+                       break;
+               }
+       }
+       if (handlers[i].oid == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
+                                       struct ldb_control *ctrl, DATA_BLOB *value)
+{
+       DATA_BLOB oid;
+
+       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
+               return false;
+       }
+       ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
+       if (!ctrl->oid) {
+               return false;
+       }
+
+       if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
+               bool critical;
+               if (!asn1_read_BOOLEAN(data, &critical)) {
+                       return false;
+               }
+               ctrl->critical = critical;
+       } else {
+               ctrl->critical = false;
+       }
+
+       ctrl->data = NULL;
+
+       if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
+               *value = data_blob(NULL, 0);
+               goto end_tag;
+       }
+
+       if (!asn1_read_OctetString(data, mem_ctx, value)) {
+               return false;
+       }
+
+end_tag:
+       if (!asn1_end_tag(data)) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
+                               const struct ldap_control_handler *handlers,
+                               struct ldb_control *ctrl)
+{
+       DATA_BLOB value;
+       int i;
+
+       if (!handlers) {
+               return false;
+       }
+
+       for (i = 0; handlers[i].oid != NULL; i++) {
+               if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
+                       if (!handlers[i].encode) {
+                               if (ctrl->critical) {
+                                       return false;
+                               } else {
+                                       /* not encoding this control */
+                                       return true;
+                               }
+                       }
+                       if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
+                               return false;
+                       }
+                       break;
+               }
+       }
+       if (handlers[i].oid == NULL) {
+               return false;
+       }
+
+       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
+               return false;
+       }
+
+       if (ctrl->critical) {
+               if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
+                       return false;
+               }
+       }
+
+       if (!ctrl->data) {
+               goto pop_tag;
+       }
+
+       if (!asn1_write_OctetString(data, value.data, value.length)) {
+               return false;
+       }
+
+pop_tag:
+       if (!asn1_pop_tag(data)) {
+               return false;
+       }
+
+       return true;
+}
+
 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
 {
        int i;
@@ -244,7 +376,9 @@ static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *res
        }
 }
 
-_PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
+_PUBLIC_ bool ldap_encode(struct ldap_message *msg,
+                         const struct ldap_control_handler *control_handlers,
+                         DATA_BLOB *result, TALLOC_CTX *mem_ctx)
 {
        struct asn1_data *data = asn1_init(mem_ctx);
        int i, j;
@@ -531,7 +665,9 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CT
                asn1_push_tag(data, ASN1_CONTEXT(0));
                
                for (i = 0; msg->controls[i] != NULL; i++) {
-                       if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
+                       if (!ldap_encode_control(mem_ctx, data,
+                                                control_handlers,
+                                                msg->controls[i])) {
                                return false;
                        }
                }
@@ -993,7 +1129,9 @@ static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 
 /* This routine returns LDAP status codes */
 
-_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
+_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
+                             const struct ldap_control_handler *control_handlers,
+                             struct ldap_message *msg)
 {
        uint8_t tag;
 
@@ -1428,7 +1566,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
                                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
                        }
                        
-                       if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
+                       if (!ldap_decode_control_value(ctrl, value,
+                                                      control_handlers,
+                                                      ctrl[i])) {
                                if (ctrl[i]->critical) {
                                        ctrl[i]->data = NULL;
                                        decoded[i] = false;
index d2ce14445d5fac95557f9cda5168edded0a13c58..c50018465c88d83c30fbcd28d1336338e1bd2f9a 100644 (file)
@@ -207,11 +207,21 @@ struct ldap_message {
        bool                   *controls_decoded;
 };
 
+struct ldap_control_handler {
+       const char *oid;
+       bool (*decode)(void *mem_ctx, DATA_BLOB in, void *_out);
+       bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
+};
+
 struct asn1_data;
 
 struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx);
-NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg);
-bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx);
+NTSTATUS ldap_decode(struct asn1_data *data,
+                    const struct ldap_control_handler *control_handlers,
+                    struct ldap_message *msg);
+bool ldap_encode(struct ldap_message *msg,
+                const struct ldap_control_handler *control_handlers,
+                DATA_BLOB *result, TALLOC_CTX *mem_ctx);
 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size);
 
 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
index da44c02aa85075d5c3eb88ae85d91ab269ce7520..a924024160326914492db016087603fc5abed5a5 100644 (file)
@@ -104,7 +104,7 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
                bool ret;
 
                msg = call->replies->msg;
-               if (!ldap_encode(msg, &b, call)) {
+               if (!ldap_encode(msg, samba_ldap_control_handlers(), &b, call)) {
                        DEBUG(0,("Failed to encode ldap reply of type %d\n", msg->type));
                        talloc_free(call);
                        return;
@@ -150,7 +150,7 @@ static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ldap_decode(asn1, msg);
+       status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
        if (!NT_STATUS_IS_OK(status)) {
                asn1_free(asn1);
                return status;
index 8d2e2e374c886e72b5b3aa1092cc4c52290bb94c..b18ba12b1fc2ac8a77681bed834c6a1154fa2fcc 100644 (file)
@@ -108,7 +108,7 @@ static void cldap_socket_recv(struct cldap_socket *cldap)
        }
 
        /* this initial decode is used to find the message id */
-       status = ldap_decode(asn1, ldap_msg);
+       status = ldap_decode(asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
                talloc_free(tmp_ctx);
@@ -343,7 +343,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
                goto failed;
        }
 
-       if (!ldap_encode(msg, &req->encoded, req)) {
+       if (!ldap_encode(msg, NULL, &req->encoded, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                goto failed;
@@ -396,7 +396,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
                msg->type = LDAP_TAG_SearchResultEntry;
                msg->r.SearchResultEntry = *io->response;
 
-               if (!ldap_encode(msg, &blob1, req)) {
+               if (!ldap_encode(msg, NULL, &blob1, req)) {
                        DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                                 req->dest->addr, req->dest->port));
                        status = NT_STATUS_INVALID_PARAMETER;
@@ -409,7 +409,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
        msg->type = LDAP_TAG_SearchResultDone;
        msg->r.SearchResultDone = *io->result;
 
-       if (!ldap_encode(msg, &blob2, req)) {
+       if (!ldap_encode(msg, NULL, &blob2, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                status = NT_STATUS_INVALID_PARAMETER;
@@ -463,7 +463,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
        ldap_msg = talloc(mem_ctx, struct ldap_message);
        NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
 
-       status = ldap_decode(req->asn1, ldap_msg);
+       status = ldap_decode(req->asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
                talloc_free(req);
@@ -479,7 +479,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
                *io->out.response = ldap_msg->r.SearchResultEntry;
 
                /* decode the 2nd part */
-               status = ldap_decode(req->asn1, ldap_msg);
+               status = ldap_decode(req->asn1, NULL, ldap_msg);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
                        talloc_free(req);
index 3e54d7fff0212d727459187d75e499d8e6b90cbd..304a2e1253d30f66945d5e3f6dec407e845122fa 100644 (file)
@@ -200,7 +200,7 @@ static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
        }
        
-       status = ldap_decode(asn1, msg);
+       status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
        if (!NT_STATUS_IS_OK(status)) {
                asn1_free(asn1);
                return status;
@@ -608,7 +608,7 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
 
        msg->messageid = req->messageid;
 
-       if (!ldap_encode(msg, &req->data, req)) {
+       if (!ldap_encode(msg, samba_ldap_control_handlers(), &req->data, req)) {
                status = NT_STATUS_INTERNAL_ERROR;
                goto failed;            
        }
index 487ea61222ff0eb4cf81e352e0e5f5b1a3277d1f..7949758a80c48200246c70d108cca0616b10eb3e 100644 (file)
 #include "libcli/ldap/ldap_proto.h"
 #include "dsdb/samdb/samdb.h"
 
-struct control_handler {
-       const char *oid;
-       bool (*decode)(void *mem_ctx, DATA_BLOB in, void *_out);
-       bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
-};
-
 static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        void **out = (void **)_out;
@@ -435,7 +429,6 @@ static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
 
 static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
-       void **out = (void **)_out;
        if (in.length != 0) {
                return false;
        }
@@ -445,7 +438,6 @@ static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
 
 static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
-       void **out = (void **)_out;
        if (in.length != 0) {
                return false;
        }
@@ -455,7 +447,6 @@ static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
 
 static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
-       void **out = (void **)_out;
        if (in.length != 0) {
                return false;
        }
@@ -465,7 +456,6 @@ static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
 
 static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
-       void **out = (void **)_out;
        if (in.length != 0) {
                return false;
        }
@@ -475,7 +465,6 @@ static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *
 
 static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
-       void **out = (void **)_out;
        if (in.length != 0) {
                return false;
        }
@@ -1149,6 +1138,7 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
 
 static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct dsdb_openldap_dereference_result_control *control;
        struct dsdb_openldap_dereference_result **r = NULL;
@@ -1216,7 +1206,7 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
        return true;
 }
 
-struct control_handler ldap_known_controls[] = {
+static const struct ldap_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 },
        { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
@@ -1240,121 +1230,8 @@ struct control_handler ldap_known_controls[] = {
        { NULL, NULL, NULL }
 };
 
-bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value, struct ldb_control *ctrl)
+const struct ldap_control_handler *samba_ldap_control_handlers(void)
 {
-       int i;
-
-       for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
-               if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].decode || !ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
-                               return false;
-                       }
-                       break;
-               }
-       }
-       if (ldap_known_controls[i].oid == NULL) {
-               return false;
-       }
-
-       return true;
+       return ldap_known_controls;
 }
 
-bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl, DATA_BLOB *value)
-{
-       DATA_BLOB oid;
-
-       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
-               return false;
-       }
-
-       if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
-               return false;
-       }
-       ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
-       if (!ctrl->oid) {
-               return false;
-       }
-
-       if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
-               bool critical;
-               if (!asn1_read_BOOLEAN(data, &critical)) {
-                       return false;
-               }
-               ctrl->critical = critical;
-       } else {
-               ctrl->critical = false;
-       }
-
-       ctrl->data = NULL;
-
-       if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
-               *value = data_blob(NULL, 0);
-               goto end_tag;
-       }
-
-       if (!asn1_read_OctetString(data, mem_ctx, value)) {
-               return false;
-       }
-
-end_tag:
-       if (!asn1_end_tag(data)) {
-               return false;
-       }
-
-       return true;
-}
-
-bool ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
-{
-       DATA_BLOB value;
-       int i;
-
-       for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
-               if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].encode) {
-                               if (ctrl->critical) {
-                                       return false;
-                               } else {
-                                       /* not encoding this control */
-                                       return true;
-                               }
-                       }
-                       if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
-                               return false;
-                       }
-                       break;
-               }
-       }
-       if (ldap_known_controls[i].oid == NULL) {
-               return false;
-       }
-
-       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
-               return false;
-       }
-
-       if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
-               return false;
-       }
-
-       if (ctrl->critical) {
-               if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
-                       return false;
-               }
-       }
-
-       if (!ctrl->data) {
-               goto pop_tag;
-       }
-
-       if (!asn1_write_OctetString(data, value.data, value.length)) {
-               return false;
-       }
-
-pop_tag:
-       if (!asn1_pop_tag(data)) {
-               return false;
-       }
-
-       return true;
-}