tldap control support
authorVolker Lendecke <vl@samba.org>
Sat, 6 Jun 2009 21:21:01 +0000 (23:21 +0200)
committerVolker Lendecke <vl@samba.org>
Sat, 20 Jun 2009 16:54:06 +0000 (18:54 +0200)
source3/include/tldap.h
source3/lib/tldap.c

index 3da7d69d86115b03d6d85b432b70138a3a5efd73..820f5d70973a680f48f6294c740ac9bf39f05d7a 100644 (file)
@@ -29,7 +29,7 @@ struct tldap_message;
 struct tldap_control {
        const char *oid;
        DATA_BLOB value;
-       bool iscritical;
+       bool critical;
 };
 
 struct tldap_attribute {
@@ -104,7 +104,7 @@ int tldap_search(struct tldap_context *ld,
                 struct tldap_control *sctrls, int num_sctrls,
                 struct tldap_control *cctrls, int num_cctrls,
                 int timelimit, int sizelimit, int deref,
-                TALLOC_CTX *mem_ctx, struct tldap_message ***pentries,
+                TALLOC_CTX *mem_ctx, struct tldap_message ***entries,
                 struct tldap_message ***refs);
 bool tldap_entry_dn(struct tldap_message *msg, char **dn);
 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
@@ -159,9 +159,13 @@ int tldap_msg_type(const struct tldap_message *msg);
 const char *tldap_req_matcheddn(struct tevent_req *req);
 const char *tldap_req_diagnosticmessage(struct tevent_req *req);
 const char *tldap_req_referral(struct tevent_req *req);
+void tldap_req_sctrls(struct tevent_req *req, int *num_sctrls,
+                     struct tldap_control **sctrls);
 const char *tldap_ctx_matcheddn(struct tldap_context *ctx);
 const char *tldap_ctx_diagnosticmessage(struct tldap_context *ctx);
 const char *tldap_ctx_referral(struct tldap_context *ctx);
+void tldap_ctx_sctrls(struct tldap_context *ctx, int *num_sctrls,
+                     struct tldap_control **sctrls);
 const char *tldap_err2string(int rc);
 
 /* DEBUG */
index 8495161b652808a29c891661de8367d1b4f55bb9..7a36310ee409d69d6e5337c34c863d9179ba259a 100644 (file)
@@ -64,6 +64,7 @@ struct tldap_context {
        char *res_matcheddn;
        char *res_diagnosticmessage;
        char *res_referral;
+       struct tldap_control *res_sctrls;
 
        /* debug */
        void (*log_fn)(void *context, enum tldap_debug_level level,
@@ -347,13 +348,44 @@ struct tldap_msg_state {
        uint8_t *inbuf;
 };
 
+static void tldap_push_controls(struct asn1_data *data,
+                               struct tldap_control *sctrls,
+                               int num_sctrls)
+{
+       int i;
+
+       if ((sctrls == NULL) || (num_sctrls == 0)) {
+               return;
+       }
+
+       asn1_push_tag(data, ASN1_CONTEXT(0));
+
+       for (i=0; i<num_sctrls; i++) {
+               struct tldap_control *c = &sctrls[i];
+               asn1_push_tag(data, ASN1_SEQUENCE(0));
+               asn1_write_OctetString(data, c->oid, strlen(c->oid));
+               if (c->critical) {
+                       asn1_write_BOOLEAN(data, true);
+               }
+               if (c->value.data != NULL) {
+                       asn1_write_OctetString(data, c->value.data,
+                                              c->value.length);
+               }
+               asn1_pop_tag(data); /* ASN1_SEQUENCE(0) */
+       }
+
+       asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
+}
+
 static void tldap_msg_sent(struct tevent_req *subreq);
 static void tldap_msg_received(struct tevent_req *subreq);
 
 static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
                                         struct tevent_context *ev,
                                         struct tldap_context *ld,
-                                        int id, struct asn1_data *data)
+                                        int id, struct asn1_data *data,
+                                        struct tldap_control *sctrls,
+                                        int num_sctrls)
 {
        struct tevent_req *req, *subreq;
        struct tldap_msg_state *state;
@@ -370,6 +402,8 @@ static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
        state->ev = ev;
        state->id = id;
 
+       tldap_push_controls(data, sctrls, num_sctrls);
+
        asn1_pop_tag(data);
 
        if (!asn1_blob(data, &blob)) {
@@ -640,6 +674,7 @@ struct tldap_req_state {
        char *res_matcheddn;
        char *res_diagnosticmessage;
        char *res_referral;
+       struct tldap_control *res_sctrls;
 };
 
 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
@@ -678,12 +713,14 @@ static void tldap_save_errors(struct tldap_context *ctx,
        TALLOC_FREE(ctx->res_matcheddn);
        TALLOC_FREE(ctx->res_diagnosticmessage);
        TALLOC_FREE(ctx->res_referral);
+       TALLOC_FREE(ctx->res_sctrls);
 
        ctx->lderr = state->lderr;
        ctx->res_matcheddn = talloc_move(ctx, &state->res_matcheddn);
        ctx->res_diagnosticmessage = talloc_move(
                ctx, &state->res_diagnosticmessage);
        ctx->res_referral = talloc_move(ctx, &state->res_referral);
+       ctx->res_sctrls = talloc_move(ctx, &state->res_sctrls);
 }
 
 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
@@ -776,7 +813,8 @@ struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       subreq = tldap_msg_send(state, ev, ld, state->id, state->out);
+       subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
+                               sctrls, num_sctrls);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1128,7 +1166,8 @@ struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
        asn1_pop_tag(state->out);
        asn1_pop_tag(state->out);
 
-       subreq = tldap_msg_send(state, ev, ld, state->id, state->out);
+       subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
+                               sctrls, num_sctrls);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1415,6 +1454,62 @@ bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
        return true;
 }
 
