summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-06-06 23:21:01 +0200
committerVolker Lendecke <vl@samba.org>2009-06-20 18:54:06 +0200
commitd45cf0146b62bf196ff207cd1ec52bbc39ef67ca (patch)
tree6c86d64a4d9d867110119a6a88d4bb10927321b4
parent63a70ba0ad306e39311db3145d85323276e02c02 (diff)
downloadsamba-d45cf0146b62bf196ff207cd1ec52bbc39ef67ca.tar.gz
samba-d45cf0146b62bf196ff207cd1ec52bbc39ef67ca.tar.bz2
samba-d45cf0146b62bf196ff207cd1ec52bbc39ef67ca.zip
tldap control support
-rw-r--r--source3/include/tldap.h8
-rw-r--r--source3/lib/tldap.c129
2 files changed, 128 insertions, 9 deletions
diff --git a/source3/include/tldap.h b/source3/include/tldap.h
index 3da7d69d86..820f5d7097 100644
--- a/source3/include/tldap.h
+++ b/source3/include/tldap.h
@@ -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 */
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index 8495161b65..7a36310ee4 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -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;