s3: Make TLDAP_IS_ALPHA and TLDAP_IS_ADH static functions
[bbaumbach/samba-autobuild/.git] / source3 / lib / tldap.c
1 /*
2    Unix SMB/CIFS implementation.
3    Infrastructure for async ldap client requests
4    Copyright (C) Volker Lendecke 2009
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21
22 bool tevent_req_is_ldap_error(struct tevent_req *req, int *perr)
23 {
24         enum tevent_req_state state;
25         uint64_t err;
26
27         if (!tevent_req_is_error(req, &state, &err)) {
28                 return false;
29         }
30         switch (state) {
31         case TEVENT_REQ_TIMED_OUT:
32                 *perr = TLDAP_TIMEOUT;
33                 break;
34         case TEVENT_REQ_NO_MEMORY:
35                 *perr = TLDAP_NO_MEMORY;
36                 break;
37         case TEVENT_REQ_USER_ERROR:
38                 *perr = err;
39                 break;
40         default:
41                 *perr = TLDAP_OPERATIONS_ERROR;
42                 break;
43         }
44         return true;
45 }
46
47 struct tldap_ctx_attribute {
48         char *name;
49         void *ptr;
50 };
51
52 struct tldap_context {
53         int ld_version;
54         int ld_deref;
55         int ld_sizelimit;
56         int ld_timelimit;
57         struct tstream_context *conn;
58         bool server_down;
59         int msgid;
60         struct tevent_queue *outgoing;
61         struct tevent_req **pending;
62
63         /* For the sync wrappers we need something like get_last_error... */
64         struct tldap_message *last_msg;
65
66         /* debug */
67         void (*log_fn)(void *context, enum tldap_debug_level level,
68                        const char *fmt, va_list ap);
69         void *log_private;
70
71         struct tldap_ctx_attribute *ctx_attrs;
72 };
73
74 struct tldap_message {
75         struct asn1_data *data;
76         uint8_t *inbuf;
77         int type;
78         int id;
79
80         /* RESULT_ENTRY */
81         char *dn;
82         struct tldap_attribute *attribs;
83
84         /* Error data sent by the server */
85         int lderr;
86         char *res_matcheddn;
87         char *res_diagnosticmessage;
88         char *res_referral;
89         struct tldap_control *res_sctrls;
90
91         /* Controls sent by the server */
92         struct tldap_control *ctrls;
93 };
94
95 void tldap_set_debug(struct tldap_context *ld,
96                      void (*log_fn)(void *log_private,
97                                     enum tldap_debug_level level,
98                                     const char *fmt,
99                                     va_list ap) PRINTF_ATTRIBUTE(3,0),
100                      void *log_private)
101 {
102         ld->log_fn = log_fn;
103         ld->log_private = log_private;
104 }
105
106 static void tldap_debug(struct tldap_context *ld,
107                          enum tldap_debug_level level,
108                          const char *fmt, ...)
109 {
110         va_list ap;
111         if (!ld) {
112                 return;
113         }
114         if (ld->log_fn == NULL) {
115                 return;
116         }
117         va_start(ap, fmt);
118         ld->log_fn(ld->log_private, level, fmt, ap);
119         va_end(ap);
120 }
121
122 static int tldap_next_msgid(struct tldap_context *ld)
123 {
124         int result;
125
126         result = ld->msgid++;
127         if (ld->msgid == 2147483647) {
128                 ld->msgid = 1;
129         }
130         return result;
131 }
132
133 struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
134 {
135         struct tldap_context *ctx;
136         int ret;
137
138         ctx = talloc_zero(mem_ctx, struct tldap_context);
139         if (ctx == NULL) {
140                 return NULL;
141         }
142         ret = tstream_bsd_existing_socket(ctx, fd, &ctx->conn);
143         if (ret == -1) {
144                 TALLOC_FREE(ctx);
145                 return NULL;
146         }
147         ctx->msgid = 1;
148         ctx->ld_version = 3;
149         ctx->outgoing = tevent_queue_create(ctx, "tldap_outgoing");
150         if (ctx->outgoing == NULL) {
151                 TALLOC_FREE(ctx);
152                 return NULL;
153         }
154         return ctx;
155 }
156
157 bool tldap_connection_ok(struct tldap_context *ld)
158 {
159         if (ld == NULL) {
160                 return false;
161         }
162         return !ld->server_down;
163 }
164
165 static struct tldap_ctx_attribute *tldap_context_findattr(
166         struct tldap_context *ld, const char *name)
167 {
168         int i, num_attrs;
169
170         num_attrs = talloc_array_length(ld->ctx_attrs);
171
172         for (i=0; i<num_attrs; i++) {
173                 if (strcmp(ld->ctx_attrs[i].name, name) == 0) {
174                         return &ld->ctx_attrs[i];
175                 }
176         }
177         return NULL;
178 }
179
180 bool tldap_context_setattr(struct tldap_context *ld,
181                            const char *name, const void *_pptr)
182 {
183         struct tldap_ctx_attribute *tmp, *attr;
184         char *tmpname;
185         int num_attrs;
186         void **pptr = (void **)_pptr;
187
188         attr = tldap_context_findattr(ld, name);
189         if (attr != NULL) {
190                 /*
191                  * We don't actually delete attrs, we don't expect tons of
192                  * attributes being shuffled around.
193                  */
194                 TALLOC_FREE(attr->ptr);
195                 if (*pptr != NULL) {
196                         attr->ptr = talloc_move(ld->ctx_attrs, pptr);
197                         *pptr = NULL;
198                 }
199                 return true;
200         }
201
202         tmpname = talloc_strdup(ld, name);
203         if (tmpname == NULL) {
204                 return false;
205         }
206
207         num_attrs = talloc_array_length(ld->ctx_attrs);
208
209         tmp = talloc_realloc(ld, ld->ctx_attrs, struct tldap_ctx_attribute,
210                              num_attrs+1);
211         if (tmp == NULL) {
212                 TALLOC_FREE(tmpname);
213                 return false;
214         }
215         tmp[num_attrs].name = talloc_move(tmp, &tmpname);
216         if (*pptr != NULL) {
217                 tmp[num_attrs].ptr = talloc_move(tmp, pptr);
218         } else {
219                 tmp[num_attrs].ptr = NULL;
220         }
221         *pptr = NULL;
222         ld->ctx_attrs = tmp;
223         return true;
224 }
225
226 void *tldap_context_getattr(struct tldap_context *ld, const char *name)
227 {
228         struct tldap_ctx_attribute *attr = tldap_context_findattr(ld, name);
229
230         if (attr == NULL) {
231                 return NULL;
232         }
233         return attr->ptr;
234 }
235
236 struct read_ldap_state {
237         uint8_t *buf;
238         bool done;
239 };
240
241 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data);
242 static void read_ldap_done(struct tevent_req *subreq);
243
244 static struct tevent_req *read_ldap_send(TALLOC_CTX *mem_ctx,
245                                          struct tevent_context *ev,
246                                          struct tstream_context *conn)
247 {
248         struct tevent_req *req, *subreq;
249         struct read_ldap_state *state;
250
251         req = tevent_req_create(mem_ctx, &state, struct read_ldap_state);
252         if (req == NULL) {
253                 return NULL;
254         }
255         state->done = false;
256
257         subreq = tstream_read_packet_send(state, ev, conn, 2, read_ldap_more,
258                                           state);
259         if (tevent_req_nomem(subreq, req)) {
260                 return tevent_req_post(req, ev);
261         }
262         tevent_req_set_callback(subreq, read_ldap_done, req);
263         return req;
264 }
265
266 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data)
267 {
268         struct read_ldap_state *state = talloc_get_type_abort(
269                 private_data, struct read_ldap_state);
270         size_t len;
271         int i, lensize;
272
273         if (state->done) {
274                 /* We've been here, we're done */
275                 return 0;
276         }
277
278         /*
279          * From ldap.h: LDAP_TAG_MESSAGE is 0x30
280          */
281         if (buf[0] != 0x30) {
282                 return -1;
283         }
284
285         len = buf[1];
286         if ((len & 0x80) == 0) {
287                 state->done = true;
288                 return len;
289         }
290
291         lensize = (len & 0x7f);
292         len = 0;
293
294         if (buflen == 2) {
295                 /* Please get us the full length */
296                 return lensize;
297         }
298         if (buflen > 2 + lensize) {
299                 state->done = true;
300                 return 0;
301         }
302         if (buflen != 2 + lensize) {
303                 return -1;
304         }
305
306         for (i=0; i<lensize; i++) {
307                 len = (len << 8) | buf[2+i];
308         }
309         return len;
310 }
311
312 static void read_ldap_done(struct tevent_req *subreq)
313 {
314         struct tevent_req *req = tevent_req_callback_data(
315                 subreq, struct tevent_req);
316         struct read_ldap_state *state = tevent_req_data(
317                 req, struct read_ldap_state);
318         ssize_t nread;
319         int err;
320
321         nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
322         TALLOC_FREE(subreq);
323         if (nread == -1) {
324                 tevent_req_error(req, err);
325                 return;
326         }
327         tevent_req_done(req);
328 }
329
330 static ssize_t read_ldap_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
331                               uint8_t **pbuf, int *perrno)
332 {
333         struct read_ldap_state *state = tevent_req_data(
334                 req, struct read_ldap_state);
335
336         if (tevent_req_is_unix_error(req, perrno)) {
337                 return -1;
338         }
339         *pbuf = talloc_move(mem_ctx, &state->buf);
340         return talloc_get_size(*pbuf);
341 }
342
343 struct tldap_msg_state {
344         struct tldap_context *ld;
345         struct tevent_context *ev;
346         int id;
347         struct iovec iov;
348
349         struct asn1_data *data;
350         uint8_t *inbuf;
351 };
352
353 static void tldap_push_controls(struct asn1_data *data,
354                                 struct tldap_control *sctrls,
355                                 int num_sctrls)
356 {
357         int i;
358
359         if ((sctrls == NULL) || (num_sctrls == 0)) {
360                 return;
361         }
362
363         asn1_push_tag(data, ASN1_CONTEXT(0));
364
365         for (i=0; i<num_sctrls; i++) {
366                 struct tldap_control *c = &sctrls[i];
367                 asn1_push_tag(data, ASN1_SEQUENCE(0));
368                 asn1_write_OctetString(data, c->oid, strlen(c->oid));
369                 if (c->critical) {
370                         asn1_write_BOOLEAN(data, true);
371                 }
372                 if (c->value.data != NULL) {
373                         asn1_write_OctetString(data, c->value.data,
374                                                c->value.length);
375                 }
376                 asn1_pop_tag(data); /* ASN1_SEQUENCE(0) */
377         }
378
379         asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
380 }
381
382 static void tldap_msg_sent(struct tevent_req *subreq);
383 static void tldap_msg_received(struct tevent_req *subreq);
384
385 static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
386                                          struct tevent_context *ev,
387                                          struct tldap_context *ld,
388                                          int id, struct asn1_data *data,
389                                          struct tldap_control *sctrls,
390                                          int num_sctrls)
391 {
392         struct tevent_req *req, *subreq;
393         struct tldap_msg_state *state;
394         DATA_BLOB blob;
395
396         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
397                     id);
398
399         req = tevent_req_create(mem_ctx, &state, struct tldap_msg_state);
400         if (req == NULL) {
401                 return NULL;
402         }
403         state->ld = ld;
404         state->ev = ev;
405         state->id = id;
406
407         if (state->ld->server_down) {
408                 tevent_req_error(req, TLDAP_SERVER_DOWN);
409                 return tevent_req_post(req, ev);
410         }
411
412         tldap_push_controls(data, sctrls, num_sctrls);
413
414         asn1_pop_tag(data);
415
416         if (!asn1_blob(data, &blob)) {
417                 tevent_req_error(req, TLDAP_ENCODING_ERROR);
418                 return tevent_req_post(req, ev);
419         }
420
421         state->iov.iov_base = blob.data;
422         state->iov.iov_len = blob.length;
423
424         subreq = tstream_writev_queue_send(state, ev, ld->conn, ld->outgoing,
425                                            &state->iov, 1);
426         if (tevent_req_nomem(subreq, req)) {
427                 return tevent_req_post(req, ev);
428         }
429         tevent_req_set_callback(subreq, tldap_msg_sent, req);
430         return req;
431 }
432
433 static void tldap_msg_unset_pending(struct tevent_req *req)
434 {
435         struct tldap_msg_state *state = tevent_req_data(
436                 req, struct tldap_msg_state);
437         struct tldap_context *ld = state->ld;
438         int num_pending = talloc_array_length(ld->pending);
439         int i;
440
441         if (num_pending == 1) {
442                 TALLOC_FREE(ld->pending);
443                 return;
444         }
445
446         for (i=0; i<num_pending; i++) {
447                 if (req == ld->pending[i]) {
448                         break;
449                 }
450         }
451         if (i == num_pending) {
452                 /*
453                  * Something's seriously broken. Just returning here is the
454                  * right thing nevertheless, the point of this routine is to
455                  * remove ourselves from cli->pending.
456                  */
457                 return;
458         }
459
460         /*
461          * Remove ourselves from the cli->pending array
462          */
463         if (num_pending > 1) {
464                 ld->pending[i] = ld->pending[num_pending-1];
465         }
466
467         /*
468          * No NULL check here, we're shrinking by sizeof(void *), and
469          * talloc_realloc just adjusts the size for this.
470          */
471         ld->pending = talloc_realloc(NULL, ld->pending, struct tevent_req *,
472                                      num_pending - 1);
473         return;
474 }
475
476 static int tldap_msg_destructor(struct tevent_req *req)
477 {
478         tldap_msg_unset_pending(req);
479         return 0;
480 }
481
482 static bool tldap_msg_set_pending(struct tevent_req *req)
483 {
484         struct tldap_msg_state *state = tevent_req_data(
485                 req, struct tldap_msg_state);
486         struct tldap_context *ld;
487         struct tevent_req **pending;
488         int num_pending;
489         struct tevent_req *subreq;
490
491         ld = state->ld;
492         num_pending = talloc_array_length(ld->pending);
493
494         pending = talloc_realloc(ld, ld->pending, struct tevent_req *,
495                                  num_pending+1);
496         if (pending == NULL) {
497                 return false;
498         }
499         pending[num_pending] = req;
500         ld->pending = pending;
501         talloc_set_destructor(req, tldap_msg_destructor);
502
503         if (num_pending > 0) {
504                 return true;
505         }
506
507         /*
508          * We're the first ones, add the read_ldap request that waits for the
509          * answer from the server
510          */
511         subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
512         if (subreq == NULL) {
513                 tldap_msg_unset_pending(req);
514                 return false;
515         }
516         tevent_req_set_callback(subreq, tldap_msg_received, ld);
517         return true;
518 }
519
520 static void tldap_msg_sent(struct tevent_req *subreq)
521 {
522         struct tevent_req *req = tevent_req_callback_data(
523                 subreq, struct tevent_req);
524         struct tldap_msg_state *state = tevent_req_data(
525                 req, struct tldap_msg_state);
526         ssize_t nwritten;
527         int err;
528
529         nwritten = tstream_writev_queue_recv(subreq, &err);
530         TALLOC_FREE(subreq);
531         if (nwritten == -1) {
532                 state->ld->server_down = true;
533                 tevent_req_error(req, TLDAP_SERVER_DOWN);
534                 return;
535         }
536
537         if (!tldap_msg_set_pending(req)) {
538                 tevent_req_nomem(NULL, req);
539                 return;
540         }
541 }
542
543 static int tldap_msg_msgid(struct tevent_req *req)
544 {
545         struct tldap_msg_state *state = tevent_req_data(
546                 req, struct tldap_msg_state);
547
548         return state->id;
549 }
550
551 static void tldap_msg_received(struct tevent_req *subreq)
552 {
553         struct tldap_context *ld = tevent_req_callback_data(
554                 subreq, struct tldap_context);
555         struct tevent_req *req;
556         struct tldap_msg_state *state;
557         struct tevent_context *ev;
558         struct asn1_data *data;
559         uint8_t *inbuf;
560         ssize_t received;
561         size_t num_pending;
562         int i, err, status;
563         int id;
564         uint8_t type;
565         bool ok;
566
567         received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
568         TALLOC_FREE(subreq);
569         if (received == -1) {
570                 status = TLDAP_SERVER_DOWN;
571                 goto fail;
572         }
573
574         data = asn1_init(talloc_tos());
575         if (data == NULL) {
576                 status = TLDAP_NO_MEMORY;
577                 goto fail;
578         }
579         asn1_load_nocopy(data, inbuf, received);
580
581         ok = true;
582         ok &= asn1_start_tag(data, ASN1_SEQUENCE(0));
583         ok &= asn1_read_Integer(data, &id);
584         ok &= asn1_peek_uint8(data, &type);
585
586         if (!ok) {
587                 status = TLDAP_PROTOCOL_ERROR;
588                 goto fail;
589         }
590
591         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
592                     "type %d\n", id, (int)type);
593
594         num_pending = talloc_array_length(ld->pending);
595
596         for (i=0; i<num_pending; i++) {
597                 if (id == tldap_msg_msgid(ld->pending[i])) {
598                         break;
599                 }
600         }
601         if (i == num_pending) {
602                 /* Dump unexpected reply */
603                 tldap_debug(ld, TLDAP_DEBUG_WARNING, "tldap_msg_received: "
604                             "No request pending for msg %d\n", id);
605                 TALLOC_FREE(data);
606                 TALLOC_FREE(inbuf);
607                 goto done;
608         }
609
610         req = ld->pending[i];
611         state = tevent_req_data(req, struct tldap_msg_state);
612
613         state->inbuf = talloc_move(state, &inbuf);
614         state->data = talloc_move(state, &data);
615
616         ev = state->ev;
617
618         talloc_set_destructor(req, NULL);
619         tldap_msg_unset_pending(req);
620         num_pending = talloc_array_length(ld->pending);
621
622         tevent_req_done(req);
623
624  done:
625         if (num_pending == 0) {
626                 return;
627         }
628         if (talloc_array_length(ld->pending) > num_pending) {
629                 /*
630                  * The callback functions called from tevent_req_done() above
631                  * have put something on the pending queue. We don't have to
632                  * trigger the read_ldap_send(), tldap_msg_set_pending() has
633                  * done it for us already.
634                  */
635                 return;
636         }
637
638         state = tevent_req_data(ld->pending[0], struct tldap_msg_state);
639         subreq = read_ldap_send(ld->pending, state->ev, ld->conn);
640         if (subreq == NULL) {
641                 status = TLDAP_NO_MEMORY;
642                 goto fail;
643         }
644         tevent_req_set_callback(subreq, tldap_msg_received, ld);
645         return;
646
647  fail:
648         while (talloc_array_length(ld->pending) > 0) {
649                 req = ld->pending[0];
650                 talloc_set_destructor(req, NULL);
651                 tldap_msg_destructor(req);
652                 tevent_req_error(req, status);
653         }
654 }
655
656 static int tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
657                           struct tldap_message **pmsg)
658 {
659         struct tldap_msg_state *state = tevent_req_data(
660                 req, struct tldap_msg_state);
661         struct tldap_message *msg;
662         int err;
663         uint8_t msgtype;
664
665         if (tevent_req_is_ldap_error(req, &err)) {
666                 return err;
667         }
668
669         if (!asn1_peek_uint8(state->data, &msgtype)) {
670                 return TLDAP_PROTOCOL_ERROR;
671         }
672
673         if (pmsg == NULL) {
674                 return TLDAP_SUCCESS;
675         }
676
677         msg = talloc_zero(mem_ctx, struct tldap_message);
678         if (msg == NULL) {
679                 return TLDAP_NO_MEMORY;
680         }
681         msg->id = state->id;
682
683         msg->inbuf = talloc_move(msg, &state->inbuf);
684         msg->data = talloc_move(msg, &state->data);
685         msg->type = msgtype;
686
687         *pmsg = msg;
688         return TLDAP_SUCCESS;
689 }
690
691 struct tldap_req_state {
692         int id;
693         struct asn1_data *out;
694         struct tldap_message *result;
695 };
696
697 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
698                                            struct tldap_context *ld,
699                                            struct tldap_req_state **pstate)
700 {
701         struct tevent_req *req;
702         struct tldap_req_state *state;
703
704         req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
705         if (req == NULL) {
706                 return NULL;
707         }
708         ZERO_STRUCTP(state);
709         state->out = asn1_init(state);
710         if (state->out == NULL) {
711                 TALLOC_FREE(req);
712                 return NULL;
713         }
714         state->result = NULL;
715         state->id = tldap_next_msgid(ld);
716
717         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
718         asn1_write_Integer(state->out, state->id);
719
720         *pstate = state;
721         return req;
722 }
723
724 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
725 {
726         struct tldap_req_state *state = tevent_req_data(
727                 req, struct tldap_req_state);
728
729         TALLOC_FREE(ld->last_msg);
730         ld->last_msg = talloc_move(ld, &state->result);
731 }
732
733 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
734 {
735         char *result = talloc_array(mem_ctx, char, blob.length+1);
736         memcpy(result, blob.data, blob.length);
737         result[blob.length] = '\0';
738         return result;
739 }
740
741 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
742                                          struct asn1_data *data,
743                                          char **result)
744 {
745         DATA_BLOB string;
746         if (!asn1_read_OctetString(data, mem_ctx, &string))
747                 return false;
748         *result = blob2string_talloc(mem_ctx, string);
749         data_blob_free(&string);
750         return true;
751 }
752
753 static bool tldap_decode_controls(struct tldap_req_state *state);
754
755 static bool tldap_decode_response(struct tldap_req_state *state)
756 {
757         struct asn1_data *data = state->result->data;
758         struct tldap_message *msg = state->result;
759         bool ok = true;
760
761         ok &= asn1_read_enumerated(data, &msg->lderr);
762         ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
763         ok &= asn1_read_OctetString_talloc(msg, data,
764                                            &msg->res_diagnosticmessage);
765         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
766                 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
767                 ok &= asn1_read_OctetString_talloc(msg, data,
768                                                    &msg->res_referral);
769                 ok &= asn1_end_tag(data);
770         } else {
771                 msg->res_referral = NULL;
772         }
773
774         return ok;
775 }
776
777 static void tldap_sasl_bind_done(struct tevent_req *subreq);
778
779 struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
780                                         struct tevent_context *ev,
781                                         struct tldap_context *ld,
782                                         const char *dn,
783                                         const char *mechanism,
784                                         DATA_BLOB *creds,
785                                         struct tldap_control *sctrls,
786                                         int num_sctrls,
787                                         struct tldap_control *cctrls,
788                                         int num_cctrls)
789 {
790         struct tevent_req *req, *subreq;
791         struct tldap_req_state *state;
792
793         req = tldap_req_create(mem_ctx, ld, &state);
794         if (req == NULL) {
795                 return NULL;
796         }
797
798         if (dn == NULL) {
799                 dn = "";
800         }
801
802         asn1_push_tag(state->out, TLDAP_REQ_BIND);
803         asn1_write_Integer(state->out, ld->ld_version);
804         asn1_write_OctetString(state->out, dn, (dn != NULL) ? strlen(dn) : 0);
805
806         if (mechanism == NULL) {
807                 asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0));
808                 asn1_write(state->out, creds->data, creds->length);
809                 asn1_pop_tag(state->out);
810         } else {
811                 asn1_push_tag(state->out, ASN1_CONTEXT(3));
812                 asn1_write_OctetString(state->out, mechanism,
813                                        strlen(mechanism));
814                 if ((creds != NULL) && (creds->data != NULL)) {
815                         asn1_write_OctetString(state->out, creds->data,
816                                                creds->length);
817                 }
818                 asn1_pop_tag(state->out);
819         }
820
821         if (!asn1_pop_tag(state->out)) {
822                 tevent_req_error(req, TLDAP_ENCODING_ERROR);
823                 return tevent_req_post(req, ev);
824         }
825
826         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
827                                 sctrls, num_sctrls);
828         if (tevent_req_nomem(subreq, req)) {
829                 return tevent_req_post(req, ev);
830         }
831         tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
832         return req;
833 }
834
835 static void tldap_sasl_bind_done(struct tevent_req *subreq)
836 {
837         struct tevent_req *req = tevent_req_callback_data(
838                 subreq, struct tevent_req);
839         struct tldap_req_state *state = tevent_req_data(
840                 req, struct tldap_req_state);
841         int err;
842
843         err = tldap_msg_recv(subreq, state, &state->result);
844         TALLOC_FREE(subreq);
845         if (err != TLDAP_SUCCESS) {
846                 tevent_req_error(req, err);
847                 return;
848         }
849         if (state->result->type != TLDAP_RES_BIND) {
850                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
851                 return;
852         }
853         if (!asn1_start_tag(state->result->data, state->result->type) ||
854             !tldap_decode_response(state) ||
855             !asn1_end_tag(state->result->data)) {
856                 tevent_req_error(req, TLDAP_DECODING_ERROR);
857                 return;
858         }
859         /*
860          * TODO: pull the reply blob
861          */
862         if (state->result->lderr != TLDAP_SUCCESS) {
863                 tevent_req_error(req, state->result->lderr);
864                 return;
865         }
866         tevent_req_done(req);
867 }
868
869 int tldap_sasl_bind_recv(struct tevent_req *req)
870 {
871         int err;
872
873         if (tevent_req_is_ldap_error(req, &err)) {
874                 return err;
875         }
876         return TLDAP_SUCCESS;
877 }
878
879 int tldap_sasl_bind(struct tldap_context *ld,
880                     const char *dn,
881                     const char *mechanism,
882                     DATA_BLOB *creds,
883                     struct tldap_control *sctrls,
884                     int num_sctrls,
885                     struct tldap_control *cctrls,
886                     int num_cctrls)
887 {
888         TALLOC_CTX *frame = talloc_stackframe();
889         struct tevent_context *ev;
890         struct tevent_req *req;
891         int result;
892
893         ev = event_context_init(frame);
894         if (ev == NULL) {
895                 result = TLDAP_NO_MEMORY;
896                 goto fail;
897         }
898
899         req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
900                                    sctrls, num_sctrls, cctrls, num_cctrls);
901         if (req == NULL) {
902                 result = TLDAP_NO_MEMORY;
903                 goto fail;
904         }
905
906         if (!tevent_req_poll(req, ev)) {
907                 result = TLDAP_OPERATIONS_ERROR;
908                 goto fail;
909         }
910
911         result = tldap_sasl_bind_recv(req);
912         tldap_save_msg(ld, req);
913  fail:
914         TALLOC_FREE(frame);
915         return result;
916 }
917
918 struct tevent_req *tldap_simple_bind_send(TALLOC_CTX *mem_ctx,
919                                           struct tevent_context *ev,
920                                           struct tldap_context *ld,
921                                           const char *dn,
922                                           const char *passwd)
923 {
924         DATA_BLOB cred;
925
926         if (passwd != NULL) {
927                 cred.data = (uint8_t *)passwd;
928                 cred.length = strlen(passwd);
929         } else {
930                 cred.data = (uint8_t *)"";
931                 cred.length = 0;
932         }
933         return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
934                                     NULL, 0);
935 }
936
937 int tldap_simple_bind_recv(struct tevent_req *req)
938 {
939         return tldap_sasl_bind_recv(req);
940 }
941
942 int tldap_simple_bind(struct tldap_context *ld, const char *dn,
943                       const char *passwd)
944 {
945         DATA_BLOB cred;
946
947         if (passwd != NULL) {
948                 cred.data = (uint8_t *)passwd;
949                 cred.length = strlen(passwd);
950         } else {
951                 cred.data = (uint8_t *)"";
952                 cred.length = 0;
953         }
954         return tldap_sasl_bind(ld, dn, NULL, &cred, NULL, 0, NULL, 0);
955 }
956
957 /*****************************************************************************/
958
959 /* can't use isalpha() as only a strict set is valid for LDAP */
960
961 static bool tldap_is_alpha(char c)
962 {
963         return (((c >= 'a') && (c <= 'z')) || \
964                 ((c >= 'A') && (c <= 'Z')));
965 }
966
967 static bool tldap_is_adh(char c)
968 {
969         return tldap_is_alpha(c) || isdigit(c) || (c == '-');
970 }
971
972 #define TLDAP_FILTER_AND  ASN1_CONTEXT(0)
973 #define TLDAP_FILTER_OR   ASN1_CONTEXT(1)
974 #define TLDAP_FILTER_NOT  ASN1_CONTEXT(2)
975 #define TLDAP_FILTER_EQ   ASN1_CONTEXT(3)
976 #define TLDAP_FILTER_SUB  ASN1_CONTEXT(4)
977 #define TLDAP_FILTER_LE   ASN1_CONTEXT(5)
978 #define TLDAP_FILTER_GE   ASN1_CONTEXT(6)
979 #define TLDAP_FILTER_PRES ASN1_CONTEXT_SIMPLE(7)
980 #define TLDAP_FILTER_APX  ASN1_CONTEXT(8)
981 #define TLDAP_FILTER_EXT  ASN1_CONTEXT(9)
982
983 #define TLDAP_SUB_INI ASN1_CONTEXT_SIMPLE(0)
984 #define TLDAP_SUB_ANY ASN1_CONTEXT_SIMPLE(1)
985 #define TLDAP_SUB_FIN ASN1_CONTEXT_SIMPLE(2)
986
987
988 /* oid's should be numerical only in theory,
989  * but apparently some broken servers may have alphanum aliases instead.
990  * Do like openldap libraries and allow alphanum aliases for oids, but
991  * do not allow Tagging options in that case.
992  */
993 static bool tldap_is_attrdesc(const char *s, int len, bool no_tagopts)
994 {
995         bool is_oid = false;
996         bool dot = false;
997         int i;
998
999         /* first char has stricter rules */
1000         if (isdigit(*s)) {
1001                 is_oid = true;
1002         } else if (!tldap_is_alpha(*s)) {
1003                 /* bad first char */
1004                 return false;
1005         }
1006
1007         for (i = 1; i < len; i++) {
1008
1009                 if (is_oid) {
1010                         if (isdigit(s[i])) {
1011                                 dot = false;
1012                                 continue;
1013                         }
1014                         if (s[i] == '.') {
1015                                 if (dot) {
1016                                         /* malformed */
1017                                         return false;
1018                                 }
1019                                 dot = true;
1020                                 continue;
1021                         }
1022                 } else {
1023                         if (tldap_is_adh(s[i])) {
1024                                 continue;
1025                         }
1026                 }
1027
1028                 if (s[i] == ';') {
1029                         if (no_tagopts) {
1030                                 /* no tagging options */
1031                                 return false;
1032                         }
1033                         if (dot) {
1034                                 /* malformed */
1035                                 return false;
1036                         }
1037                         if ((i + 1) == len) {
1038                                 /* malformed */
1039                                 return false;
1040                         }
1041
1042                         is_oid = false;
1043                         continue;
1044                 }
1045         }
1046
1047         if (dot) {
1048                 /* malformed */
1049                 return false;
1050         }
1051
1052         return true;
1053 }
1054
1055 /* this function copies the value until the closing parenthesis is found. */
1056 static char *tldap_get_val(TALLOC_CTX *memctx,
1057                            const char *value, const char **_s)
1058 {
1059         const char *s = value;
1060
1061         /* find terminator */
1062         while (*s) {
1063                 s = strchr(s, ')');
1064                 if (s && (*(s - 1) == '\\')) {
1065                         continue;
1066                 }
1067                 break;
1068         }
1069         if (!s || !(*s == ')')) {
1070                 /* malformed filter */
1071                 return NULL;
1072         }
1073
1074         *_s = s;
1075
1076         return talloc_strndup(memctx, value, s - value);
1077 }
1078
1079 static int tldap_hex2char(const char *x)
1080 {
1081         if (isxdigit(x[0]) && isxdigit(x[1])) {
1082                 const char h1 = x[0], h2 = x[1];
1083                 int c;
1084
1085                 if (h1 >= 'a') c = h1 - (int)'a' + 10;
1086                 else if (h1 >= 'A') c = h1 - (int)'A' + 10;
1087                 else if (h1 >= '0') c = h1 - (int)'0';
1088                 c = c << 4;
1089                 if (h2 >= 'a') c += h2 - (int)'a' + 10;
1090                 else if (h2 >= 'A') c += h2 - (int)'A' + 10;
1091                 else if (h2 >= '0') c += h2 - (int)'0';
1092
1093                 return c;
1094         }
1095
1096         return -1;
1097 }
1098
1099 static bool tldap_find_first_star(const char *val, const char **star)
1100 {
1101         const char *s;
1102
1103         for (s = val; *s; s++) {
1104                 switch (*s) {
1105                 case '\\':
1106                         if (isxdigit(s[1]) && isxdigit(s[2])) {
1107                                 s += 2;
1108                                 break;
1109                         }
1110                         /* not hex based escape, check older syntax */
1111                         switch (s[1]) {
1112                         case '(':
1113                         case ')':
1114                         case '*':
1115                         case '\\':
1116                                 s++;
1117                                 break;
1118                         default:
1119                                 /* invalid escape sequence */
1120                                 return false;
1121                         }
1122                         break;
1123                 case ')':
1124                         /* end of val, nothing found */
1125                         *star = s;
1126                         return true;
1127
1128                 case '*':
1129                         *star = s;
1130                         return true;
1131                 }
1132         }
1133
1134         /* string ended without closing parenthesis, filter is malformed */
1135         return false;
1136 }
1137
1138 static bool tldap_unescape_inplace(char *value, size_t *val_len)
1139 {
1140         int c, i, p;
1141
1142         for (i = 0,p = 0; i < *val_len; i++) {
1143
1144                 switch (value[i]) {
1145                 case '(':
1146                 case ')':
1147                 case '*':
1148                         /* these must be escaped */
1149                         return false;
1150
1151                 case '\\':
1152                         if (!value[i + 1]) {
1153                                 /* invalid EOL */
1154                                 return false;
1155                         }
1156                         i++;
1157
1158                         c = tldap_hex2char(&value[i]);
1159                         if (c >= 0 && c < 256) {
1160                                 value[p] = c;
1161                                 i++;
1162                                 p++;
1163                                 break;
1164                         }
1165
1166                         switch (value[i]) {
1167                         case '(':
1168                         case ')':
1169                         case '*':
1170                         case '\\':
1171                                 value[p] = value[i];
1172                                 p++;
1173                         default:
1174                                 /* invalid */
1175                                 return false;
1176                         }
1177                         break;
1178
1179                 default:
1180                         value[p] = value[i];
1181                         p++;
1182                 }
1183         }
1184         value[p] = '\0';
1185         *val_len = p;
1186         return true;
1187 }
1188
1189 static bool tldap_push_filter_basic(struct tldap_context *ld,
1190                                     struct asn1_data *data,
1191                                     const char **_s);
1192 static bool tldap_push_filter_substring(struct tldap_context *ld,
1193                                         struct asn1_data *data,
1194                                         const char *val,
1195                                         const char **_s);
1196 static bool tldap_push_filter_int(struct tldap_context *ld,
1197                                   struct asn1_data *data,
1198                                   const char **_s)
1199 {
1200         const char *s = *_s;
1201         bool ret;
1202
1203         if (*s != '(') {
1204                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1205                             "Incomplete or malformed filter\n");
1206                 return false;
1207         }
1208         s++;
1209
1210         /* we are right after a parenthesis,
1211          * find out what op we have at hand */
1212         switch (*s) {
1213         case '&':
1214                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: AND\n");
1215                 asn1_push_tag(data, TLDAP_FILTER_AND);
1216                 s++;
1217                 break;
1218
1219         case '|':
1220                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: OR\n");
1221                 asn1_push_tag(data, TLDAP_FILTER_OR);
1222                 s++;
1223                 break;
1224
1225         case '!':
1226                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: NOT\n");
1227                 asn1_push_tag(data, TLDAP_FILTER_NOT);
1228                 s++;
1229                 ret = tldap_push_filter_int(ld, data, &s);
1230                 if (!ret) {
1231                         return false;
1232                 }
1233                 asn1_pop_tag(data);
1234                 goto done;
1235
1236         case '(':
1237         case ')':
1238                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1239                             "Invalid parenthesis '%c'\n", *s);
1240                 return false;
1241
1242         case '\0':
1243                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1244                             "Invalid filter termination\n");
1245                 return false;
1246
1247         default:
1248                 ret = tldap_push_filter_basic(ld, data, &s);
1249                 if (!ret) {
1250                         return false;
1251                 }
1252                 goto done;
1253         }
1254
1255         /* only and/or filters get here.
1256          * go through the list of filters */
1257
1258         if (*s == ')') {
1259                 /* RFC 4526: empty and/or */
1260                 asn1_pop_tag(data);
1261                 goto done;
1262         }
1263
1264         while (*s) {
1265                 ret = tldap_push_filter_int(ld, data, &s);
1266                 if (!ret) {
1267                         return false;
1268                 }
1269
1270                 if (*s == ')') {
1271                         /* end of list, return */
1272                         asn1_pop_tag(data);
1273                         break;
1274                 }
1275         }
1276
1277 done:
1278         if (*s != ')') {
1279                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1280                             "Incomplete or malformed filter\n");
1281                 return false;
1282         }
1283         s++;
1284
1285         if (data->has_error) {
1286                 return false;
1287         }
1288
1289         *_s = s;
1290         return true;
1291 }
1292
1293
1294 static bool tldap_push_filter_basic(struct tldap_context *ld,
1295                                     struct asn1_data *data,
1296                                     const char **_s)
1297 {
1298         TALLOC_CTX *tmpctx = talloc_tos();
1299         const char *s = *_s;
1300         const char *e;
1301         const char *eq;
1302         const char *val;
1303         const char *type;
1304         const char *dn;
1305         const char *rule;
1306         const char *star;
1307         size_t type_len;
1308         char *uval;
1309         size_t uval_len;
1310         bool write_octect = true;
1311         bool ret;
1312
1313         eq = strchr(s, '=');
1314         if (!eq) {
1315                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1316                             "Invalid filter, missing equal sign\n");
1317                 return false;
1318         }
1319
1320         val = eq + 1;
1321         e = eq - 1;
1322
1323         switch (*e) {
1324         case '<':
1325                 asn1_push_tag(data, TLDAP_FILTER_LE);
1326                 break;
1327
1328         case '>':
1329                 asn1_push_tag(data, TLDAP_FILTER_GE);
1330                 break;
1331
1332         case '~':
1333                 asn1_push_tag(data, TLDAP_FILTER_APX);
1334                 break;
1335
1336         case ':':
1337                 asn1_push_tag(data, TLDAP_FILTER_EXT);
1338                 write_octect = false;
1339
1340                 type = NULL;
1341                 dn = NULL;
1342                 rule = NULL;
1343
1344                 if (*s == ':') { /* [:dn]:rule:= value */
1345                         if (s == e) {
1346                                 /* malformed filter */
1347                                 return false;
1348                         }
1349                         dn = s;
1350                 } else { /* type[:dn][:rule]:= value */
1351                         type = s;
1352                         dn = strchr(s, ':');
1353                         type_len = dn - type;
1354                         if (dn == e) { /* type:= value */
1355                                 dn = NULL;
1356                         }
1357                 }
1358                 if (dn) {
1359                         dn++;
1360
1361                         rule = strchr(dn, ':');
1362                         if ((rule == dn + 1) || rule + 1 == e) {
1363                                 /* malformed filter, contains "::" */
1364                                 return false;
1365                         }
1366
1367                         if (StrnCaseCmp(dn, "dn:", 3) != 0) {
1368                                 if (rule == e) {
1369                                         rule = dn;
1370                                         dn = NULL;
1371                                 } else {
1372                                         /* malformed filter. With two
1373                                          * optionals, the first must be "dn"
1374                                          */
1375                                         return false;
1376                                 }
1377                         } else {
1378                                 if (rule == e) {
1379                                         rule = NULL;
1380                                 } else {
1381                                         rule++;
1382                                 }
1383                         }
1384                 }
1385
1386                 if (!type && !dn && !rule) {
1387                         /* malformed filter, there must be at least one */
1388                         return false;
1389                 }
1390
1391                 /*
1392                   MatchingRuleAssertion ::= SEQUENCE {
1393                   matchingRule    [1] MatchingRuleID OPTIONAL,
1394                   type      [2] AttributeDescription OPTIONAL,
1395                   matchValue      [3] AssertionValue,
1396                   dnAttributes    [4] BOOLEAN DEFAULT FALSE
1397                   }
1398                 */
1399
1400                 /* check and add rule */
1401                 if (rule) {
1402                         ret = tldap_is_attrdesc(rule, e - rule, true);
1403                         if (!ret) {
1404                                 return false;
1405                         }
1406                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
1407                         asn1_write(data, rule, e - rule);
1408                         asn1_pop_tag(data);
1409                 }
1410
1411                 /* check and add type */
1412                 if (type) {
1413                         ret = tldap_is_attrdesc(type, type_len, false);
1414                         if (!ret) {
1415                                 return false;
1416                         }
1417                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
1418                         asn1_write(data, type, type_len);
1419                         asn1_pop_tag(data);
1420                 }
1421
1422                 uval = tldap_get_val(tmpctx, val, _s);
1423                 if (!uval) {
1424                         return false;
1425                 }
1426                 uval_len = *_s - val;
1427                 ret = tldap_unescape_inplace(uval, &uval_len);
1428                 if (!ret) {
1429                         return false;
1430                 }
1431
1432                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
1433                 asn1_write(data, uval, uval_len);
1434                 asn1_pop_tag(data);
1435
1436                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
1437                 asn1_write_uint8(data, dn?1:0);
1438                 asn1_pop_tag(data);
1439                 break;
1440
1441         default:
1442                 e = eq;
1443
1444                 ret = tldap_is_attrdesc(s, e - s, false);
1445                 if (!ret) {
1446                         return false;
1447                 }
1448
1449                 if (strncmp(val, "*)", 2) == 0) {
1450                         /* presence */
1451                         asn1_push_tag(data, TLDAP_FILTER_PRES);
1452                         asn1_write(data, s, e - s);
1453                         *_s = val + 1;
1454                         write_octect = false;
1455                         break;
1456                 }
1457
1458                 ret = tldap_find_first_star(val, &star);
1459                 if (!ret) {
1460                         return false;
1461                 }
1462                 if (*star == '*') {
1463                         /* substring */
1464                         asn1_push_tag(data, TLDAP_FILTER_SUB);
1465                         asn1_write_OctetString(data, s, e - s);
1466                         ret = tldap_push_filter_substring(ld, data, val, &s);
1467                         if (!ret) {
1468                                 return false;
1469                         }
1470                         *_s = s;
1471                         write_octect = false;
1472                         break;
1473                 }
1474
1475                 /* if nothing else, then it is just equality */
1476                 asn1_push_tag(data, TLDAP_FILTER_EQ);
1477                 write_octect = true;
1478                 break;
1479         }
1480
1481         if (write_octect) {
1482                 uval = tldap_get_val(tmpctx, val, _s);
1483                 if (!uval) {
1484                         return false;
1485                 }
1486                 uval_len = *_s - val;
1487                 ret = tldap_unescape_inplace(uval, &uval_len);
1488                 if (!ret) {
1489                         return false;
1490                 }
1491
1492                 asn1_write_OctetString(data, s, e - s);
1493                 asn1_write_OctetString(data, uval, uval_len);
1494         }
1495
1496         if (data->has_error) {
1497                 return false;
1498         }
1499         asn1_pop_tag(data);
1500         return true;
1501 }
1502
1503 static bool tldap_push_filter_substring(struct tldap_context *ld,
1504                                         struct asn1_data *data,
1505                                         const char *val,
1506                                         const char **_s)
1507 {
1508         TALLOC_CTX *tmpctx = talloc_tos();
1509         bool initial = true;
1510         const char *star;
1511         char *chunk;
1512         size_t chunk_len;
1513         bool ret;
1514
1515         /*
1516           SubstringFilter ::= SEQUENCE {
1517                   type      AttributeDescription,
1518                   -- at least one must be present
1519                   substrings      SEQUENCE OF CHOICE {
1520                           initial [0] LDAPString,
1521                           any     [1] LDAPString,
1522                           final   [2] LDAPString } }
1523         */
1524         asn1_push_tag(data, ASN1_SEQUENCE(0));
1525
1526         do {
1527                 ret = tldap_find_first_star(val, &star);
1528                 if (!ret) {
1529                         return false;
1530                 }
1531                 chunk_len = star - val;
1532
1533                 switch (*star) {
1534                 case '*':
1535                         if (!initial && chunk_len == 0) {
1536                                 /* found '**', which is illegal */
1537                                 return false;
1538                         }
1539                         break;
1540                 case ')':
1541                         if (initial) {
1542                                 /* no stars ?? */
1543                                 return false;
1544                         }
1545                         /* we are done */
1546                         break;
1547                 default:
1548                         /* ?? */
1549                         return false;
1550                 }
1551
1552                 if (initial && chunk_len == 0) {
1553                         val = star + 1;
1554                         initial = false;
1555                         continue;
1556                 }
1557
1558                 chunk = talloc_strndup(tmpctx, val, chunk_len);
1559                 if (!chunk) {
1560                         return false;
1561                 }
1562                 ret = tldap_unescape_inplace(chunk, &chunk_len);
1563                 if (!ret) {
1564                         return false;
1565                 }
1566                 switch (*star) {
1567                 case '*':
1568                         if (initial) {
1569                                 asn1_push_tag(data, TLDAP_SUB_INI);
1570                                 initial = false;
1571                         } else {
1572                                 asn1_push_tag(data, TLDAP_SUB_ANY);
1573                         }
1574                         break;
1575                 case ')':
1576                         asn1_push_tag(data, TLDAP_SUB_FIN);
1577                         break;
1578                 default:
1579                         /* ?? */
1580                         return false;
1581                 }
1582                 asn1_write(data, chunk, chunk_len);
1583                 asn1_pop_tag(data);
1584
1585                 val = star + 1;
1586
1587         } while (*star == '*');
1588
1589         *_s = star;
1590
1591         /* end of sequence */
1592         asn1_pop_tag(data);
1593         return true;
1594 }
1595
1596 /* NOTE: although openldap libraries allow for spaces in some places, mosly
1597  * around parenthesis, we do not allow any spaces (except in values of
1598  * course) as I couldn't fine any place in RFC 4512 or RFC 4515 where
1599  * leading or trailing spaces where allowed.
1600  */
1601 static bool tldap_push_filter(struct tldap_context *ld,
1602                               struct asn1_data *data,
1603                               const char *filter)
1604 {
1605         const char *s = filter;
1606         bool ret;
1607
1608         ret = tldap_push_filter_int(ld, data, &s);
1609         if (ret && *s) {
1610                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1611                             "Incomplete or malformed filter\n");
1612                 return false;
1613         }
1614         return ret;
1615 }
1616
1617 /*****************************************************************************/
1618
1619 static void tldap_search_done(struct tevent_req *subreq);
1620
1621 struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
1622                                      struct tevent_context *ev,
1623                                      struct tldap_context *ld,
1624                                      const char *base, int scope,
1625                                      const char *filter,
1626                                      const char **attrs,
1627                                      int num_attrs,
1628                                      int attrsonly,
1629                                      struct tldap_control *sctrls,
1630                                      int num_sctrls,
1631                                      struct tldap_control *cctrls,
1632                                      int num_cctrls,
1633                                      int timelimit,
1634                                      int sizelimit,
1635                                      int deref)
1636 {
1637         struct tevent_req *req, *subreq;
1638         struct tldap_req_state *state;
1639         int i;
1640
1641         req = tldap_req_create(mem_ctx, ld, &state);
1642         if (req == NULL) {
1643                 return NULL;
1644         }
1645
1646         asn1_push_tag(state->out, TLDAP_REQ_SEARCH);
1647         asn1_write_OctetString(state->out, base, strlen(base));
1648         asn1_write_enumerated(state->out, scope);
1649         asn1_write_enumerated(state->out, deref);
1650         asn1_write_Integer(state->out, sizelimit);
1651         asn1_write_Integer(state->out, timelimit);
1652         asn1_write_BOOLEAN(state->out, attrsonly);
1653
1654         if (!tldap_push_filter(ld, state->out, filter)) {
1655                 goto encoding_error;
1656         }
1657
1658         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1659         for (i=0; i<num_attrs; i++) {
1660                 asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]));
1661         }
1662         asn1_pop_tag(state->out);
1663         asn1_pop_tag(state->out);
1664
1665         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1666                                 sctrls, num_sctrls);
1667         if (tevent_req_nomem(subreq, req)) {
1668                 return tevent_req_post(req, ev);
1669         }
1670         tevent_req_set_callback(subreq, tldap_search_done, req);
1671         return req;
1672
1673  encoding_error:
1674         tevent_req_error(req, TLDAP_ENCODING_ERROR);
1675         return tevent_req_post(req, ev);
1676 }
1677
1678 static void tldap_search_done(struct tevent_req *subreq)
1679 {
1680         struct tevent_req *req = tevent_req_callback_data(
1681                 subreq, struct tevent_req);
1682         struct tldap_req_state *state = tevent_req_data(
1683                 req, struct tldap_req_state);
1684         int err;
1685
1686         err = tldap_msg_recv(subreq, state, &state->result);
1687         if (err != TLDAP_SUCCESS) {
1688                 tevent_req_error(req, err);
1689                 return;
1690         }
1691         switch (state->result->type) {
1692         case TLDAP_RES_SEARCH_ENTRY:
1693         case TLDAP_RES_SEARCH_REFERENCE:
1694                 tevent_req_notify_callback(req);
1695                 if (!tldap_msg_set_pending(subreq)) {
1696                         tevent_req_nomem(NULL, req);
1697                         return;
1698                 }
1699                 break;
1700         case TLDAP_RES_SEARCH_RESULT:
1701                 TALLOC_FREE(subreq);
1702                 if (!asn1_start_tag(state->result->data,
1703                                     state->result->type) ||
1704                     !tldap_decode_response(state) ||
1705                     !asn1_end_tag(state->result->data) ||
1706                     !tldap_decode_controls(state)) {
1707                         tevent_req_error(req, TLDAP_DECODING_ERROR);
1708                         return;
1709                 }
1710                 tevent_req_done(req);
1711                 break;
1712         default:
1713                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1714                 return;
1715         }
1716 }
1717
1718 int tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1719                       struct tldap_message **pmsg)
1720 {
1721         struct tldap_req_state *state = tevent_req_data(
1722                 req, struct tldap_req_state);
1723         int err;
1724
1725         if (!tevent_req_is_in_progress(req)
1726             && tevent_req_is_ldap_error(req, &err)) {
1727                 return err;
1728         }
1729
1730         if (tevent_req_is_in_progress(req)) {
1731                 switch (state->result->type) {
1732                 case TLDAP_RES_SEARCH_ENTRY:
1733                 case TLDAP_RES_SEARCH_REFERENCE:
1734                         break;
1735                 default:
1736                         return TLDAP_OPERATIONS_ERROR;
1737                 }
1738         }
1739
1740         *pmsg = talloc_move(mem_ctx, &state->result);
1741         return TLDAP_SUCCESS;
1742 }
1743
1744 struct tldap_sync_search_state {
1745         TALLOC_CTX *mem_ctx;
1746         struct tldap_message **entries;
1747         struct tldap_message **refs;
1748         int rc;
1749 };
1750
1751 static void tldap_search_cb(struct tevent_req *req)
1752 {
1753         struct tldap_sync_search_state *state =
1754                 (struct tldap_sync_search_state *)
1755                 tevent_req_callback_data_void(req);
1756         struct tldap_message *msg, **tmp;
1757         int rc, num_entries, num_refs;
1758
1759         rc = tldap_search_recv(req, talloc_tos(), &msg);
1760         if (rc != TLDAP_SUCCESS) {
1761                 state->rc = rc;
1762                 return;
1763         }
1764
1765         switch (tldap_msg_type(msg)) {
1766         case TLDAP_RES_SEARCH_ENTRY:
1767                 num_entries = talloc_array_length(state->entries);
1768                 tmp = talloc_realloc(state->mem_ctx, state->entries,
1769                                      struct tldap_message *, num_entries + 1);
1770                 if (tmp == NULL) {
1771                         state->rc = TLDAP_NO_MEMORY;
1772                         return;
1773                 }
1774                 state->entries = tmp;
1775                 state->entries[num_entries] = talloc_move(state->entries,
1776                                                           &msg);
1777                 break;
1778         case TLDAP_RES_SEARCH_REFERENCE:
1779                 num_refs = talloc_array_length(state->refs);
1780                 tmp = talloc_realloc(state->mem_ctx, state->refs,
1781                                      struct tldap_message *, num_refs + 1);
1782                 if (tmp == NULL) {
1783                         state->rc = TLDAP_NO_MEMORY;
1784                         return;
1785                 }
1786                 state->refs = tmp;
1787                 state->refs[num_refs] = talloc_move(state->refs, &msg);
1788                 break;
1789         case TLDAP_RES_SEARCH_RESULT:
1790                 state->rc = TLDAP_SUCCESS;
1791                 break;
1792         default:
1793                 state->rc = TLDAP_PROTOCOL_ERROR;
1794                 break;
1795         }
1796 }
1797
1798 int tldap_search(struct tldap_context *ld,
1799                  const char *base, int scope, const char *filter,
1800                  const char **attrs, int num_attrs, int attrsonly,
1801                  struct tldap_control *sctrls, int num_sctrls,
1802                  struct tldap_control *cctrls, int num_cctrls,
1803                  int timelimit, int sizelimit, int deref,
1804                  TALLOC_CTX *mem_ctx, struct tldap_message ***entries,
1805                  struct tldap_message ***refs)
1806 {
1807         TALLOC_CTX *frame = talloc_stackframe();
1808         struct tevent_context *ev;
1809         struct tevent_req *req;
1810         struct tldap_sync_search_state state;
1811
1812         ZERO_STRUCT(state);
1813         state.mem_ctx = mem_ctx;
1814         state.rc = TLDAP_SUCCESS;
1815
1816         ev = event_context_init(frame);
1817         if (ev == NULL) {
1818                 state.rc = TLDAP_NO_MEMORY;
1819                 goto fail;
1820         }
1821
1822         req = tldap_search_send(frame, ev, ld, base, scope, filter,
1823                                 attrs, num_attrs, attrsonly,
1824                                 sctrls, num_sctrls, cctrls, num_cctrls,
1825                                 timelimit, sizelimit, deref);
1826         if (req == NULL) {
1827                 state.rc = TLDAP_NO_MEMORY;
1828                 goto fail;
1829         }
1830
1831         tevent_req_set_callback(req, tldap_search_cb, &state);
1832
1833         if (!tevent_req_is_in_progress(req)) {
1834                 /* an error happend before sending */
1835                 if (tevent_req_is_ldap_error(req, &state.rc)) {
1836                         goto fail;
1837                 }
1838         }
1839
1840         while (tevent_req_is_in_progress(req)
1841                && (state.rc == TLDAP_SUCCESS)) {
1842                 if (tevent_loop_once(ev) == -1) {
1843                         return TLDAP_OPERATIONS_ERROR;
1844                 }
1845         }
1846
1847         if (state.rc != TLDAP_SUCCESS) {
1848                 return state.rc;
1849         }
1850
1851         if (entries != NULL) {
1852                 *entries = state.entries;
1853         } else {
1854                 TALLOC_FREE(state.entries);
1855         }
1856         if (refs != NULL) {
1857                 *refs = state.refs;
1858         } else {
1859                 TALLOC_FREE(state.refs);
1860         }
1861         tldap_save_msg(ld, req);
1862 fail:
1863         TALLOC_FREE(frame);
1864         return state.rc;
1865 }
1866
1867 static bool tldap_parse_search_entry(struct tldap_message *msg)
1868 {
1869         int num_attribs = 0;
1870
1871         asn1_start_tag(msg->data, msg->type);
1872
1873         /* dn */
1874
1875         asn1_read_OctetString_talloc(msg, msg->data, &msg->dn);
1876         if (msg->dn == NULL) {
1877                 return false;
1878         }
1879
1880         /*
1881          * Attributes: We overallocate msg->attribs by one, so that while
1882          * looping over the attributes we can directly parse into the last
1883          * array element. Same for the values in the inner loop.
1884          */
1885
1886         msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
1887         if (msg->attribs == NULL) {
1888                 return false;
1889         }
1890
1891         asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1892         while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
1893                 struct tldap_attribute *attrib;
1894                 int num_values = 0;
1895
1896                 attrib = &msg->attribs[num_attribs];
1897                 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
1898                 if (attrib->values == NULL) {
1899                         return false;
1900                 }
1901                 asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1902                 asn1_read_OctetString_talloc(msg->attribs, msg->data,
1903                                              &attrib->name);
1904                 asn1_start_tag(msg->data, ASN1_SET);
1905
1906                 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
1907                         asn1_read_OctetString(msg->data, msg,
1908                                               &attrib->values[num_values]);
1909
1910                         attrib->values = talloc_realloc(
1911                                 msg->attribs, attrib->values, DATA_BLOB,
1912                                 num_values + 2);
1913                         if (attrib->values == NULL) {
1914                                 return false;
1915                         }
1916                         num_values += 1;
1917                 }
1918                 attrib->values = talloc_realloc(msg->attribs, attrib->values,
1919                                                 DATA_BLOB, num_values);
1920                 attrib->num_values = num_values;
1921
1922                 asn1_end_tag(msg->data); /* ASN1_SET */
1923                 asn1_end_tag(msg->data); /* ASN1_SEQUENCE(0) */
1924                 msg->attribs = talloc_realloc(
1925                         msg, msg->attribs, struct tldap_attribute,
1926                         num_attribs + 2);
1927                 if (msg->attribs == NULL) {
1928                         return false;
1929                 }
1930                 num_attribs += 1;
1931         }
1932         msg->attribs = talloc_realloc(
1933                 msg, msg->attribs, struct tldap_attribute, num_attribs);
1934         asn1_end_tag(msg->data);
1935         if (msg->data->has_error) {
1936                 return false;
1937         }
1938         return true;
1939 }
1940
1941 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
1942 {
1943         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1944                 return false;
1945         }
1946         *dn = msg->dn;
1947         return true;
1948 }
1949
1950 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
1951                             struct tldap_attribute **attributes)
1952 {
1953         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1954                 return false;
1955         }
1956         *attributes = msg->attribs;
1957         *num_attributes = talloc_array_length(msg->attribs);
1958         return true;
1959 }
1960
1961 static bool tldap_decode_controls(struct tldap_req_state *state)
1962 {
1963         struct tldap_message *msg = state->result;
1964         struct asn1_data *data = msg->data;
1965         struct tldap_control *sctrls = NULL;
1966         int num_controls = 0;
1967
1968         msg->res_sctrls = NULL;
1969
1970         if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1971                 return true;
1972         }
1973
1974         asn1_start_tag(data, ASN1_CONTEXT(0));
1975
1976         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1977                 struct tldap_control *c;
1978                 char *oid = NULL;
1979
1980                 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
1981                                         num_controls + 1);
1982                 if (sctrls == NULL) {
1983                         return false;
1984                 }
1985                 c = &sctrls[num_controls];
1986
1987                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1988                 asn1_read_OctetString_talloc(msg, data, &oid);
1989                 if ((data->has_error) || (oid == NULL)) {
1990                         return false;
1991                 }
1992                 c->oid = oid;
1993                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1994                         asn1_read_BOOLEAN(data, &c->critical);
1995                 } else {
1996                         c->critical = false;
1997                 }
1998                 c->value = data_blob_null;
1999                 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
2000                     !asn1_read_OctetString(data, msg, &c->value)) {
2001                         return false;
2002                 }
2003                 asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
2004
2005                 num_controls += 1;
2006         }
2007
2008         asn1_end_tag(data);     /* ASN1_CONTEXT(0) */
2009
2010         if (data->has_error) {
2011                 TALLOC_FREE(sctrls);
2012                 return false;
2013         }
2014         msg->res_sctrls = sctrls;
2015         return true;
2016 }
2017
2018 static void tldap_simple_done(struct tevent_req *subreq, int type)
2019 {
2020         struct tevent_req *req = tevent_req_callback_data(
2021                 subreq, struct tevent_req);
2022         struct tldap_req_state *state = tevent_req_data(
2023                 req, struct tldap_req_state);
2024         int err;
2025
2026         err = tldap_msg_recv(subreq, state, &state->result);
2027         TALLOC_FREE(subreq);
2028         if (err != TLDAP_SUCCESS) {
2029                 tevent_req_error(req, err);
2030                 return;
2031         }
2032         if (state->result->type != type) {
2033                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
2034                 return;
2035         }
2036         if (!asn1_start_tag(state->result->data, state->result->type) ||
2037             !tldap_decode_response(state) ||
2038             !asn1_end_tag(state->result->data) ||
2039             !tldap_decode_controls(state)) {
2040                 tevent_req_error(req, TLDAP_DECODING_ERROR);
2041                 return;
2042         }
2043         if (state->result->lderr != TLDAP_SUCCESS) {
2044                 tevent_req_error(req, state->result->lderr);
2045                 return;
2046         }
2047         tevent_req_done(req);
2048 }
2049
2050 static int tldap_simple_recv(struct tevent_req *req)
2051 {
2052         int err;
2053         if (tevent_req_is_ldap_error(req, &err)) {
2054                 return err;
2055         }
2056         return TLDAP_SUCCESS;
2057 }
2058
2059 static void tldap_add_done(struct tevent_req *subreq);
2060
2061 struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
2062                                   struct tevent_context *ev,
2063                                   struct tldap_context *ld,
2064                                   const char *dn,
2065                                   struct tldap_mod *attributes,
2066                                   int num_attributes,
2067                                   struct tldap_control *sctrls,
2068                                   int num_sctrls,
2069                                   struct tldap_control *cctrls,
2070                                   int num_cctrls)
2071 {
2072         struct tevent_req *req, *subreq;
2073         struct tldap_req_state *state;
2074         int i, j;
2075
2076         req = tldap_req_create(mem_ctx, ld, &state);
2077         if (req == NULL) {
2078                 return NULL;
2079         }
2080
2081         asn1_push_tag(state->out, TLDAP_REQ_ADD);
2082         asn1_write_OctetString(state->out, dn, strlen(dn));
2083         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
2084
2085         for (i=0; i<num_attributes; i++) {
2086                 struct tldap_mod *attrib = &attributes[i];
2087                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
2088                 asn1_write_OctetString(state->out, attrib->attribute,
2089                                        strlen(attrib->attribute));
2090                 asn1_push_tag(state->out, ASN1_SET);
2091                 for (j=0; j<attrib->num_values; j++) {
2092                         asn1_write_OctetString(state->out,
2093                                                attrib->values[j].data,
2094                                                attrib->values[j].length);
2095                 }
2096                 asn1_pop_tag(state->out);
2097                 asn1_pop_tag(state->out);
2098         }
2099
2100         asn1_pop_tag(state->out);
2101         asn1_pop_tag(state->out);
2102
2103         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2104                                 sctrls, num_sctrls);
2105         if (tevent_req_nomem(subreq, req)) {
2106                 return tevent_req_post(req, ev);
2107         }
2108         tevent_req_set_callback(subreq, tldap_add_done, req);
2109         return req;
2110 }
2111
2112 static void tldap_add_done(struct tevent_req *subreq)
2113 {
2114         tldap_simple_done(subreq, TLDAP_RES_ADD);
2115 }
2116
2117 int tldap_add_recv(struct tevent_req *req)
2118 {
2119         return tldap_simple_recv(req);
2120 }
2121
2122 int tldap_add(struct tldap_context *ld, const char *dn,
2123               int num_attributes, struct tldap_mod *attributes,
2124               struct tldap_control *sctrls, int num_sctrls,
2125               struct tldap_control *cctrls, int num_cctrls)
2126 {
2127         TALLOC_CTX *frame = talloc_stackframe();
2128         struct tevent_context *ev;
2129         struct tevent_req *req;
2130         int result;
2131
2132         ev = event_context_init(frame);
2133         if (ev == NULL) {
2134                 result = TLDAP_NO_MEMORY;
2135                 goto fail;
2136         }
2137
2138         req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
2139                              sctrls, num_sctrls, cctrls, num_cctrls);
2140         if (req == NULL) {
2141                 result = TLDAP_NO_MEMORY;
2142                 goto fail;
2143         }
2144
2145         if (!tevent_req_poll(req, ev)) {
2146                 result = TLDAP_OPERATIONS_ERROR;
2147                 goto fail;
2148         }
2149
2150         result = tldap_add_recv(req);
2151         tldap_save_msg(ld, req);
2152  fail:
2153         TALLOC_FREE(frame);
2154         return result;
2155 }
2156
2157 static void tldap_modify_done(struct tevent_req *subreq);
2158
2159 struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
2160                                      struct tevent_context *ev,
2161                                      struct tldap_context *ld,
2162                                      const char *dn,
2163                                      int num_mods, struct tldap_mod *mods,
2164                                      struct tldap_control *sctrls,
2165                                      int num_sctrls,
2166                                      struct tldap_control *cctrls,
2167                                      int num_cctrls)
2168 {
2169         struct tevent_req *req, *subreq;
2170         struct tldap_req_state *state;
2171         int i, j;
2172
2173         req = tldap_req_create(mem_ctx, ld, &state);
2174         if (req == NULL) {
2175                 return NULL;
2176         }
2177
2178         asn1_push_tag(state->out, TLDAP_REQ_MODIFY);
2179         asn1_write_OctetString(state->out, dn, strlen(dn));
2180         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
2181
2182         for (i=0; i<num_mods; i++) {
2183                 struct tldap_mod *mod = &mods[i];
2184                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
2185                 asn1_write_enumerated(state->out, mod->mod_op),
2186                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
2187                 asn1_write_OctetString(state->out, mod->attribute,
2188                                        strlen(mod->attribute));
2189                 asn1_push_tag(state->out, ASN1_SET);
2190                 for (j=0; j<mod->num_values; j++) {
2191                         asn1_write_OctetString(state->out,
2192                                                mod->values[j].data,
2193                                                mod->values[j].length);
2194                 }
2195                 asn1_pop_tag(state->out);
2196                 asn1_pop_tag(state->out);
2197                 asn1_pop_tag(state->out);
2198         }
2199
2200         asn1_pop_tag(state->out);
2201         asn1_pop_tag(state->out);
2202
2203         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2204                                 sctrls, num_sctrls);
2205         if (tevent_req_nomem(subreq, req)) {
2206                 return tevent_req_post(req, ev);
2207         }
2208         tevent_req_set_callback(subreq, tldap_modify_done, req);
2209         return req;
2210 }
2211
2212 static void tldap_modify_done(struct tevent_req *subreq)
2213 {
2214         tldap_simple_done(subreq, TLDAP_RES_MODIFY);
2215 }
2216
2217 int tldap_modify_recv(struct tevent_req *req)
2218 {
2219         return tldap_simple_recv(req);
2220 }
2221
2222 int tldap_modify(struct tldap_context *ld, const char *dn,
2223                  int num_mods, struct tldap_mod *mods,
2224                  struct tldap_control *sctrls, int num_sctrls,
2225                  struct tldap_control *cctrls, int num_cctrls)
2226  {
2227         TALLOC_CTX *frame = talloc_stackframe();
2228         struct tevent_context *ev;
2229         struct tevent_req *req;
2230         int result;
2231
2232         ev = event_context_init(frame);
2233         if (ev == NULL) {
2234                 result = TLDAP_NO_MEMORY;
2235                 goto fail;
2236         }
2237
2238         req = tldap_modify_send(frame, ev, ld, dn, num_mods, mods,
2239                                 sctrls, num_sctrls, cctrls, num_cctrls);
2240         if (req == NULL) {
2241                 result = TLDAP_NO_MEMORY;
2242                 goto fail;
2243         }
2244
2245         if (!tevent_req_poll(req, ev)) {
2246                 result = TLDAP_OPERATIONS_ERROR;
2247                 goto fail;
2248         }
2249
2250         result = tldap_modify_recv(req);
2251         tldap_save_msg(ld, req);
2252  fail:
2253         TALLOC_FREE(frame);
2254         return result;
2255 }
2256
2257 static void tldap_delete_done(struct tevent_req *subreq);
2258
2259 struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
2260                                      struct tevent_context *ev,
2261                                      struct tldap_context *ld,
2262                                      const char *dn,
2263                                      struct tldap_control *sctrls,
2264                                      int num_sctrls,
2265                                      struct tldap_control *cctrls,
2266                                      int num_cctrls)
2267 {
2268         struct tevent_req *req, *subreq;
2269         struct tldap_req_state *state;
2270
2271         req = tldap_req_create(mem_ctx, ld, &state);
2272         if (req == NULL) {
2273                 return NULL;
2274         }
2275
2276         asn1_push_tag(state->out, TLDAP_REQ_DELETE);
2277         asn1_write(state->out, dn, strlen(dn));
2278         asn1_pop_tag(state->out);
2279
2280         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2281                                 sctrls, num_sctrls);
2282         if (tevent_req_nomem(subreq, req)) {
2283                 return tevent_req_post(req, ev);
2284         }
2285         tevent_req_set_callback(subreq, tldap_delete_done, req);
2286         return req;
2287 }
2288
2289 static void tldap_delete_done(struct tevent_req *subreq)
2290 {
2291         tldap_simple_done(subreq, TLDAP_RES_DELETE);
2292 }
2293
2294 int tldap_delete_recv(struct tevent_req *req)
2295 {
2296         return tldap_simple_recv(req);
2297 }
2298
2299 int tldap_delete(struct tldap_context *ld, const char *dn,
2300                  struct tldap_control *sctrls, int num_sctrls,
2301                  struct tldap_control *cctrls, int num_cctrls)
2302 {
2303         TALLOC_CTX *frame = talloc_stackframe();
2304         struct tevent_context *ev;
2305         struct tevent_req *req;
2306         int result;
2307
2308         ev = event_context_init(frame);
2309         if (ev == NULL) {
2310                 result = TLDAP_NO_MEMORY;
2311                 goto fail;
2312         }
2313
2314         req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
2315                                 cctrls, num_cctrls);
2316         if (req == NULL) {
2317                 result = TLDAP_NO_MEMORY;
2318                 goto fail;
2319         }
2320
2321         if (!tevent_req_poll(req, ev)) {
2322                 result = TLDAP_OPERATIONS_ERROR;
2323                 goto fail;
2324         }
2325
2326         result = tldap_delete_recv(req);
2327         tldap_save_msg(ld, req);
2328  fail:
2329         TALLOC_FREE(frame);
2330         return result;
2331 }
2332
2333 int tldap_msg_id(const struct tldap_message *msg)
2334 {
2335         return msg->id;
2336 }
2337
2338 int tldap_msg_type(const struct tldap_message *msg)
2339 {
2340         return msg->type;
2341 }
2342
2343 const char *tldap_msg_matcheddn(struct tldap_message *msg)
2344 {
2345         if (msg == NULL) {
2346                 return NULL;
2347         }
2348         return msg->res_matcheddn;
2349 }
2350
2351 const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
2352 {
2353         if (msg == NULL) {
2354                 return NULL;
2355         }
2356         return msg->res_diagnosticmessage;
2357 }
2358
2359 const char *tldap_msg_referral(struct tldap_message *msg)
2360 {
2361         if (msg == NULL) {
2362                 return NULL;
2363         }
2364         return msg->res_referral;
2365 }
2366
2367 void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
2368                       struct tldap_control **sctrls)
2369 {
2370         if (msg == NULL) {
2371                 *sctrls = NULL;
2372                 *num_sctrls = 0;
2373         }
2374         *sctrls = msg->res_sctrls;
2375         *num_sctrls = talloc_array_length(msg->res_sctrls);
2376 }
2377
2378 struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
2379 {
2380         return ld->last_msg;
2381 }
2382
2383 const char *tldap_err2string(int rc)
2384 {
2385         const char *res = NULL;
2386
2387         /*
2388          * This would normally be a table, but the error codes are not fully
2389          * sequential. Let the compiler figure out the optimum implementation
2390          * :-)
2391          */
2392
2393         switch (rc) {
2394         case TLDAP_SUCCESS:
2395                 res = "TLDAP_SUCCESS";
2396                 break;
2397         case TLDAP_OPERATIONS_ERROR:
2398                 res = "TLDAP_OPERATIONS_ERROR";
2399                 break;
2400         case TLDAP_PROTOCOL_ERROR:
2401                 res = "TLDAP_PROTOCOL_ERROR";
2402                 break;
2403         case TLDAP_TIMELIMIT_EXCEEDED:
2404                 res = "TLDAP_TIMELIMIT_EXCEEDED";
2405                 break;
2406         case TLDAP_SIZELIMIT_EXCEEDED:
2407                 res = "TLDAP_SIZELIMIT_EXCEEDED";
2408                 break;
2409         case TLDAP_COMPARE_FALSE:
2410                 res = "TLDAP_COMPARE_FALSE";
2411                 break;
2412         case TLDAP_COMPARE_TRUE:
2413                 res = "TLDAP_COMPARE_TRUE";
2414                 break;
2415         case TLDAP_STRONG_AUTH_NOT_SUPPORTED:
2416                 res = "TLDAP_STRONG_AUTH_NOT_SUPPORTED";
2417                 break;
2418         case TLDAP_STRONG_AUTH_REQUIRED:
2419                 res = "TLDAP_STRONG_AUTH_REQUIRED";
2420                 break;
2421         case TLDAP_REFERRAL:
2422                 res = "TLDAP_REFERRAL";
2423                 break;
2424         case TLDAP_ADMINLIMIT_EXCEEDED:
2425                 res = "TLDAP_ADMINLIMIT_EXCEEDED";
2426                 break;
2427         case TLDAP_UNAVAILABLE_CRITICAL_EXTENSION:
2428                 res = "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION";
2429                 break;
2430         case TLDAP_CONFIDENTIALITY_REQUIRED:
2431                 res = "TLDAP_CONFIDENTIALITY_REQUIRED";
2432                 break;
2433         case TLDAP_SASL_BIND_IN_PROGRESS:
2434                 res = "TLDAP_SASL_BIND_IN_PROGRESS";
2435                 break;
2436         case TLDAP_NO_SUCH_ATTRIBUTE:
2437                 res = "TLDAP_NO_SUCH_ATTRIBUTE";
2438                 break;
2439         case TLDAP_UNDEFINED_TYPE:
2440                 res = "TLDAP_UNDEFINED_TYPE";
2441                 break;
2442         case TLDAP_INAPPROPRIATE_MATCHING:
2443                 res = "TLDAP_INAPPROPRIATE_MATCHING";
2444                 break;
2445         case TLDAP_CONSTRAINT_VIOLATION:
2446                 res = "TLDAP_CONSTRAINT_VIOLATION";
2447                 break;
2448         case TLDAP_TYPE_OR_VALUE_EXISTS:
2449                 res = "TLDAP_TYPE_OR_VALUE_EXISTS";
2450                 break;
2451         case TLDAP_INVALID_SYNTAX:
2452                 res = "TLDAP_INVALID_SYNTAX";
2453                 break;
2454         case TLDAP_NO_SUCH_OBJECT:
2455                 res = "TLDAP_NO_SUCH_OBJECT";
2456                 break;
2457         case TLDAP_ALIAS_PROBLEM:
2458                 res = "TLDAP_ALIAS_PROBLEM";
2459                 break;
2460         case TLDAP_INVALID_DN_SYNTAX:
2461                 res = "TLDAP_INVALID_DN_SYNTAX";
2462                 break;
2463         case TLDAP_IS_LEAF:
2464                 res = "TLDAP_IS_LEAF";
2465                 break;
2466         case TLDAP_ALIAS_DEREF_PROBLEM:
2467                 res = "TLDAP_ALIAS_DEREF_PROBLEM";
2468                 break;
2469         case TLDAP_INAPPROPRIATE_AUTH:
2470                 res = "TLDAP_INAPPROPRIATE_AUTH";
2471                 break;
2472         case TLDAP_INVALID_CREDENTIALS:
2473                 res = "TLDAP_INVALID_CREDENTIALS";
2474                 break;
2475         case TLDAP_INSUFFICIENT_ACCESS:
2476                 res = "TLDAP_INSUFFICIENT_ACCESS";
2477                 break;
2478         case TLDAP_BUSY:
2479                 res = "TLDAP_BUSY";
2480                 break;
2481         case TLDAP_UNAVAILABLE:
2482                 res = "TLDAP_UNAVAILABLE";
2483                 break;
2484         case TLDAP_UNWILLING_TO_PERFORM:
2485                 res = "TLDAP_UNWILLING_TO_PERFORM";
2486                 break;
2487         case TLDAP_LOOP_DETECT:
2488                 res = "TLDAP_LOOP_DETECT";
2489                 break;
2490         case TLDAP_NAMING_VIOLATION:
2491                 res = "TLDAP_NAMING_VIOLATION";
2492                 break;
2493         case TLDAP_OBJECT_CLASS_VIOLATION:
2494                 res = "TLDAP_OBJECT_CLASS_VIOLATION";
2495                 break;
2496         case TLDAP_NOT_ALLOWED_ON_NONLEAF:
2497                 res = "TLDAP_NOT_ALLOWED_ON_NONLEAF";
2498                 break;
2499         case TLDAP_NOT_ALLOWED_ON_RDN:
2500                 res = "TLDAP_NOT_ALLOWED_ON_RDN";
2501                 break;
2502         case TLDAP_ALREADY_EXISTS:
2503                 res = "TLDAP_ALREADY_EXISTS";
2504                 break;
2505         case TLDAP_NO_OBJECT_CLASS_MODS:
2506                 res = "TLDAP_NO_OBJECT_CLASS_MODS";
2507                 break;
2508         case TLDAP_RESULTS_TOO_LARGE:
2509                 res = "TLDAP_RESULTS_TOO_LARGE";
2510                 break;
2511         case TLDAP_AFFECTS_MULTIPLE_DSAS:
2512                 res = "TLDAP_AFFECTS_MULTIPLE_DSAS";
2513                 break;
2514         case TLDAP_OTHER:
2515                 res = "TLDAP_OTHER";
2516                 break;
2517         case TLDAP_SERVER_DOWN:
2518                 res = "TLDAP_SERVER_DOWN";
2519                 break;
2520         case TLDAP_LOCAL_ERROR:
2521                 res = "TLDAP_LOCAL_ERROR";
2522                 break;
2523         case TLDAP_ENCODING_ERROR:
2524                 res = "TLDAP_ENCODING_ERROR";
2525                 break;
2526         case TLDAP_DECODING_ERROR:
2527                 res = "TLDAP_DECODING_ERROR";
2528                 break;
2529         case TLDAP_TIMEOUT:
2530                 res = "TLDAP_TIMEOUT";
2531                 break;
2532         case TLDAP_AUTH_UNKNOWN:
2533                 res = "TLDAP_AUTH_UNKNOWN";
2534                 break;
2535         case TLDAP_FILTER_ERROR:
2536                 res = "TLDAP_FILTER_ERROR";
2537                 break;
2538         case TLDAP_USER_CANCELLED:
2539                 res = "TLDAP_USER_CANCELLED";
2540                 break;
2541         case TLDAP_PARAM_ERROR:
2542                 res = "TLDAP_PARAM_ERROR";
2543                 break;
2544         case TLDAP_NO_MEMORY:
2545                 res = "TLDAP_NO_MEMORY";
2546                 break;
2547         case TLDAP_CONNECT_ERROR:
2548                 res = "TLDAP_CONNECT_ERROR";
2549                 break;
2550         case TLDAP_NOT_SUPPORTED:
2551                 res = "TLDAP_NOT_SUPPORTED";
2552                 break;
2553         case TLDAP_CONTROL_NOT_FOUND:
2554                 res = "TLDAP_CONTROL_NOT_FOUND";
2555                 break;
2556         case TLDAP_NO_RESULTS_RETURNED:
2557                 res = "TLDAP_NO_RESULTS_RETURNED";
2558                 break;
2559         case TLDAP_MORE_RESULTS_TO_RETURN:
2560                 res = "TLDAP_MORE_RESULTS_TO_RETURN";
2561                 break;
2562         case TLDAP_CLIENT_LOOP:
2563                 res = "TLDAP_CLIENT_LOOP";
2564                 break;
2565         case TLDAP_REFERRAL_LIMIT_EXCEEDED:
2566                 res = "TLDAP_REFERRAL_LIMIT_EXCEEDED";
2567                 break;
2568         default:
2569                 res = talloc_asprintf(talloc_tos(), "Unknown LDAP Error (%d)",
2570                                       rc);
2571                 break;
2572         }
2573         if (res == NULL) {
2574                 res = "Unknown LDAP Error";
2575         }
2576         return res;
2577 }