+static bool tldap_decode_controls(struct tldap_req_state *state)
+{
+       struct asn1_data *data = state->result->data;
+       struct tldap_control *sctrls = NULL;
+       int num_controls = 0;
+
+       state->res_sctrls = NULL;
+
+       if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
+               return true;
+       }
+
+       asn1_start_tag(data, ASN1_CONTEXT(0));
+
+       while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
+               struct tldap_control *c;
+               char *oid = NULL;
+
+               sctrls = talloc_realloc(state, sctrls, struct tldap_control,
+                                       num_controls + 1);
+               if (sctrls == NULL) {
+                       return false;
+               }
+               c = &sctrls[num_controls];
+
+               asn1_start_tag(data, ASN1_SEQUENCE(0));
+               asn1_read_OctetString_talloc(state, data, &oid);
+               if ((data->has_error) || (oid == NULL)) {
+                       return false;
+               }
+               c->oid = oid;
+               if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
+                       asn1_read_BOOLEAN(data, &c->critical);
+               } else {
+                       c->critical = false;
+               }
+               c->value = data_blob_null;
+               if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
+                   !asn1_read_OctetString(data, state, &c->value)) {
+                       return false;
+               }
+               asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
+
+               num_controls += 1;
+       }
+
+       asn1_end_tag(data);     /* ASN1_CONTEXT(0) */
+
+       if (data->has_error) {
+               TALLOC_FREE(sctrls);
+               return false;
+       }
+       state->res_sctrls = sctrls;
+       return true;
+}
+
 static void tldap_simple_done(struct tevent_req *subreq, int type)
 {
        struct tevent_req *req = tevent_req_callback_data(
@@ -1435,7 +1530,8 @@ static void tldap_simple_done(struct tevent_req *subreq, int type)
        }
        if (!asn1_start_tag(state->result->data, state->result->type) ||
            !tldap_decode_response(state) ||
-           !asn1_end_tag(state->result->data)) {
+           !asn1_end_tag(state->result->data) ||
+           !tldap_decode_controls(state)) {
                tevent_req_error(req, TLDAP_DECODING_ERROR);
                return;
        }
@@ -1499,7 +1595,8 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
        asn1_pop_tag(state->out);
        asn1_pop_tag(state->out);
 
-       subreq = tldap_msg_send(state, ev, ld, state->id, state->out);
+       subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
+                               sctrls, num_sctrls);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1598,7 +1695,8 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
        asn1_pop_tag(state->out);
        asn1_pop_tag(state->out);
 
-       subreq = tldap_msg_send(state, ev, ld, state->id, state->out);
+       subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
+                               sctrls, num_sctrls);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1674,7 +1772,8 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
        asn1_write(state->out, dn, strlen(dn));
        asn1_pop_tag(state->out);
 
-       subreq = tldap_msg_send(state, ev, ld, state->id, state->out);
+       subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
+                               sctrls, num_sctrls);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -1757,6 +1856,15 @@ const char *tldap_req_referral(struct tevent_req *req)
        return state->res_referral;
 }
 
+void tldap_req_sctrls(struct tevent_req *req, int *num_sctrls,
+                     struct tldap_control **sctrls)
+{
+       struct tldap_req_state *state = tevent_req_data(
+               req, struct tldap_req_state);
+       *sctrls = state->res_sctrls;
+       *num_sctrls = talloc_array_length(state->res_sctrls);
+}
+
 const char *tldap_ctx_matcheddn(struct tldap_context *ctx)
 {
        return ctx->res_matcheddn;
@@ -1772,6 +1880,13 @@ const char *tldap_ctx_referral(struct tldap_context *ctx)
        return ctx->res_referral;
 }
 
+void tldap_ctx_sctrls(struct tldap_context *ctx, int *num_sctrls,
+                     struct tldap_control **sctrls)
+{
+       *sctrls = ctx->res_sctrls;
+       *num_sctrls = talloc_array_length(ctx->res_sctrls);
+}
+
 const char *tldap_err2string(int rc)
 {
        const char *res = NULL;