2 Unix SMB/CIFS implementation.
3 Infrastructure for async ldap client requests
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 bool tevent_req_is_ldap_error(struct tevent_req *req, int *perr)
24 enum tevent_req_state state;
27 if (!tevent_req_is_error(req, &state, &err)) {
31 case TEVENT_REQ_TIMED_OUT:
32 *perr = TLDAP_TIMEOUT;
34 case TEVENT_REQ_NO_MEMORY:
35 *perr = TLDAP_NO_MEMORY;
37 case TEVENT_REQ_USER_ERROR:
41 *perr = TLDAP_OPERATIONS_ERROR;
47 struct tldap_ctx_attribute {
52 struct tldap_context {
57 struct tstream_context *conn;
59 struct tevent_queue *outgoing;
60 struct tevent_req **pending;
62 /* For the sync wrappers we need something like get_last_error... */
63 struct tldap_message *last_msg;
66 void (*log_fn)(void *context, enum tldap_debug_level level,
67 const char *fmt, va_list ap);
70 struct tldap_ctx_attribute *ctx_attrs;
73 struct tldap_message {
74 struct asn1_data *data;
81 struct tldap_attribute *attribs;
83 /* Error data sent by the server */
86 char *res_diagnosticmessage;
88 struct tldap_control *res_sctrls;
90 /* Controls sent by the server */
91 struct tldap_control *ctrls;
94 void tldap_set_debug(struct tldap_context *ld,
95 void (*log_fn)(void *log_private,
96 enum tldap_debug_level level,
98 va_list ap) PRINTF_ATTRIBUTE(3,0),
102 ld->log_private = log_private;
105 static void tldap_debug(struct tldap_context *ld,
106 enum tldap_debug_level level,
107 const char *fmt, ...)
113 if (ld->log_fn == NULL) {
117 ld->log_fn(ld->log_private, level, fmt, ap);
121 static int tldap_next_msgid(struct tldap_context *ld)
125 result = ld->msgid++;
126 if (ld->msgid == 2147483647) {
132 struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
134 struct tldap_context *ctx;
137 ctx = talloc_zero(mem_ctx, struct tldap_context);
141 ret = tstream_bsd_existing_socket(ctx, fd, &ctx->conn);
148 ctx->outgoing = tevent_queue_create(ctx, "tldap_outgoing");
149 if (ctx->outgoing == NULL) {
156 static struct tldap_ctx_attribute *tldap_context_findattr(
157 struct tldap_context *ld, const char *name)
161 num_attrs = talloc_array_length(ld->ctx_attrs);
163 for (i=0; i<num_attrs; i++) {
164 if (strcmp(ld->ctx_attrs[i].name, name) == 0) {
165 return &ld->ctx_attrs[i];
171 bool tldap_context_setattr(struct tldap_context *ld,
172 const char *name, const void *_pptr)
174 struct tldap_ctx_attribute *tmp, *attr;
177 void **pptr = (void **)_pptr;
179 attr = tldap_context_findattr(ld, name);
182 * We don't actually delete attrs, we don't expect tons of
183 * attributes being shuffled around.
185 TALLOC_FREE(attr->ptr);
187 attr->ptr = talloc_move(ld->ctx_attrs, pptr);
193 tmpname = talloc_strdup(ld, name);
194 if (tmpname == NULL) {
198 num_attrs = talloc_array_length(ld->ctx_attrs);
200 tmp = talloc_realloc(ld, ld->ctx_attrs, struct tldap_ctx_attribute,
203 TALLOC_FREE(tmpname);
206 tmp[num_attrs].name = talloc_move(tmp, &tmpname);
208 tmp[num_attrs].ptr = talloc_move(tmp, pptr);
210 tmp[num_attrs].ptr = NULL;
217 void *tldap_context_getattr(struct tldap_context *ld, const char *name)
219 struct tldap_ctx_attribute *attr = tldap_context_findattr(ld, name);
227 struct read_ldap_state {
232 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data);
233 static void read_ldap_done(struct tevent_req *subreq);
235 static struct tevent_req *read_ldap_send(TALLOC_CTX *mem_ctx,
236 struct tevent_context *ev,
237 struct tstream_context *conn)
239 struct tevent_req *req, *subreq;
240 struct read_ldap_state *state;
242 req = tevent_req_create(mem_ctx, &state, struct read_ldap_state);
248 subreq = tstream_read_packet_send(state, ev, conn, 2, read_ldap_more,
250 if (tevent_req_nomem(subreq, req)) {
251 return tevent_req_post(req, ev);
253 tevent_req_set_callback(subreq, read_ldap_done, req);
257 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data)
259 struct read_ldap_state *state = talloc_get_type_abort(
260 private_data, struct read_ldap_state);
265 /* We've been here, we're done */
270 * From ldap.h: LDAP_TAG_MESSAGE is 0x30
272 if (buf[0] != 0x30) {
277 if ((len & 0x80) == 0) {
282 lensize = (len & 0x7f);
286 /* Please get us the full length */
289 if (buflen > 2 + lensize) {
293 if (buflen != 2 + lensize) {
297 for (i=0; i<lensize; i++) {
298 len = (len << 8) | buf[2+i];
303 static void read_ldap_done(struct tevent_req *subreq)
305 struct tevent_req *req = tevent_req_callback_data(
306 subreq, struct tevent_req);
307 struct read_ldap_state *state = tevent_req_data(
308 req, struct read_ldap_state);
312 nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
315 tevent_req_error(req, err);
318 tevent_req_done(req);
321 static ssize_t read_ldap_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
322 uint8_t **pbuf, int *perrno)
324 struct read_ldap_state *state = tevent_req_data(
325 req, struct read_ldap_state);
327 if (tevent_req_is_unix_error(req, perrno)) {
330 *pbuf = talloc_move(mem_ctx, &state->buf);
331 return talloc_get_size(*pbuf);
334 struct tldap_msg_state {
335 struct tldap_context *ld;
336 struct tevent_context *ev;
340 struct asn1_data *data;
344 static void tldap_push_controls(struct asn1_data *data,
345 struct tldap_control *sctrls,
350 if ((sctrls == NULL) || (num_sctrls == 0)) {
354 asn1_push_tag(data, ASN1_CONTEXT(0));
356 for (i=0; i<num_sctrls; i++) {
357 struct tldap_control *c = &sctrls[i];
358 asn1_push_tag(data, ASN1_SEQUENCE(0));
359 asn1_write_OctetString(data, c->oid, strlen(c->oid));
361 asn1_write_BOOLEAN(data, true);
363 if (c->value.data != NULL) {
364 asn1_write_OctetString(data, c->value.data,
367 asn1_pop_tag(data); /* ASN1_SEQUENCE(0) */
370 asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
373 static void tldap_msg_sent(struct tevent_req *subreq);
374 static void tldap_msg_received(struct tevent_req *subreq);
376 static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
377 struct tevent_context *ev,
378 struct tldap_context *ld,
379 int id, struct asn1_data *data,
380 struct tldap_control *sctrls,
383 struct tevent_req *req, *subreq;
384 struct tldap_msg_state *state;
387 tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
390 req = tevent_req_create(mem_ctx, &state, struct tldap_msg_state);
398 tldap_push_controls(data, sctrls, num_sctrls);
402 if (!asn1_blob(data, &blob)) {
403 tevent_req_error(req, TLDAP_ENCODING_ERROR);
404 return tevent_req_post(req, ev);
407 state->iov.iov_base = blob.data;
408 state->iov.iov_len = blob.length;
410 subreq = tstream_writev_queue_send(state, ev, ld->conn, ld->outgoing,
412 if (tevent_req_nomem(subreq, req)) {
413 return tevent_req_post(req, ev);
415 tevent_req_set_callback(subreq, tldap_msg_sent, req);
419 static void tldap_msg_unset_pending(struct tevent_req *req)
421 struct tldap_msg_state *state = tevent_req_data(
422 req, struct tldap_msg_state);
423 struct tldap_context *ld = state->ld;
424 int num_pending = talloc_array_length(ld->pending);
427 if (num_pending == 1) {
428 TALLOC_FREE(ld->pending);
432 for (i=0; i<num_pending; i++) {
433 if (req == ld->pending[i]) {
437 if (i == num_pending) {
439 * Something's seriously broken. Just returning here is the
440 * right thing nevertheless, the point of this routine is to
441 * remove ourselves from cli->pending.
447 * Remove ourselves from the cli->pending array
449 if (num_pending > 1) {
450 ld->pending[i] = ld->pending[num_pending-1];
454 * No NULL check here, we're shrinking by sizeof(void *), and
455 * talloc_realloc just adjusts the size for this.
457 ld->pending = talloc_realloc(NULL, ld->pending, struct tevent_req *,
462 static int tldap_msg_destructor(struct tevent_req *req)
464 tldap_msg_unset_pending(req);
468 static bool tldap_msg_set_pending(struct tevent_req *req)
470 struct tldap_msg_state *state = tevent_req_data(
471 req, struct tldap_msg_state);
472 struct tldap_context *ld;
473 struct tevent_req **pending;
475 struct tevent_req *subreq;
478 num_pending = talloc_array_length(ld->pending);
480 pending = talloc_realloc(ld, ld->pending, struct tevent_req *,
482 if (pending == NULL) {
485 pending[num_pending] = req;
486 ld->pending = pending;
487 talloc_set_destructor(req, tldap_msg_destructor);
489 if (num_pending > 0) {
494 * We're the first ones, add the read_ldap request that waits for the
495 * answer from the server
497 subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
498 if (subreq == NULL) {
499 tldap_msg_unset_pending(req);
502 tevent_req_set_callback(subreq, tldap_msg_received, ld);
506 static void tldap_msg_sent(struct tevent_req *subreq)
508 struct tevent_req *req = tevent_req_callback_data(
509 subreq, struct tevent_req);
513 nwritten = tstream_writev_queue_recv(subreq, &err);
515 if (nwritten == -1) {
516 tevent_req_error(req, TLDAP_SERVER_DOWN);
520 if (!tldap_msg_set_pending(req)) {
521 tevent_req_nomem(NULL, req);
526 static int tldap_msg_msgid(struct tevent_req *req)
528 struct tldap_msg_state *state = tevent_req_data(
529 req, struct tldap_msg_state);
534 static void tldap_msg_received(struct tevent_req *subreq)
536 struct tldap_context *ld = tevent_req_callback_data(
537 subreq, struct tldap_context);
538 struct tevent_req *req;
539 struct tldap_msg_state *state;
540 struct tevent_context *ev;
541 struct asn1_data *data;
550 received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
552 if (received == -1) {
553 status = TLDAP_SERVER_DOWN;
557 data = asn1_init(talloc_tos());
559 status = TLDAP_NO_MEMORY;
562 asn1_load_nocopy(data, inbuf, received);
565 ok &= asn1_start_tag(data, ASN1_SEQUENCE(0));
566 ok &= asn1_read_Integer(data, &id);
567 ok &= asn1_peek_uint8(data, &type);
570 status = TLDAP_PROTOCOL_ERROR;
574 tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
575 "type %d\n", id, (int)type);
577 num_pending = talloc_array_length(ld->pending);
579 for (i=0; i<num_pending; i++) {
580 if (id == tldap_msg_msgid(ld->pending[i])) {
584 if (i == num_pending) {
585 /* Dump unexpected reply */
586 tldap_debug(ld, TLDAP_DEBUG_WARNING, "tldap_msg_received: "
587 "No request pending for msg %d\n", id);
593 req = ld->pending[i];
594 state = tevent_req_data(req, struct tldap_msg_state);
596 state->inbuf = talloc_move(state, &inbuf);
597 state->data = talloc_move(state, &data);
601 talloc_set_destructor(req, NULL);
602 tldap_msg_unset_pending(req);
603 num_pending = talloc_array_length(ld->pending);
605 tevent_req_done(req);
608 if (num_pending == 0) {
611 if (talloc_array_length(ld->pending) > num_pending) {
613 * The callback functions called from tevent_req_done() above
614 * have put something on the pending queue. We don't have to
615 * trigger the read_ldap_send(), tldap_msg_set_pending() has
616 * done it for us already.
621 state = tevent_req_data(ld->pending[0], struct tldap_msg_state);
622 subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
623 if (subreq == NULL) {
624 status = TLDAP_NO_MEMORY;
627 tevent_req_set_callback(subreq, tldap_msg_received, ld);
631 while (talloc_array_length(ld->pending) > 0) {
632 req = ld->pending[0];
633 talloc_set_destructor(req, NULL);
634 tldap_msg_destructor(req);
635 tevent_req_error(req, status);
639 static int tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
640 struct tldap_message **pmsg)
642 struct tldap_msg_state *state = tevent_req_data(
643 req, struct tldap_msg_state);
644 struct tldap_message *msg;
648 if (tevent_req_is_ldap_error(req, &err)) {
652 if (!asn1_peek_uint8(state->data, &msgtype)) {
653 return TLDAP_PROTOCOL_ERROR;
657 return TLDAP_SUCCESS;
660 msg = talloc_zero(mem_ctx, struct tldap_message);
662 return TLDAP_NO_MEMORY;
666 msg->inbuf = talloc_move(msg, &state->inbuf);
667 msg->data = talloc_move(msg, &state->data);
671 return TLDAP_SUCCESS;
674 struct tldap_req_state {
676 struct asn1_data *out;
677 struct tldap_message *result;
680 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
681 struct tldap_context *ld,
682 struct tldap_req_state **pstate)
684 struct tevent_req *req;
685 struct tldap_req_state *state;
687 req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
692 state->out = asn1_init(state);
693 if (state->out == NULL) {
697 state->result = NULL;
698 state->id = tldap_next_msgid(ld);
700 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
701 asn1_write_Integer(state->out, state->id);
707 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
709 struct tldap_req_state *state = tevent_req_data(
710 req, struct tldap_req_state);
712 TALLOC_FREE(ld->last_msg);
713 ld->last_msg = talloc_move(ld, &state->result);
716 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
718 char *result = talloc_array(mem_ctx, char, blob.length+1);
719 memcpy(result, blob.data, blob.length);
720 result[blob.length] = '\0';
724 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
725 struct asn1_data *data,
729 if (!asn1_read_OctetString(data, mem_ctx, &string))
731 *result = blob2string_talloc(mem_ctx, string);
732 data_blob_free(&string);
736 static bool tldap_decode_controls(struct tldap_req_state *state);
738 static bool tldap_decode_response(struct tldap_req_state *state)
740 struct asn1_data *data = state->result->data;
741 struct tldap_message *msg = state->result;
744 ok &= asn1_read_enumerated(data, &msg->lderr);
745 ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
746 ok &= asn1_read_OctetString_talloc(msg, data,
747 &msg->res_diagnosticmessage);
748 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
749 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
750 ok &= asn1_read_OctetString_talloc(msg, data,
752 ok &= asn1_end_tag(data);
754 msg->res_referral = NULL;
760 static void tldap_sasl_bind_done(struct tevent_req *subreq);
762 struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
763 struct tevent_context *ev,
764 struct tldap_context *ld,
766 const char *mechanism,
768 struct tldap_control *sctrls,
770 struct tldap_control *cctrls,
773 struct tevent_req *req, *subreq;
774 struct tldap_req_state *state;
776 req = tldap_req_create(mem_ctx, ld, &state);
785 asn1_push_tag(state->out, TLDAP_REQ_BIND);
786 asn1_write_Integer(state->out, ld->ld_version);
787 asn1_write_OctetString(state->out, dn, (dn != NULL) ? strlen(dn) : 0);
789 if (mechanism == NULL) {
790 asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0));
791 asn1_write(state->out, creds->data, creds->length);
792 asn1_pop_tag(state->out);
794 asn1_push_tag(state->out, ASN1_CONTEXT(3));
795 asn1_write_OctetString(state->out, mechanism,
797 if ((creds != NULL) && (creds->data != NULL)) {
798 asn1_write_OctetString(state->out, creds->data,
801 asn1_pop_tag(state->out);
804 if (!asn1_pop_tag(state->out)) {
805 tevent_req_error(req, TLDAP_ENCODING_ERROR);
806 return tevent_req_post(req, ev);
809 subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
811 if (tevent_req_nomem(subreq, req)) {
812 return tevent_req_post(req, ev);
814 tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
818 static void tldap_sasl_bind_done(struct tevent_req *subreq)
820 struct tevent_req *req = tevent_req_callback_data(
821 subreq, struct tevent_req);
822 struct tldap_req_state *state = tevent_req_data(
823 req, struct tldap_req_state);
826 err = tldap_msg_recv(subreq, state, &state->result);
828 if (err != TLDAP_SUCCESS) {
829 tevent_req_error(req, err);
832 if (state->result->type != TLDAP_RES_BIND) {
833 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
836 if (!asn1_start_tag(state->result->data, state->result->type) ||
837 !tldap_decode_response(state) ||
838 !asn1_end_tag(state->result->data)) {
839 tevent_req_error(req, TLDAP_DECODING_ERROR);
843 * TODO: pull the reply blob
845 if (state->result->lderr != TLDAP_SUCCESS) {
846 tevent_req_error(req, state->result->lderr);
849 tevent_req_done(req);
852 int tldap_sasl_bind_recv(struct tevent_req *req)
856 if (tevent_req_is_ldap_error(req, &err)) {
859 return TLDAP_SUCCESS;
862 int tldap_sasl_bind(struct tldap_context *ld,
864 const char *mechanism,
866 struct tldap_control *sctrls,
868 struct tldap_control *cctrls,
871 TALLOC_CTX *frame = talloc_stackframe();
872 struct tevent_context *ev;
873 struct tevent_req *req;
876 ev = event_context_init(frame);
878 result = TLDAP_NO_MEMORY;
882 req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
883 sctrls, num_sctrls, cctrls, num_cctrls);
885 result = TLDAP_NO_MEMORY;
889 if (!tevent_req_poll(req, ev)) {
890 result = TLDAP_OPERATIONS_ERROR;
894 result = tldap_sasl_bind_recv(req);
895 tldap_save_msg(ld, req);
901 struct tevent_req *tldap_simple_bind_send(TALLOC_CTX *mem_ctx,
902 struct tevent_context *ev,
903 struct tldap_context *ld,
909 if (passwd != NULL) {
910 cred.data = (uint8_t *)passwd;
911 cred.length = strlen(passwd);
913 cred.data = (uint8_t *)"";
916 return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
920 int tldap_simple_bind_recv(struct tevent_req *req)
922 return tldap_sasl_bind_recv(req);
925 int tldap_simple_bind(struct tldap_context *ld, const char *dn,
930 if (passwd != NULL) {
931 cred.data = (uint8_t *)passwd;
932 cred.length = strlen(passwd);
934 cred.data = (uint8_t *)"";
937 return tldap_sasl_bind(ld, dn, NULL, &cred, NULL, 0, NULL, 0);
940 /*****************************************************************************/
943 * This piece has a dependency on ldb, the ldb_parse_tree() function is used.
944 * In case we want to separate out tldap, we need to copy or rewrite it.
947 #include "lib/ldb/include/ldb.h"
948 #include "lib/ldb/include/ldb_errors.h"
950 static bool ldap_push_filter(struct asn1_data *data,
951 struct ldb_parse_tree *tree)
955 switch (tree->operation) {
959 ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
960 for (i=0; i<tree->u.list.num_elements; i++) {
961 if (!ldap_push_filter(data,
962 tree->u.list.elements[i])) {
970 asn1_push_tag(data, ASN1_CONTEXT(2));
971 if (!ldap_push_filter(data, tree->u.isnot.child)) {
977 case LDB_OP_EQUALITY:
979 asn1_push_tag(data, ASN1_CONTEXT(3));
980 asn1_write_OctetString(data, tree->u.equality.attr,
981 strlen(tree->u.equality.attr));
982 asn1_write_OctetString(data, tree->u.equality.value.data,
983 tree->u.equality.value.length);
987 case LDB_OP_SUBSTRING:
989 SubstringFilter ::= SEQUENCE {
990 type AttributeDescription,
991 -- at least one must be present
992 substrings SEQUENCE OF CHOICE {
993 initial [0] LDAPString,
995 final [2] LDAPString } }
997 asn1_push_tag(data, ASN1_CONTEXT(4));
998 asn1_write_OctetString(data, tree->u.substring.attr,
999 strlen(tree->u.substring.attr));
1000 asn1_push_tag(data, ASN1_SEQUENCE(0));
1002 if (!tree->u.substring.start_with_wildcard) {
1003 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
1004 asn1_write_DATA_BLOB_LDAPString(
1005 data, tree->u.substring.chunks[i]);
1009 while (tree->u.substring.chunks[i]) {
1012 if ((!tree->u.substring.chunks[i + 1]) &&
1013 (tree->u.substring.end_with_wildcard == 0)) {
1018 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
1019 asn1_write_DATA_BLOB_LDAPString(
1020 data, tree->u.substring.chunks[i]);
1028 case LDB_OP_GREATER:
1029 /* greaterOrEqual test */
1030 asn1_push_tag(data, ASN1_CONTEXT(5));
1031 asn1_write_OctetString(data, tree->u.comparison.attr,
1032 strlen(tree->u.comparison.attr));
1033 asn1_write_OctetString(data, tree->u.comparison.value.data,
1034 tree->u.comparison.value.length);
1039 /* lessOrEqual test */
1040 asn1_push_tag(data, ASN1_CONTEXT(6));
1041 asn1_write_OctetString(data, tree->u.comparison.attr,
1042 strlen(tree->u.comparison.attr));
1043 asn1_write_OctetString(data, tree->u.comparison.value.data,
1044 tree->u.comparison.value.length);
1048 case LDB_OP_PRESENT:
1050 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
1051 asn1_write_LDAPString(data, tree->u.present.attr);
1053 return !data->has_error;
1057 asn1_push_tag(data, ASN1_CONTEXT(8));
1058 asn1_write_OctetString(data, tree->u.comparison.attr,
1059 strlen(tree->u.comparison.attr));
1060 asn1_write_OctetString(data, tree->u.comparison.value.data,
1061 tree->u.comparison.value.length);
1065 case LDB_OP_EXTENDED:
1067 MatchingRuleAssertion ::= SEQUENCE {
1068 matchingRule [1] MatchingRuleID OPTIONAL,
1069 type [2] AttributeDescription OPTIONAL,
1070 matchValue [3] AssertionValue,
1071 dnAttributes [4] BOOLEAN DEFAULT FALSE
1074 asn1_push_tag(data, ASN1_CONTEXT(9));
1075 if (tree->u.extended.rule_id) {
1076 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
1077 asn1_write_LDAPString(data, tree->u.extended.rule_id);
1080 if (tree->u.extended.attr) {
1081 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
1082 asn1_write_LDAPString(data, tree->u.extended.attr);
1085 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
1086 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
1088 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
1089 asn1_write_uint8(data, tree->u.extended.dnAttributes);
1097 return !data->has_error;
1100 static bool tldap_push_filter(struct asn1_data *data, const char *filter)
1102 struct ldb_parse_tree *tree;
1105 tree = ldb_parse_tree(talloc_tos(), filter);
1109 ret = ldap_push_filter(data, tree);
1114 /*****************************************************************************/
1116 static void tldap_search_done(struct tevent_req *subreq);
1118 struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
1119 struct tevent_context *ev,
1120 struct tldap_context *ld,
1121 const char *base, int scope,
1126 struct tldap_control *sctrls,
1128 struct tldap_control *cctrls,
1134 struct tevent_req *req, *subreq;
1135 struct tldap_req_state *state;
1138 req = tldap_req_create(mem_ctx, ld, &state);
1143 asn1_push_tag(state->out, TLDAP_REQ_SEARCH);
1144 asn1_write_OctetString(state->out, base, strlen(base));
1145 asn1_write_enumerated(state->out, scope);
1146 asn1_write_enumerated(state->out, deref);
1147 asn1_write_Integer(state->out, sizelimit);
1148 asn1_write_Integer(state->out, timelimit);
1149 asn1_write_BOOLEAN(state->out, attrsonly);
1151 if (!tldap_push_filter(state->out, filter)) {
1152 goto encoding_error;
1155 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1156 for (i=0; i<num_attrs; i++) {
1157 asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]));
1159 asn1_pop_tag(state->out);
1160 asn1_pop_tag(state->out);
1162 subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1163 sctrls, num_sctrls);
1164 if (tevent_req_nomem(subreq, req)) {
1165 return tevent_req_post(req, ev);
1167 tevent_req_set_callback(subreq, tldap_search_done, req);
1171 tevent_req_error(req, TLDAP_ENCODING_ERROR);
1172 return tevent_req_post(req, ev);
1175 static void tldap_search_done(struct tevent_req *subreq)
1177 struct tevent_req *req = tevent_req_callback_data(
1178 subreq, struct tevent_req);
1179 struct tldap_req_state *state = tevent_req_data(
1180 req, struct tldap_req_state);
1183 err = tldap_msg_recv(subreq, state, &state->result);
1184 if (err != TLDAP_SUCCESS) {
1185 tevent_req_error(req, err);
1188 switch (state->result->type) {
1189 case TLDAP_RES_SEARCH_ENTRY:
1190 case TLDAP_RES_SEARCH_REFERENCE:
1191 tevent_req_notify_callback(req);
1192 if (!tldap_msg_set_pending(subreq)) {
1193 tevent_req_nomem(NULL, req);
1197 case TLDAP_RES_SEARCH_RESULT:
1198 TALLOC_FREE(subreq);
1199 if (!asn1_start_tag(state->result->data,
1200 state->result->type) ||
1201 !tldap_decode_response(state) ||
1202 !asn1_end_tag(state->result->data) ||
1203 !tldap_decode_controls(state)) {
1204 tevent_req_error(req, TLDAP_DECODING_ERROR);
1207 tevent_req_done(req);
1210 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1215 int tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1216 struct tldap_message **pmsg)
1218 struct tldap_req_state *state = tevent_req_data(
1219 req, struct tldap_req_state);
1222 if (!tevent_req_is_in_progress(req)
1223 && tevent_req_is_ldap_error(req, &err)) {
1227 if (tevent_req_is_in_progress(req)) {
1228 switch (state->result->type) {
1229 case TLDAP_RES_SEARCH_ENTRY:
1230 case TLDAP_RES_SEARCH_REFERENCE:
1233 return TLDAP_OPERATIONS_ERROR;
1237 *pmsg = talloc_move(mem_ctx, &state->result);
1238 return TLDAP_SUCCESS;
1241 struct tldap_sync_search_state {
1242 TALLOC_CTX *mem_ctx;
1243 struct tldap_message **entries;
1244 struct tldap_message **refs;
1248 static void tldap_search_cb(struct tevent_req *req)
1250 struct tldap_sync_search_state *state =
1251 (struct tldap_sync_search_state *)
1252 tevent_req_callback_data_void(req);
1253 struct tldap_message *msg, **tmp;
1254 int rc, num_entries, num_refs;
1256 rc = tldap_search_recv(req, talloc_tos(), &msg);
1257 if (rc != TLDAP_SUCCESS) {
1262 switch (tldap_msg_type(msg)) {
1263 case TLDAP_RES_SEARCH_ENTRY:
1264 num_entries = talloc_array_length(state->entries);
1265 tmp = talloc_realloc(state->mem_ctx, state->entries,
1266 struct tldap_message *, num_entries + 1);
1268 state->rc = TLDAP_NO_MEMORY;
1271 state->entries = tmp;
1272 state->entries[num_entries] = talloc_move(state->entries,
1275 case TLDAP_RES_SEARCH_REFERENCE:
1276 num_refs = talloc_array_length(state->refs);
1277 tmp = talloc_realloc(state->mem_ctx, state->refs,
1278 struct tldap_message *, num_refs + 1);
1280 state->rc = TLDAP_NO_MEMORY;
1284 state->refs[num_refs] = talloc_move(state->refs, &msg);
1286 case TLDAP_RES_SEARCH_RESULT:
1287 state->rc = TLDAP_SUCCESS;
1290 state->rc = TLDAP_PROTOCOL_ERROR;
1295 int tldap_search(struct tldap_context *ld,
1296 const char *base, int scope, const char *filter,
1297 const char **attrs, int num_attrs, int attrsonly,
1298 struct tldap_control *sctrls, int num_sctrls,
1299 struct tldap_control *cctrls, int num_cctrls,
1300 int timelimit, int sizelimit, int deref,
1301 TALLOC_CTX *mem_ctx, struct tldap_message ***entries,
1302 struct tldap_message ***refs)
1304 TALLOC_CTX *frame = talloc_stackframe();
1305 struct tevent_context *ev;
1306 struct tevent_req *req;
1307 struct tldap_sync_search_state state;
1310 state.mem_ctx = mem_ctx;
1311 state.rc = TLDAP_SUCCESS;
1313 ev = event_context_init(frame);
1315 state.rc = TLDAP_NO_MEMORY;
1319 req = tldap_search_send(frame, ev, ld, base, scope, filter,
1320 attrs, num_attrs, attrsonly,
1321 sctrls, num_sctrls, cctrls, num_cctrls,
1322 timelimit, sizelimit, deref);
1324 state.rc = TLDAP_NO_MEMORY;
1328 tevent_req_set_callback(req, tldap_search_cb, &state);
1330 while (tevent_req_is_in_progress(req)
1331 && (state.rc == TLDAP_SUCCESS)) {
1332 if (tevent_loop_once(ev) == -1) {
1333 return TLDAP_OPERATIONS_ERROR;
1337 if (state.rc != TLDAP_SUCCESS) {
1341 if (entries != NULL) {
1342 *entries = state.entries;
1344 TALLOC_FREE(state.entries);
1349 TALLOC_FREE(state.refs);
1351 tldap_save_msg(ld, req);
1357 static bool tldap_parse_search_entry(struct tldap_message *msg)
1359 int num_attribs = 0;
1361 asn1_start_tag(msg->data, msg->type);
1365 asn1_read_OctetString_talloc(msg, msg->data, &msg->dn);
1366 if (msg->dn == NULL) {
1371 * Attributes: We overallocate msg->attribs by one, so that while
1372 * looping over the attributes we can directly parse into the last
1373 * array element. Same for the values in the inner loop.
1376 msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
1377 if (msg->attribs == NULL) {
1381 asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1382 while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
1383 struct tldap_attribute *attrib;
1386 attrib = &msg->attribs[num_attribs];
1387 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
1388 if (attrib->values == NULL) {
1391 asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1392 asn1_read_OctetString_talloc(msg->attribs, msg->data,
1394 asn1_start_tag(msg->data, ASN1_SET);
1396 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
1397 asn1_read_OctetString(msg->data, msg,
1398 &attrib->values[num_values]);
1400 attrib->values = talloc_realloc(
1401 msg->attribs, attrib->values, DATA_BLOB,
1403 if (attrib->values == NULL) {
1408 attrib->values = talloc_realloc(msg->attribs, attrib->values,
1409 DATA_BLOB, num_values);
1410 attrib->num_values = num_values;
1412 asn1_end_tag(msg->data); /* ASN1_SET */
1413 asn1_end_tag(msg->data); /* ASN1_SEQUENCE(0) */
1414 msg->attribs = talloc_realloc(
1415 msg, msg->attribs, struct tldap_attribute,
1417 if (msg->attribs == NULL) {
1422 msg->attribs = talloc_realloc(
1423 msg, msg->attribs, struct tldap_attribute, num_attribs);
1424 asn1_end_tag(msg->data);
1425 if (msg->data->has_error) {
1431 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
1433 if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1440 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
1441 struct tldap_attribute **attributes)
1443 if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1446 *attributes = msg->attribs;
1447 *num_attributes = talloc_array_length(msg->attribs);
1451 static bool tldap_decode_controls(struct tldap_req_state *state)
1453 struct tldap_message *msg = state->result;
1454 struct asn1_data *data = msg->data;
1455 struct tldap_control *sctrls = NULL;
1456 int num_controls = 0;
1458 msg->res_sctrls = NULL;
1460 if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1464 asn1_start_tag(data, ASN1_CONTEXT(0));
1466 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1467 struct tldap_control *c;
1470 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
1472 if (sctrls == NULL) {
1475 c = &sctrls[num_controls];
1477 asn1_start_tag(data, ASN1_SEQUENCE(0));
1478 asn1_read_OctetString_talloc(msg, data, &oid);
1479 if ((data->has_error) || (oid == NULL)) {
1483 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1484 asn1_read_BOOLEAN(data, &c->critical);
1486 c->critical = false;
1488 c->value = data_blob_null;
1489 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
1490 !asn1_read_OctetString(data, msg, &c->value)) {
1493 asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
1498 asn1_end_tag(data); /* ASN1_CONTEXT(0) */
1500 if (data->has_error) {
1501 TALLOC_FREE(sctrls);
1504 msg->res_sctrls = sctrls;
1508 static void tldap_simple_done(struct tevent_req *subreq, int type)
1510 struct tevent_req *req = tevent_req_callback_data(
1511 subreq, struct tevent_req);
1512 struct tldap_req_state *state = tevent_req_data(
1513 req, struct tldap_req_state);
1516 err = tldap_msg_recv(subreq, state, &state->result);
1517 TALLOC_FREE(subreq);
1518 if (err != TLDAP_SUCCESS) {
1519 tevent_req_error(req, err);
1522 if (state->result->type != type) {
1523 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1526 if (!asn1_start_tag(state->result->data, state->result->type) ||
1527 !tldap_decode_response(state) ||
1528 !asn1_end_tag(state->result->data) ||
1529 !tldap_decode_controls(state)) {
1530 tevent_req_error(req, TLDAP_DECODING_ERROR);
1533 if (state->result->lderr != TLDAP_SUCCESS) {
1534 tevent_req_error(req, state->result->lderr);
1537 tevent_req_done(req);
1540 static int tldap_simple_recv(struct tevent_req *req)
1543 if (tevent_req_is_ldap_error(req, &err)) {
1546 return TLDAP_SUCCESS;
1549 static void tldap_add_done(struct tevent_req *subreq);
1551 struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
1552 struct tevent_context *ev,
1553 struct tldap_context *ld,
1555 struct tldap_mod *attributes,
1557 struct tldap_control *sctrls,
1559 struct tldap_control *cctrls,
1562 struct tevent_req *req, *subreq;
1563 struct tldap_req_state *state;
1566 req = tldap_req_create(mem_ctx, ld, &state);
1571 asn1_push_tag(state->out, TLDAP_REQ_ADD);
1572 asn1_write_OctetString(state->out, dn, strlen(dn));
1573 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1575 for (i=0; i<num_attributes; i++) {
1576 struct tldap_mod *attrib = &attributes[i];
1577 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1578 asn1_write_OctetString(state->out, attrib->attribute,
1579 strlen(attrib->attribute));
1580 asn1_push_tag(state->out, ASN1_SET);
1581 for (j=0; j<attrib->num_values; j++) {
1582 asn1_write_OctetString(state->out,
1583 attrib->values[j].data,
1584 attrib->values[j].length);
1586 asn1_pop_tag(state->out);
1587 asn1_pop_tag(state->out);
1590 asn1_pop_tag(state->out);
1591 asn1_pop_tag(state->out);
1593 subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1594 sctrls, num_sctrls);
1595 if (tevent_req_nomem(subreq, req)) {
1596 return tevent_req_post(req, ev);
1598 tevent_req_set_callback(subreq, tldap_add_done, req);
1602 static void tldap_add_done(struct tevent_req *subreq)
1604 return tldap_simple_done(subreq, TLDAP_RES_ADD);
1607 int tldap_add_recv(struct tevent_req *req)
1609 return tldap_simple_recv(req);
1612 int tldap_add(struct tldap_context *ld, const char *dn,
1613 int num_attributes, struct tldap_mod *attributes,
1614 struct tldap_control *sctrls, int num_sctrls,
1615 struct tldap_control *cctrls, int num_cctrls)
1617 TALLOC_CTX *frame = talloc_stackframe();
1618 struct tevent_context *ev;
1619 struct tevent_req *req;
1622 ev = event_context_init(frame);
1624 result = TLDAP_NO_MEMORY;
1628 req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
1629 sctrls, num_sctrls, cctrls, num_cctrls);
1631 result = TLDAP_NO_MEMORY;
1635 if (!tevent_req_poll(req, ev)) {
1636 result = TLDAP_OPERATIONS_ERROR;
1640 result = tldap_add_recv(req);
1641 tldap_save_msg(ld, req);
1647 static void tldap_modify_done(struct tevent_req *subreq);
1649 struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
1650 struct tevent_context *ev,
1651 struct tldap_context *ld,
1653 int num_mods, struct tldap_mod *mods,
1654 struct tldap_control *sctrls,
1656 struct tldap_control *cctrls,
1659 struct tevent_req *req, *subreq;
1660 struct tldap_req_state *state;
1663 req = tldap_req_create(mem_ctx, ld, &state);
1668 asn1_push_tag(state->out, TLDAP_REQ_MODIFY);
1669 asn1_write_OctetString(state->out, dn, strlen(dn));
1670 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1672 for (i=0; i<num_mods; i++) {
1673 struct tldap_mod *mod = &mods[i];
1674 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1675 asn1_write_enumerated(state->out, mod->mod_op),
1676 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1677 asn1_write_OctetString(state->out, mod->attribute,
1678 strlen(mod->attribute));
1679 asn1_push_tag(state->out, ASN1_SET);
1680 for (j=0; j<mod->num_values; j++) {
1681 asn1_write_OctetString(state->out,
1682 mod->values[j].data,
1683 mod->values[j].length);
1685 asn1_pop_tag(state->out);
1686 asn1_pop_tag(state->out);
1687 asn1_pop_tag(state->out);
1690 asn1_pop_tag(state->out);
1691 asn1_pop_tag(state->out);
1693 subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1694 sctrls, num_sctrls);
1695 if (tevent_req_nomem(subreq, req)) {
1696 return tevent_req_post(req, ev);
1698 tevent_req_set_callback(subreq, tldap_modify_done, req);
1702 static void tldap_modify_done(struct tevent_req *subreq)
1704 return tldap_simple_done(subreq, TLDAP_RES_MODIFY);
1707 int tldap_modify_recv(struct tevent_req *req)
1709 return tldap_simple_recv(req);
1712 int tldap_modify(struct tldap_context *ld, const char *dn,
1713 int num_mods, struct tldap_mod *mods,
1714 struct tldap_control *sctrls, int num_sctrls,
1715 struct tldap_control *cctrls, int num_cctrls)
1717 TALLOC_CTX *frame = talloc_stackframe();
1718 struct tevent_context *ev;
1719 struct tevent_req *req;
1722 ev = event_context_init(frame);
1724 result = TLDAP_NO_MEMORY;
1728 req = tldap_modify_send(frame, ev, ld, dn, num_mods, mods,
1729 sctrls, num_sctrls, cctrls, num_cctrls);
1731 result = TLDAP_NO_MEMORY;
1735 if (!tevent_req_poll(req, ev)) {
1736 result = TLDAP_OPERATIONS_ERROR;
1740 result = tldap_modify_recv(req);
1741 tldap_save_msg(ld, req);
1747 static void tldap_delete_done(struct tevent_req *subreq);
1749 struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
1750 struct tevent_context *ev,
1751 struct tldap_context *ld,
1753 struct tldap_control *sctrls,
1755 struct tldap_control *cctrls,
1758 struct tevent_req *req, *subreq;
1759 struct tldap_req_state *state;
1761 req = tldap_req_create(mem_ctx, ld, &state);
1766 asn1_push_tag(state->out, TLDAP_REQ_DELETE);
1767 asn1_write(state->out, dn, strlen(dn));
1768 asn1_pop_tag(state->out);
1770 subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1771 sctrls, num_sctrls);
1772 if (tevent_req_nomem(subreq, req)) {
1773 return tevent_req_post(req, ev);
1775 tevent_req_set_callback(subreq, tldap_delete_done, req);
1779 static void tldap_delete_done(struct tevent_req *subreq)
1781 return tldap_simple_done(subreq, TLDAP_RES_DELETE);
1784 int tldap_delete_recv(struct tevent_req *req)
1786 return tldap_simple_recv(req);
1789 int tldap_delete(struct tldap_context *ld, const char *dn,
1790 struct tldap_control *sctrls, int num_sctrls,
1791 struct tldap_control *cctrls, int num_cctrls)
1793 TALLOC_CTX *frame = talloc_stackframe();
1794 struct tevent_context *ev;
1795 struct tevent_req *req;
1798 ev = event_context_init(frame);
1800 result = TLDAP_NO_MEMORY;
1804 req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
1805 cctrls, num_cctrls);
1807 result = TLDAP_NO_MEMORY;
1811 if (!tevent_req_poll(req, ev)) {
1812 result = TLDAP_OPERATIONS_ERROR;
1816 result = tldap_delete_recv(req);
1817 tldap_save_msg(ld, req);
1823 int tldap_msg_id(const struct tldap_message *msg)
1828 int tldap_msg_type(const struct tldap_message *msg)
1833 const char *tldap_msg_matcheddn(struct tldap_message *msg)
1838 return msg->res_matcheddn;
1841 const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
1846 return msg->res_diagnosticmessage;
1849 const char *tldap_msg_referral(struct tldap_message *msg)
1854 return msg->res_referral;
1857 void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
1858 struct tldap_control **sctrls)
1864 *sctrls = msg->res_sctrls;
1865 *num_sctrls = talloc_array_length(msg->res_sctrls);
1868 struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
1870 return ld->last_msg;
1873 const char *tldap_err2string(int rc)
1875 const char *res = NULL;
1878 * This would normally be a table, but the error codes are not fully
1879 * sequential. Let the compiler figure out the optimum implementation
1885 res = "TLDAP_SUCCESS";
1887 case TLDAP_OPERATIONS_ERROR:
1888 res = "TLDAP_OPERATIONS_ERROR";
1890 case TLDAP_PROTOCOL_ERROR:
1891 res = "TLDAP_PROTOCOL_ERROR";
1893 case TLDAP_TIMELIMIT_EXCEEDED:
1894 res = "TLDAP_TIMELIMIT_EXCEEDED";
1896 case TLDAP_SIZELIMIT_EXCEEDED:
1897 res = "TLDAP_SIZELIMIT_EXCEEDED";
1899 case TLDAP_COMPARE_FALSE:
1900 res = "TLDAP_COMPARE_FALSE";
1902 case TLDAP_COMPARE_TRUE:
1903 res = "TLDAP_COMPARE_TRUE";
1905 case TLDAP_STRONG_AUTH_NOT_SUPPORTED:
1906 res = "TLDAP_STRONG_AUTH_NOT_SUPPORTED";
1908 case TLDAP_STRONG_AUTH_REQUIRED:
1909 res = "TLDAP_STRONG_AUTH_REQUIRED";
1911 case TLDAP_REFERRAL:
1912 res = "TLDAP_REFERRAL";
1914 case TLDAP_ADMINLIMIT_EXCEEDED:
1915 res = "TLDAP_ADMINLIMIT_EXCEEDED";
1917 case TLDAP_UNAVAILABLE_CRITICAL_EXTENSION:
1918 res = "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION";
1920 case TLDAP_CONFIDENTIALITY_REQUIRED:
1921 res = "TLDAP_CONFIDENTIALITY_REQUIRED";
1923 case TLDAP_SASL_BIND_IN_PROGRESS:
1924 res = "TLDAP_SASL_BIND_IN_PROGRESS";
1926 case TLDAP_NO_SUCH_ATTRIBUTE:
1927 res = "TLDAP_NO_SUCH_ATTRIBUTE";
1929 case TLDAP_UNDEFINED_TYPE:
1930 res = "TLDAP_UNDEFINED_TYPE";
1932 case TLDAP_INAPPROPRIATE_MATCHING:
1933 res = "TLDAP_INAPPROPRIATE_MATCHING";
1935 case TLDAP_CONSTRAINT_VIOLATION:
1936 res = "TLDAP_CONSTRAINT_VIOLATION";
1938 case TLDAP_TYPE_OR_VALUE_EXISTS:
1939 res = "TLDAP_TYPE_OR_VALUE_EXISTS";
1941 case TLDAP_INVALID_SYNTAX:
1942 res = "TLDAP_INVALID_SYNTAX";
1944 case TLDAP_NO_SUCH_OBJECT:
1945 res = "TLDAP_NO_SUCH_OBJECT";
1947 case TLDAP_ALIAS_PROBLEM:
1948 res = "TLDAP_ALIAS_PROBLEM";
1950 case TLDAP_INVALID_DN_SYNTAX:
1951 res = "TLDAP_INVALID_DN_SYNTAX";
1954 res = "TLDAP_IS_LEAF";
1956 case TLDAP_ALIAS_DEREF_PROBLEM:
1957 res = "TLDAP_ALIAS_DEREF_PROBLEM";
1959 case TLDAP_INAPPROPRIATE_AUTH:
1960 res = "TLDAP_INAPPROPRIATE_AUTH";
1962 case TLDAP_INVALID_CREDENTIALS:
1963 res = "TLDAP_INVALID_CREDENTIALS";
1965 case TLDAP_INSUFFICIENT_ACCESS:
1966 res = "TLDAP_INSUFFICIENT_ACCESS";
1971 case TLDAP_UNAVAILABLE:
1972 res = "TLDAP_UNAVAILABLE";
1974 case TLDAP_UNWILLING_TO_PERFORM:
1975 res = "TLDAP_UNWILLING_TO_PERFORM";
1977 case TLDAP_LOOP_DETECT:
1978 res = "TLDAP_LOOP_DETECT";
1980 case TLDAP_NAMING_VIOLATION:
1981 res = "TLDAP_NAMING_VIOLATION";
1983 case TLDAP_OBJECT_CLASS_VIOLATION:
1984 res = "TLDAP_OBJECT_CLASS_VIOLATION";
1986 case TLDAP_NOT_ALLOWED_ON_NONLEAF:
1987 res = "TLDAP_NOT_ALLOWED_ON_NONLEAF";
1989 case TLDAP_NOT_ALLOWED_ON_RDN:
1990 res = "TLDAP_NOT_ALLOWED_ON_RDN";
1992 case TLDAP_ALREADY_EXISTS:
1993 res = "TLDAP_ALREADY_EXISTS";
1995 case TLDAP_NO_OBJECT_CLASS_MODS:
1996 res = "TLDAP_NO_OBJECT_CLASS_MODS";
1998 case TLDAP_RESULTS_TOO_LARGE:
1999 res = "TLDAP_RESULTS_TOO_LARGE";
2001 case TLDAP_AFFECTS_MULTIPLE_DSAS:
2002 res = "TLDAP_AFFECTS_MULTIPLE_DSAS";
2005 res = "TLDAP_OTHER";
2007 case TLDAP_SERVER_DOWN:
2008 res = "TLDAP_SERVER_DOWN";
2010 case TLDAP_LOCAL_ERROR:
2011 res = "TLDAP_LOCAL_ERROR";
2013 case TLDAP_ENCODING_ERROR:
2014 res = "TLDAP_ENCODING_ERROR";
2016 case TLDAP_DECODING_ERROR:
2017 res = "TLDAP_DECODING_ERROR";
2020 res = "TLDAP_TIMEOUT";
2022 case TLDAP_AUTH_UNKNOWN:
2023 res = "TLDAP_AUTH_UNKNOWN";
2025 case TLDAP_FILTER_ERROR:
2026 res = "TLDAP_FILTER_ERROR";
2028 case TLDAP_USER_CANCELLED:
2029 res = "TLDAP_USER_CANCELLED";
2031 case TLDAP_PARAM_ERROR:
2032 res = "TLDAP_PARAM_ERROR";
2034 case TLDAP_NO_MEMORY:
2035 res = "TLDAP_NO_MEMORY";
2037 case TLDAP_CONNECT_ERROR:
2038 res = "TLDAP_CONNECT_ERROR";
2040 case TLDAP_NOT_SUPPORTED:
2041 res = "TLDAP_NOT_SUPPORTED";
2043 case TLDAP_CONTROL_NOT_FOUND:
2044 res = "TLDAP_CONTROL_NOT_FOUND";
2046 case TLDAP_NO_RESULTS_RETURNED:
2047 res = "TLDAP_NO_RESULTS_RETURNED";
2049 case TLDAP_MORE_RESULTS_TO_RETURN:
2050 res = "TLDAP_MORE_RESULTS_TO_RETURN";
2052 case TLDAP_CLIENT_LOOP:
2053 res = "TLDAP_CLIENT_LOOP";
2055 case TLDAP_REFERRAL_LIMIT_EXCEEDED:
2056 res = "TLDAP_REFERRAL_LIMIT_EXCEEDED";
2059 res = talloc_asprintf(talloc_tos(), "Unknown LDAP Error (%d)",
2064 res = "Unknown LDAP Error";