diff options
author | Volker Lendecke <vl@samba.org> | 2009-06-13 11:59:39 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2009-06-19 14:28:22 +0200 |
commit | b9c99a29286c748bbd706fd8757be6ef3fa9abc1 (patch) | |
tree | 505fcc81dba4db2affa85cbd620f508114807a6a /source3/lib | |
parent | 663e841ecdd4baddcdc4905a72c78c2868a8c408 (diff) | |
download | samba-b9c99a29286c748bbd706fd8757be6ef3fa9abc1.tar.gz samba-b9c99a29286c748bbd706fd8757be6ef3fa9abc1.tar.bz2 samba-b9c99a29286c748bbd706fd8757be6ef3fa9abc1.zip |
Add tldap_fetch_rootdse
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/tldap_util.c | 131 |
1 files changed, 131 insertions, 0 deletions
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); +} |