summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/tldap_util.h7
-rw-r--r--source3/lib/tldap_util.c131
2 files changed, 138 insertions, 0 deletions
diff --git a/source3/include/tldap_util.h b/source3/include/tldap_util.h
index 06b1036474..8869d1e9de 100644
--- a/source3/include/tldap_util.h
+++ b/source3/include/tldap_util.h
@@ -54,4 +54,11 @@ bool tldap_pull_uint64(struct tldap_message *msg, const char *attr,
bool tldap_pull_uint32(struct tldap_message *msg, const char *attr,
uint32_t *presult);
+struct tevent_req *tldap_fetch_rootdse_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tldap_context *ld);
+int tldap_fetch_rootdse_recv(struct tevent_req *req);
+int tldap_fetch_rootdse(struct tldap_context *ld);
+struct tldap_message *tldap_rootdse(struct tldap_context *ld);
+
#endif
diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c
index 7c579162a5..042665f15f 100644
--- a/source3/lib/tldap_util.c
+++ b/source3/lib/tldap_util.c
@@ -378,3 +378,134 @@ bool tldap_pull_uint32(struct tldap_message *msg, const char *attr,
*presult = (uint32_t)result;
return true;
}
+
+struct tldap_fetch_rootdse_state {
+ struct tldap_context *ld;
+ struct tldap_message *rootdse;
+};
+
+static void tldap_fetch_rootdse_done(struct tevent_req *subreq);
+
+struct tevent_req *tldap_fetch_rootdse_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tldap_context *ld)
+{
+ struct tevent_req *req, *subreq;
+ struct tldap_fetch_rootdse_state *state;
+ static const char *attrs[2] = { "*", "+" };
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct tldap_fetch_rootdse_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ld = ld;
+ state->rootdse = NULL;
+
+ subreq = tldap_search_send(
+ mem_ctx, ev, ld, "", TLDAP_SCOPE_BASE, "(objectclass=*)",
+ attrs, ARRAY_SIZE(attrs), 0, NULL, NULL, 0, 0, 0);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, tldap_fetch_rootdse_done, req);
+ return req;
+}
+
+static void tldap_fetch_rootdse_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct tldap_fetch_rootdse_state *state = tevent_req_data(
+ req, struct tldap_fetch_rootdse_state);
+ struct tldap_message *msg;
+ int rc;
+
+ rc = tldap_search_recv(subreq, state, &msg);
+ if (rc != TLDAP_SUCCESS) {
+ TALLOC_FREE(subreq);
+ tevent_req_error(req, rc);
+ return;
+ }
+
+ switch (tldap_msg_type(msg)) {
+ case TLDAP_RES_SEARCH_ENTRY:
+ if (state->rootdse != NULL) {
+ goto protocol_error;
+ }
+ state->rootdse = msg;
+ break;
+ case TLDAP_RES_SEARCH_RESULT:
+ TALLOC_FREE(subreq);
+ if (state->rootdse == NULL) {
+ goto protocol_error;
+ }
+ tevent_req_done(req);
+ break;
+ default:
+ goto protocol_error;
+ }
+ tevent_req_done(req);
+ return;
+
+protocol_error:
+ tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
+ return;
+}
+
+int tldap_fetch_rootdse_recv(struct tevent_req *req)
+{
+ struct tldap_fetch_rootdse_state *state = tevent_req_data(
+ req, struct tldap_fetch_rootdse_state);
+ int err;
+ char *dn;
+
+ if (tevent_req_is_ldap_error(req, &err)) {
+ return err;
+ }
+ /* Trigger parsing the dn, just to make sure it's ok */
+ if (!tldap_entry_dn(state->rootdse, &dn)) {
+ return TLDAP_DECODING_ERROR;
+ }
+ if (!tldap_context_setattr(state->ld, "tldap:rootdse",
+ &state->rootdse)) {
+ return TLDAP_NO_MEMORY;
+ }
+ return 0;
+}
+
+int tldap_fetch_rootdse(struct tldap_context *ld)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ int result;
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ result = TLDAP_NO_MEMORY;
+ goto fail;
+ }
+
+ req = tldap_fetch_rootdse_send(frame, ev, ld);
+ if (req == NULL) {
+ result = TLDAP_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ result = TLDAP_OPERATIONS_ERROR;
+ goto fail;
+ }
+
+ result = tldap_fetch_rootdse_recv(req);
+ fail:
+ TALLOC_FREE(frame);
+ return result;
+}
+
+struct tldap_message *tldap_rootdse(struct tldap_context *ld)
+{
+ return talloc_get_type(tldap_context_getattr(ld, "tldap:rootdse"),
+ struct tldap_message);
+}