Add tstream_read_packet
[ira/wip.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         int fd;
58         int msgid;
59         struct tevent_queue *outgoing;
60         struct tevent_req **pending;
61
62         /* For the sync wrappers we need something like get_last_error... */
63         struct tldap_message *last_msg;
64
65         /* debug */
66         void (*log_fn)(void *context, enum tldap_debug_level level,
67                        const char *fmt, va_list ap);
68         void *log_private;
69
70         struct tldap_ctx_attribute *ctx_attrs;
71 };
72
73 struct tldap_message {
74         struct asn1_data *data;
75         uint8_t *inbuf;
76         int type;
77         int id;
78
79         /* RESULT_ENTRY */
80         char *dn;
81         struct tldap_attribute *attribs;
82
83         /* Error data sent by the server */
84         int lderr;
85         char *res_matcheddn;
86         char *res_diagnosticmessage;
87         char *res_referral;
88         struct tldap_control *res_sctrls;
89
90         /* Controls sent by the server */
91         struct tldap_control *ctrls;
92 };
93
94 void tldap_set_debug(struct tldap_context *ld,
95                      void (*log_fn)(void *log_private,
96                                     enum tldap_debug_level level,
97                                     const char *fmt,
98                                     va_list ap) PRINTF_ATTRIBUTE(3,0),
99                      void *log_private)
100 {
101         ld->log_fn = log_fn;
102         ld->log_private = log_private;
103 }
104
105 static void tldap_debug(struct tldap_context *ld,
106                          enum tldap_debug_level level,
107                          const char *fmt, ...)
108 {
109         va_list ap;
110         if (!ld) {
111                 return;
112         }
113         if (ld->log_fn == NULL) {
114                 return;
115         }
116         va_start(ap, fmt);
117         ld->log_fn(ld->log_private, level, fmt, ap);
118         va_end(ap);
119 }
120
121 static int tldap_next_msgid(struct tldap_context *ld)
122 {
123         int result;
124
125         result = ld->msgid++;
126         if (ld->msgid == 2147483647) {
127                 ld->msgid = 1;
128         }
129         return result;
130 }
131
132 struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
133 {
134         struct tldap_context *ctx;
135
136         ctx = talloc_zero(mem_ctx, struct tldap_context);
137         if (ctx == NULL) {
138                 return NULL;
139         }
140         ctx->fd = fd;
141         ctx->msgid = 1;
142         ctx->ld_version = 3;
143         ctx->outgoing = tevent_queue_create(ctx, "tldap_outgoing");
144         if (ctx->outgoing == NULL) {
145                 TALLOC_FREE(ctx);
146                 return NULL;
147         }
148         return ctx;
149 }
150
151 static struct tldap_ctx_attribute *tldap_context_findattr(
152         struct tldap_context *ld, const char *name)
153 {
154         int i, num_attrs;
155
156         num_attrs = talloc_array_length(ld->ctx_attrs);
157
158         for (i=0; i<num_attrs; i++) {
159                 if (strcmp(ld->ctx_attrs[i].name, name) == 0) {
160                         return &ld->ctx_attrs[i];
161                 }
162         }
163         return NULL;
164 }
165
166 bool tldap_context_setattr(struct tldap_context *ld,
167                            const char *name, const void *_pptr)
168 {
169         struct tldap_ctx_attribute *tmp, *attr;
170         char *tmpname;
171         int num_attrs;
172         void **pptr = (void **)_pptr;
173
174         attr = tldap_context_findattr(ld, name);
175         if (attr != NULL) {
176                 /*
177                  * We don't actually delete attrs, we don't expect tons of
178                  * attributes being shuffled around.
179                  */
180                 TALLOC_FREE(attr->ptr);
181                 if (*pptr != NULL) {
182                         attr->ptr = talloc_move(ld->ctx_attrs, pptr);
183                         *pptr = NULL;
184                 }
185                 return true;
186         }
187
188         tmpname = talloc_strdup(ld, name);
189         if (tmpname == NULL) {
190                 return false;
191         }
192
193         num_attrs = talloc_array_length(ld->ctx_attrs);
194
195         tmp = talloc_realloc(ld, ld->ctx_attrs, struct tldap_ctx_attribute,
196                              num_attrs+1);
197         if (tmp == NULL) {
198                 TALLOC_FREE(tmpname);
199                 return false;
200         }
201         tmp[num_attrs].name = talloc_move(tmp, &tmpname);
202         if (*pptr != NULL) {
203                 tmp[num_attrs].ptr = talloc_move(tmp, pptr);
204         } else {
205                 tmp[num_attrs].ptr = NULL;
206         }
207         *pptr = NULL;
208         ld->ctx_attrs = tmp;
209         return true;
210 }
211
212 void *tldap_context_getattr(struct tldap_context *ld, const char *name)
213 {
214         struct tldap_ctx_attribute *attr = tldap_context_findattr(ld, name);
215
216         if (attr == NULL) {
217                 return NULL;
218         }
219         return attr->ptr;
220 }
221
222 struct read_ldap_state {
223         uint8_t *buf;
224         bool done;
225 };
226
227 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data)
228 {
229         struct read_ldap_state *state = talloc_get_type_abort(
230                 private_data, struct read_ldap_state);
231         size_t len;
232         int i, lensize;
233
234         if (state->done) {
235                 /* We've been here, we're done */
236                 return 0;
237         }
238
239         /*
240          * From ldap.h: LDAP_TAG_MESSAGE is 0x30
241          */
242         if (buf[0] != 0x30) {
243                 return -1;
244         }
245
246         len = buf[1];
247         if ((len & 0x80) == 0) {
248                 state->done = true;
249                 return len;
250         }
251
252         lensize = (len & 0x7f);
253         len = 0;
254
255         if (buflen == 2) {
256                 /* Please get us the full length */
257                 return lensize;
258         }
259         if (buflen > 2 + lensize) {
260                 state->done = true;
261                 return 0;
262         }
263         if (buflen != 2 + lensize) {
264                 return -1;
265         }
266
267         for (i=0; i<lensize; i++) {
268                 len = (len << 8) | buf[2+i];
269         }
270         return len;
271 }
272
273 static void read_ldap_done(struct tevent_req *subreq);
274
275 static struct tevent_req *read_ldap_send(TALLOC_CTX *mem_ctx,
276                                          struct tevent_context *ev,
277                                          int fd)
278 {
279         struct tevent_req *req, *subreq;
280         struct read_ldap_state *state;
281
282         req = tevent_req_create(mem_ctx, &state, struct read_ldap_state);
283         if (req == NULL) {
284                 return NULL;
285         }
286         state->done = false;
287
288         subreq = read_packet_send(state, ev, fd, 2, read_ldap_more, state);
289         if (tevent_req_nomem(subreq, req)) {
290                 return tevent_req_post(req, ev);
291         }
292         tevent_req_set_callback(subreq, read_ldap_done, req);
293         return req;
294 }
295
296 static void read_ldap_done(struct tevent_req *subreq)
297 {
298         struct tevent_req *req = tevent_req_callback_data(
299                 subreq, struct tevent_req);
300         struct read_ldap_state *state = tevent_req_data(
301                 req, struct read_ldap_state);
302         ssize_t nread;
303         int err;
304
305         nread = read_packet_recv(subreq, state, &state->buf, &err);
306         TALLOC_FREE(subreq);
307         if (nread == -1) {
308                 tevent_req_error(req, err);
309                 return;
310         }
311         tevent_req_done(req);
312 }
313
314 static ssize_t read_ldap_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
315                               uint8_t **pbuf, int *perrno)
316 {
317         struct read_ldap_state *state = tevent_req_data(
318                 req, struct read_ldap_state);
319
320         if (tevent_req_is_unix_error(req, perrno)) {
321                 return -1;
322         }
323         *pbuf = talloc_move(mem_ctx, &state->buf);
324         return talloc_get_size(*pbuf);
325 }
326
327 struct tldap_msg_state {
328         struct tldap_context *ld;
329         struct tevent_context *ev;
330         int id;
331         struct iovec iov;
332
333         struct asn1_data *data;
334         uint8_t *inbuf;
335 };
336
337 static void tldap_push_controls(struct asn1_data *data,
338                                 struct tldap_control *sctrls,
339                                 int num_sctrls)
340 {
341         int i;
342
343         if ((sctrls == NULL) || (num_sctrls == 0)) {
344                 return;
345         }
346
347         asn1_push_tag(data, ASN1_CONTEXT(0));
348
349         for (i=0; i<num_sctrls; i++) {
350                 struct tldap_control *c = &sctrls[i];
351                 asn1_push_tag(data, ASN1_SEQUENCE(0));
352                 asn1_write_OctetString(data, c->oid, strlen(c->oid));
353                 if (c->critical) {
354                         asn1_write_BOOLEAN(data, true);
355                 }
356                 if (c->value.data != NULL) {
357                         asn1_write_OctetString(data, c->value.data,
358                                                c->value.length);
359                 }
360                 asn1_pop_tag(data); /* ASN1_SEQUENCE(0) */
361         }
362
363         asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
364 }
365
366 static void tldap_msg_sent(struct tevent_req *subreq);
367 static void tldap_msg_received(struct tevent_req *subreq);
368
369 static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
370                                          struct tevent_context *ev,
371                                          struct tldap_context *ld,
372                                          int id, struct asn1_data *data,
373                                          struct tldap_control *sctrls,
374                                          int num_sctrls)
375 {
376         struct tevent_req *req, *subreq;
377         struct tldap_msg_state *state;
378         DATA_BLOB blob;
379
380         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
381                     id);
382
383         req = tevent_req_create(mem_ctx, &state, struct tldap_msg_state);
384         if (req == NULL) {
385                 return NULL;
386         }
387         state->ld = ld;
388         state->ev = ev;
389         state->id = id;
390
391         tldap_push_controls(data, sctrls, num_sctrls);
392
393         asn1_pop_tag(data);
394
395         if (!asn1_blob(data, &blob)) {
396                 tevent_req_error(req, TLDAP_ENCODING_ERROR);
397                 return tevent_req_post(req, ev);
398         }
399
400         state->iov.iov_base = blob.data;
401         state->iov.iov_len = blob.length;
402
403         subreq = writev_send(state, ev, ld->outgoing, ld->fd, false,
404                              &state->iov, 1);
405         if (tevent_req_nomem(subreq, req)) {
406                 return tevent_req_post(req, ev);
407         }
408         tevent_req_set_callback(subreq, tldap_msg_sent, req);
409         return req;
410 }
411
412 static void tldap_msg_unset_pending(struct tevent_req *req)
413 {
414         struct tldap_msg_state *state = tevent_req_data(
415                 req, struct tldap_msg_state);
416         struct tldap_context *ld = state->ld;
417         int num_pending = talloc_array_length(ld->pending);
418         int i;
419
420         if (num_pending == 1) {
421                 TALLOC_FREE(ld->pending);
422                 return;
423         }
424
425         for (i=0; i<num_pending; i++) {
426                 if (req == ld->pending[i]) {
427                         break;
428                 }
429         }
430         if (i == num_pending) {
431                 /*
432                  * Something's seriously broken. Just returning here is the
433                  * right thing nevertheless, the point of this routine is to
434                  * remove ourselves from cli->pending.
435                  */
436                 return;
437         }
438
439         /*
440          * Remove ourselves from the cli->pending array
441          */
442         if (num_pending > 1) {
443                 ld->pending[i] = ld->pending[num_pending-1];
444         }
445
446         /*
447          * No NULL check here, we're shrinking by sizeof(void *), and
448          * talloc_realloc just adjusts the size for this.
449          */
450         ld->pending = talloc_realloc(NULL, ld->pending, struct tevent_req *,
451                                      num_pending - 1);
452         return;
453 }
454
455 static int tldap_msg_destructor(struct tevent_req *req)
456 {
457         tldap_msg_unset_pending(req);
458         return 0;
459 }
460
461 static bool tldap_msg_set_pending(struct tevent_req *req)
462 {
463         struct tldap_msg_state *state = tevent_req_data(
464                 req, struct tldap_msg_state);
465         struct tldap_context *ld;
466         struct tevent_req **pending;
467         int num_pending;
468         struct tevent_req *subreq;
469
470         ld = state->ld;
471         num_pending = talloc_array_length(ld->pending);
472
473         pending = talloc_realloc(ld, ld->pending, struct tevent_req *,
474                                  num_pending+1);
475         if (pending == NULL) {
476                 return false;
477         }
478         pending[num_pending] = req;
479         ld->pending = pending;
480         talloc_set_destructor(req, tldap_msg_destructor);
481
482         if (num_pending > 0) {
483                 return true;
484         }
485
486         /*
487          * We're the first ones, add the read_ldap request that waits for the
488          * answer from the server
489          */
490         subreq = read_ldap_send(ld->pending, state->ev, ld->fd);
491         if (subreq == NULL) {
492                 tldap_msg_unset_pending(req);
493                 return false;
494         }
495         tevent_req_set_callback(subreq, tldap_msg_received, ld);
496         return true;
497 }
498
499 static void tldap_msg_sent(struct tevent_req *subreq)
500 {
501         struct tevent_req *req = tevent_req_callback_data(
502                 subreq, struct tevent_req);
503         ssize_t nwritten;
504         int err;
505
506         nwritten = writev_recv(subreq, &err);
507         TALLOC_FREE(subreq);
508         if (nwritten == -1) {
509                 tevent_req_error(req, TLDAP_SERVER_DOWN);
510                 return;
511         }
512
513         if (!tldap_msg_set_pending(req)) {
514                 tevent_req_nomem(NULL, req);
515                 return;
516         }
517 }
518
519 static int tldap_msg_msgid(struct tevent_req *req)
520 {
521         struct tldap_msg_state *state = tevent_req_data(
522                 req, struct tldap_msg_state);
523
524         return state->id;
525 }
526
527 static void tldap_msg_received(struct tevent_req *subreq)
528 {
529         struct tldap_context *ld = tevent_req_callback_data(
530                 subreq, struct tldap_context);
531         struct tevent_req *req;
532         struct tldap_msg_state *state;
533         struct tevent_context *ev;
534         struct asn1_data *data;
535         uint8_t *inbuf;
536         ssize_t received;
537         size_t num_pending;
538         int i, err, status;
539         int id;
540         uint8_t type;
541         bool ok;
542
543         received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
544         TALLOC_FREE(subreq);
545         if (received == -1) {
546                 status = TLDAP_SERVER_DOWN;
547                 goto fail;
548         }
549
550         data = asn1_init(talloc_tos());
551         if (data == NULL) {
552                 status = TLDAP_NO_MEMORY;
553                 goto fail;
554         }
555         asn1_load_nocopy(data, inbuf, received);
556
557         ok = true;
558         ok &= asn1_start_tag(data, ASN1_SEQUENCE(0));
559         ok &= asn1_read_Integer(data, &id);
560         ok &= asn1_peek_uint8(data, &type);
561
562         if (!ok) {
563                 status = TLDAP_PROTOCOL_ERROR;
564                 goto fail;
565         }
566
567         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
568                     "type %d\n", id, (int)type);
569
570         num_pending = talloc_array_length(ld->pending);
571
572         for (i=0; i<num_pending; i++) {
573                 if (id == tldap_msg_msgid(ld->pending[i])) {
574                         break;
575                 }
576         }
577         if (i == num_pending) {
578                 /* Dump unexpected reply */
579                 tldap_debug(ld, TLDAP_DEBUG_WARNING, "tldap_msg_received: "
580                             "No request pending for msg %d\n", id);
581                 TALLOC_FREE(inbuf);
582                 goto done;
583         }
584
585         req = ld->pending[i];
586         state = tevent_req_data(req, struct tldap_msg_state);
587
588         state->inbuf = talloc_move(state, &inbuf);
589         state->data = talloc_move(state, &data);
590
591         ev = state->ev;
592
593         talloc_set_destructor(req, NULL);
594         tldap_msg_unset_pending(req);
595         num_pending = talloc_array_length(ld->pending);
596
597         tevent_req_done(req);
598
599  done:
600         if (num_pending == 0) {
601                 return;
602         }
603         if (talloc_array_length(ld->pending) > num_pending) {
604                 /*
605                  * The callback functions called from tevent_req_done() above
606                  * have put something on the pending queue. We don't have to
607                  * trigger the read_ldap_send(), tldap_msg_set_pending() has
608                  * done it for us already.
609                  */
610                 return;
611         }
612
613         state = tevent_req_data(ld->pending[0], struct tldap_msg_state);
614         subreq = read_ldap_send(ld->pending, state->ev, ld->fd);
615         if (subreq == NULL) {
616                 status = TLDAP_NO_MEMORY;
617                 goto fail;
618         }
619         tevent_req_set_callback(subreq, tldap_msg_received, ld);
620         return;
621
622  fail:
623         while (talloc_array_length(ld->pending) > 0) {
624                 req = ld->pending[0];
625                 talloc_set_destructor(req, NULL);
626                 tldap_msg_destructor(req);
627                 tevent_req_error(req, status);
628         }
629 }
630
631 static int tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
632                           struct tldap_message **pmsg)
633 {
634         struct tldap_msg_state *state = tevent_req_data(
635                 req, struct tldap_msg_state);
636         struct tldap_message *msg;
637         int err;
638         uint8_t msgtype;
639
640         if (tevent_req_is_ldap_error(req, &err)) {
641                 return err;
642         }
643
644         if (!asn1_peek_uint8(state->data, &msgtype)) {
645                 return TLDAP_PROTOCOL_ERROR;
646         }
647
648         if (pmsg == NULL) {
649                 return TLDAP_SUCCESS;
650         }
651
652         msg = talloc_zero(mem_ctx, struct tldap_message);
653         if (msg == NULL) {
654                 return TLDAP_NO_MEMORY;
655         }
656         msg->id = state->id;
657
658         msg->inbuf = talloc_move(msg, &state->inbuf);
659         msg->data = talloc_move(msg, &state->data);
660         msg->type = msgtype;
661
662         *pmsg = msg;
663         return TLDAP_SUCCESS;
664 }
665
666 struct tldap_req_state {
667         int id;
668         struct asn1_data *out;
669         struct tldap_message *result;
670 };
671
672 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
673                                            struct tldap_context *ld,
674                                            struct tldap_req_state **pstate)
675 {
676         struct tevent_req *req;
677         struct tldap_req_state *state;
678
679         req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
680         if (req == NULL) {
681                 return NULL;
682         }
683         ZERO_STRUCTP(state);
684         state->out = asn1_init(state);
685         if (state->out == NULL) {
686                 TALLOC_FREE(req);
687                 return NULL;
688         }
689         state->result = NULL;
690         state->id = tldap_next_msgid(ld);
691
692         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
693         asn1_write_Integer(state->out, state->id);
694
695         *pstate = state;
696         return req;
697 }
698
699 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
700 {
701         struct tldap_req_state *state = tevent_req_data(
702                 req, struct tldap_req_state);
703
704         TALLOC_FREE(ld->last_msg);
705         ld->last_msg = talloc_move(ld, &state->result);
706 }
707
708 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
709 {
710         char *result = talloc_array(mem_ctx, char, blob.length+1);
711         memcpy(result, blob.data, blob.length);
712         result[blob.length] = '\0';
713         return result;
714 }
715
716 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
717                                          struct asn1_data *data,
718                                          char **result)
719 {
720         DATA_BLOB string;
721         if (!asn1_read_OctetString(data, mem_ctx, &string))
722                 return false;
723         *result = blob2string_talloc(mem_ctx, string);
724         data_blob_free(&string);
725         return true;
726 }
727
728 static bool tldap_decode_controls(struct tldap_req_state *state);
729
730 static bool tldap_decode_response(struct tldap_req_state *state)
731 {
732         struct asn1_data *data = state->result->data;
733         struct tldap_message *msg = state->result;
734         bool ok = true;
735
736         ok &= asn1_read_enumerated(data, &msg->lderr);
737         ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
738         ok &= asn1_read_OctetString_talloc(msg, data,
739                                            &msg->res_diagnosticmessage);
740         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
741                 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
742                 ok &= asn1_read_OctetString_talloc(msg, data,
743                                                    &msg->res_referral);
744                 ok &= asn1_end_tag(data);
745         } else {
746                 msg->res_referral = NULL;
747         }
748
749         return ok;
750 }
751
752 static void tldap_sasl_bind_done(struct tevent_req *subreq);
753
754 struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
755                                         struct tevent_context *ev,
756                                         struct tldap_context *ld,
757                                         const char *dn,
758                                         const char *mechanism,
759                                         DATA_BLOB *creds,
760                                         struct tldap_control *sctrls,
761                                         int num_sctrls,
762                                         struct tldap_control *cctrls,
763                                         int num_cctrls)
764 {
765         struct tevent_req *req, *subreq;
766         struct tldap_req_state *state;
767
768         req = tldap_req_create(mem_ctx, ld, &state);
769         if (req == NULL) {
770                 return NULL;
771         }
772
773         if (dn == NULL) {
774                 dn = "";
775         }
776
777         asn1_push_tag(state->out, TLDAP_REQ_BIND);
778         asn1_write_Integer(state->out, ld->ld_version);
779         asn1_write_OctetString(state->out, dn, (dn != NULL) ? strlen(dn) : 0);
780
781         if (mechanism == NULL) {
782                 asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0));
783                 asn1_write(state->out, creds->data, creds->length);
784                 asn1_pop_tag(state->out);
785         } else {
786                 asn1_push_tag(state->out, ASN1_CONTEXT(3));
787                 asn1_write_OctetString(state->out, mechanism,
788                                        strlen(mechanism));
789                 if ((creds != NULL) && (creds->data != NULL)) {
790                         asn1_write_OctetString(state->out, creds->data,
791                                                creds->length);
792                 }
793                 asn1_pop_tag(state->out);
794         }
795
796         if (!asn1_pop_tag(state->out)) {
797                 tevent_req_error(req, TLDAP_ENCODING_ERROR);
798                 return tevent_req_post(req, ev);
799         }
800
801         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
802                                 sctrls, num_sctrls);
803         if (tevent_req_nomem(subreq, req)) {
804                 return tevent_req_post(req, ev);
805         }
806         tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
807         return req;
808 }
809
810 static void tldap_sasl_bind_done(struct tevent_req *subreq)
811 {
812         struct tevent_req *req = tevent_req_callback_data(
813                 subreq, struct tevent_req);
814         struct tldap_req_state *state = tevent_req_data(
815                 req, struct tldap_req_state);
816         int err;
817
818         err = tldap_msg_recv(subreq, state, &state->result);
819         TALLOC_FREE(subreq);
820         if (err != TLDAP_SUCCESS) {
821                 tevent_req_error(req, err);
822                 return;
823         }
824         if (state->result->type != TLDAP_RES_BIND) {
825                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
826                 return;
827         }
828         if (!asn1_start_tag(state->result->data, state->result->type) ||
829             !tldap_decode_response(state) ||
830             !asn1_end_tag(state->result->data)) {
831                 tevent_req_error(req, TLDAP_DECODING_ERROR);
832                 return;
833         }
834         /*
835          * TODO: pull the reply blob
836          */
837         if (state->result->lderr != TLDAP_SUCCESS) {
838                 tevent_req_error(req, state->result->lderr);
839                 return;
840         }
841         tevent_req_done(req);
842 }
843
844 int tldap_sasl_bind_recv(struct tevent_req *req)
845 {
846         int err;
847
848         if (tevent_req_is_ldap_error(req, &err)) {
849                 return err;
850         }
851         return TLDAP_SUCCESS;
852 }
853
854 int tldap_sasl_bind(struct tldap_context *ld,
855                     const char *dn,
856                     const char *mechanism,
857                     DATA_BLOB *creds,
858                     struct tldap_control *sctrls,
859                     int num_sctrls,
860                     struct tldap_control *cctrls,
861                     int num_cctrls)
862 {
863         TALLOC_CTX *frame = talloc_stackframe();
864         struct tevent_context *ev;
865         struct tevent_req *req;
866         int result;
867
868         ev = event_context_init(frame);
869         if (ev == NULL) {
870                 result = TLDAP_NO_MEMORY;
871                 goto fail;
872         }
873
874         req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
875                                    sctrls, num_sctrls, cctrls, num_cctrls);
876         if (req == NULL) {
877                 result = TLDAP_NO_MEMORY;
878                 goto fail;
879         }
880
881         if (!tevent_req_poll(req, ev)) {
882                 result = TLDAP_OPERATIONS_ERROR;
883                 goto fail;
884         }
885
886         result = tldap_sasl_bind_recv(req);
887         tldap_save_msg(ld, req);
888  fail:
889         TALLOC_FREE(frame);
890         return result;
891 }
892
893 struct tevent_req *tldap_simple_bind_send(TALLOC_CTX *mem_ctx,
894                                           struct tevent_context *ev,
895                                           struct tldap_context *ld,
896                                           const char *dn,
897                                           const char *passwd)
898 {
899         DATA_BLOB cred;
900
901         if (passwd != NULL) {
902                 cred.data = (uint8_t *)passwd;
903                 cred.length = strlen(passwd);
904         } else {
905                 cred.data = (uint8_t *)"";
906                 cred.length = 0;
907         }
908         return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
909                                     NULL, 0);
910 }
911
912 int tldap_simple_bind_recv(struct tevent_req *req)
913 {
914         return tldap_sasl_bind_recv(req);
915 }
916
917 int tldap_simple_bind(struct tldap_context *ld, const char *dn,
918                       const char *passwd)
919 {
920         DATA_BLOB cred;
921
922         if (passwd != NULL) {
923                 cred.data = (uint8_t *)passwd;
924                 cred.length = strlen(passwd);
925         } else {
926                 cred.data = (uint8_t *)"";
927                 cred.length = 0;
928         }
929         return tldap_sasl_bind(ld, dn, NULL, &cred, NULL, 0, NULL, 0);
930 }
931
932 /*****************************************************************************/
933
934 /*
935  * This piece has a dependency on ldb, the ldb_parse_tree() function is used.
936  * In case we want to separate out tldap, we need to copy or rewrite it.
937  */
938
939 #include "lib/ldb/include/ldb.h"
940 #include "lib/ldb/include/ldb_errors.h"
941
942 static bool ldap_push_filter(struct asn1_data *data,
943                              struct ldb_parse_tree *tree)
944 {
945         int i;
946
947         switch (tree->operation) {
948         case LDB_OP_AND:
949         case LDB_OP_OR:
950                 asn1_push_tag(data,
951                               ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
952                 for (i=0; i<tree->u.list.num_elements; i++) {
953                         if (!ldap_push_filter(data,
954                                               tree->u.list.elements[i])) {
955                                 return false;
956                         }
957                 }
958                 asn1_pop_tag(data);
959                 break;
960
961         case LDB_OP_NOT:
962                 asn1_push_tag(data, ASN1_CONTEXT(2));
963                 if (!ldap_push_filter(data, tree->u.isnot.child)) {
964                         return false;
965                 }
966                 asn1_pop_tag(data);
967                 break;
968
969         case LDB_OP_EQUALITY:
970                 /* equality test */
971                 asn1_push_tag(data, ASN1_CONTEXT(3));
972                 asn1_write_OctetString(data, tree->u.equality.attr,
973                                       strlen(tree->u.equality.attr));
974                 asn1_write_OctetString(data, tree->u.equality.value.data,
975                                       tree->u.equality.value.length);
976                 asn1_pop_tag(data);
977                 break;
978
979         case LDB_OP_SUBSTRING:
980                 /*
981                   SubstringFilter ::= SEQUENCE {
982                           type            AttributeDescription,
983                           -- at least one must be present
984                           substrings      SEQUENCE OF CHOICE {
985                                   initial [0] LDAPString,
986                                   any     [1] LDAPString,
987                                   final   [2] LDAPString } }
988                 */
989                 asn1_push_tag(data, ASN1_CONTEXT(4));
990                 asn1_write_OctetString(data, tree->u.substring.attr,
991                                        strlen(tree->u.substring.attr));
992                 asn1_push_tag(data, ASN1_SEQUENCE(0));
993                 i = 0;
994                 if (!tree->u.substring.start_with_wildcard) {
995                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
996                         asn1_write_DATA_BLOB_LDAPString(
997                                 data, tree->u.substring.chunks[i]);
998                         asn1_pop_tag(data);
999                         i++;
1000                 }
1001                 while (tree->u.substring.chunks[i]) {
1002                         int ctx;
1003
1004                         if ((!tree->u.substring.chunks[i + 1]) &&
1005                             (tree->u.substring.end_with_wildcard == 0)) {
1006                                 ctx = 2;
1007                         } else {
1008                                 ctx = 1;
1009                         }
1010                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
1011                         asn1_write_DATA_BLOB_LDAPString(
1012                                 data, tree->u.substring.chunks[i]);
1013                         asn1_pop_tag(data);
1014                         i++;
1015                 }
1016                 asn1_pop_tag(data);
1017                 asn1_pop_tag(data);
1018                 break;
1019
1020         case LDB_OP_GREATER:
1021                 /* greaterOrEqual test */
1022                 asn1_push_tag(data, ASN1_CONTEXT(5));
1023                 asn1_write_OctetString(data, tree->u.comparison.attr,
1024                                       strlen(tree->u.comparison.attr));
1025                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1026                                       tree->u.comparison.value.length);
1027                 asn1_pop_tag(data);
1028                 break;
1029
1030         case LDB_OP_LESS:
1031                 /* lessOrEqual test */
1032                 asn1_push_tag(data, ASN1_CONTEXT(6));
1033                 asn1_write_OctetString(data, tree->u.comparison.attr,
1034                                       strlen(tree->u.comparison.attr));
1035                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1036                                       tree->u.comparison.value.length);
1037                 asn1_pop_tag(data);
1038                 break;
1039
1040         case LDB_OP_PRESENT:
1041                 /* present test */
1042                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
1043                 asn1_write_LDAPString(data, tree->u.present.attr);
1044                 asn1_pop_tag(data);
1045                 return !data->has_error;
1046
1047         case LDB_OP_APPROX:
1048                 /* approx test */
1049                 asn1_push_tag(data, ASN1_CONTEXT(8));
1050                 asn1_write_OctetString(data, tree->u.comparison.attr,
1051                                       strlen(tree->u.comparison.attr));
1052                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1053                                       tree->u.comparison.value.length);
1054                 asn1_pop_tag(data);
1055                 break;
1056
1057         case LDB_OP_EXTENDED:
1058                 /*
1059                   MatchingRuleAssertion ::= SEQUENCE {
1060                   matchingRule    [1] MatchingRuleID OPTIONAL,
1061                   type            [2] AttributeDescription OPTIONAL,
1062                   matchValue      [3] AssertionValue,
1063                   dnAttributes    [4] BOOLEAN DEFAULT FALSE
1064                   }
1065                 */
1066                 asn1_push_tag(data, ASN1_CONTEXT(9));
1067                 if (tree->u.extended.rule_id) {
1068                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
1069                         asn1_write_LDAPString(data, tree->u.extended.rule_id);
1070                         asn1_pop_tag(data);
1071                 }
1072                 if (tree->u.extended.attr) {
1073                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
1074                         asn1_write_LDAPString(data, tree->u.extended.attr);
1075                         asn1_pop_tag(data);
1076                 }
1077                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
1078                 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
1079                 asn1_pop_tag(data);
1080                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
1081                 asn1_write_uint8(data, tree->u.extended.dnAttributes);
1082                 asn1_pop_tag(data);
1083                 asn1_pop_tag(data);
1084                 break;
1085
1086         default:
1087                 return false;
1088         }
1089         return !data->has_error;
1090 }
1091
1092 static bool tldap_push_filter(struct asn1_data *data, const char *filter)
1093 {
1094         struct ldb_parse_tree *tree;
1095         bool ret;
1096
1097         tree = ldb_parse_tree(talloc_tos(), filter);
1098         if (tree == NULL) {
1099                 return false;
1100         }
1101         ret = ldap_push_filter(data, tree);
1102         TALLOC_FREE(tree);
1103         return ret;
1104 }
1105
1106 /*****************************************************************************/
1107
1108 static void tldap_search_done(struct tevent_req *subreq);
1109
1110 struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
1111                                      struct tevent_context *ev,
1112                                      struct tldap_context *ld,
1113                                      const char *base, int scope,
1114                                      const char *filter,
1115                                      const char **attrs,
1116                                      int num_attrs,
1117                                      int attrsonly,
1118                                      struct tldap_control *sctrls,
1119                                      int num_sctrls,
1120                                      struct tldap_control *cctrls,
1121                                      int num_cctrls,
1122                                      int timelimit,
1123                                      int sizelimit,
1124                                      int deref)
1125 {
1126         struct tevent_req *req, *subreq;
1127         struct tldap_req_state *state;
1128         int i;
1129
1130         req = tldap_req_create(mem_ctx, ld, &state);
1131         if (req == NULL) {
1132                 return NULL;
1133         }
1134
1135         asn1_push_tag(state->out, TLDAP_REQ_SEARCH);
1136         asn1_write_OctetString(state->out, base, strlen(base));
1137         asn1_write_enumerated(state->out, scope);
1138         asn1_write_enumerated(state->out, deref);
1139         asn1_write_Integer(state->out, sizelimit);
1140         asn1_write_Integer(state->out, timelimit);
1141         asn1_write_BOOLEAN(state->out, attrsonly);
1142
1143         if (!tldap_push_filter(state->out, filter)) {
1144                 goto encoding_error;
1145         }
1146
1147         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1148         for (i=0; i<num_attrs; i++) {
1149                 asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]));
1150         }
1151         asn1_pop_tag(state->out);
1152         asn1_pop_tag(state->out);
1153
1154         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1155                                 sctrls, num_sctrls);
1156         if (tevent_req_nomem(subreq, req)) {
1157                 return tevent_req_post(req, ev);
1158         }
1159         tevent_req_set_callback(subreq, tldap_search_done, req);
1160         return req;
1161
1162  encoding_error:
1163         tevent_req_error(req, TLDAP_ENCODING_ERROR);
1164         return tevent_req_post(req, ev);
1165 }
1166
1167 static void tldap_search_done(struct tevent_req *subreq)
1168 {
1169         struct tevent_req *req = tevent_req_callback_data(
1170                 subreq, struct tevent_req);
1171         struct tldap_req_state *state = tevent_req_data(
1172                 req, struct tldap_req_state);
1173         int err;
1174
1175         err = tldap_msg_recv(subreq, state, &state->result);
1176         if (err != TLDAP_SUCCESS) {
1177                 tevent_req_error(req, err);
1178                 return;
1179         }
1180         switch (state->result->type) {
1181         case TLDAP_RES_SEARCH_ENTRY:
1182         case TLDAP_RES_SEARCH_REFERENCE:
1183                 tevent_req_notify_callback(req);
1184                 if (!tldap_msg_set_pending(subreq)) {
1185                         tevent_req_nomem(NULL, req);
1186                         return;
1187                 }
1188                 break;
1189         case TLDAP_RES_SEARCH_RESULT:
1190                 TALLOC_FREE(subreq);
1191                 if (!asn1_start_tag(state->result->data,
1192                                     state->result->type) ||
1193                     !tldap_decode_response(state) ||
1194                     !asn1_end_tag(state->result->data) ||
1195                     !tldap_decode_controls(state)) {
1196                         tevent_req_error(req, TLDAP_DECODING_ERROR);
1197                         return;
1198                 }
1199                 tevent_req_done(req);
1200                 break;
1201         default:
1202                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1203                 return;
1204         }
1205 }
1206
1207 int tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1208                       struct tldap_message **pmsg)
1209 {
1210         struct tldap_req_state *state = tevent_req_data(
1211                 req, struct tldap_req_state);
1212         int err;
1213
1214         if (!tevent_req_is_in_progress(req)
1215             && tevent_req_is_ldap_error(req, &err)) {
1216                 return err;
1217         }
1218
1219         if (tevent_req_is_in_progress(req)) {
1220                 switch (state->result->type) {
1221                 case TLDAP_RES_SEARCH_ENTRY:
1222                 case TLDAP_RES_SEARCH_REFERENCE:
1223                         break;
1224                 default:
1225                         return TLDAP_OPERATIONS_ERROR;
1226                 }
1227         }
1228
1229         *pmsg = talloc_move(mem_ctx, &state->result);
1230         return TLDAP_SUCCESS;
1231 }
1232
1233 struct tldap_sync_search_state {
1234         TALLOC_CTX *mem_ctx;
1235         struct tldap_message **entries;
1236         struct tldap_message **refs;
1237         int rc;
1238 };
1239
1240 static void tldap_search_cb(struct tevent_req *req)
1241 {
1242         struct tldap_sync_search_state *state =
1243                 (struct tldap_sync_search_state *)
1244                 tevent_req_callback_data_void(req);
1245         struct tldap_message *msg, **tmp;
1246         int rc, num_entries, num_refs;
1247
1248         rc = tldap_search_recv(req, talloc_tos(), &msg);
1249         if (rc != TLDAP_SUCCESS) {
1250                 state->rc = rc;
1251                 return;
1252         }
1253
1254         switch (tldap_msg_type(msg)) {
1255         case TLDAP_RES_SEARCH_ENTRY:
1256                 num_entries = talloc_array_length(state->entries);
1257                 tmp = talloc_realloc(state->mem_ctx, state->entries,
1258                                      struct tldap_message *, num_entries + 1);
1259                 if (tmp == NULL) {
1260                         state->rc = TLDAP_NO_MEMORY;
1261                         return;
1262                 }
1263                 state->entries = tmp;
1264                 state->entries[num_entries] = talloc_move(state->entries,
1265                                                           &msg);
1266                 break;
1267         case TLDAP_RES_SEARCH_REFERENCE:
1268                 num_refs = talloc_array_length(state->refs);
1269                 tmp = talloc_realloc(state->mem_ctx, state->refs,
1270                                      struct tldap_message *, num_refs + 1);
1271                 if (tmp == NULL) {
1272                         state->rc = TLDAP_NO_MEMORY;
1273                         return;
1274                 }
1275                 state->refs = tmp;
1276                 state->refs[num_refs] = talloc_move(state->refs, &msg);
1277                 break;
1278         case TLDAP_RES_SEARCH_RESULT:
1279                 state->rc = TLDAP_SUCCESS;
1280                 break;
1281         default:
1282                 state->rc = TLDAP_PROTOCOL_ERROR;
1283                 break;
1284         }
1285 }
1286
1287 int tldap_search(struct tldap_context *ld,
1288                  const char *base, int scope, const char *filter,
1289                  const char **attrs, int num_attrs, int attrsonly,
1290                  struct tldap_control *sctrls, int num_sctrls,
1291                  struct tldap_control *cctrls, int num_cctrls,
1292                  int timelimit, int sizelimit, int deref,
1293                  TALLOC_CTX *mem_ctx, struct tldap_message ***entries,
1294                  struct tldap_message ***refs)
1295 {
1296         TALLOC_CTX *frame = talloc_stackframe();
1297         struct tevent_context *ev;
1298         struct tevent_req *req;
1299         struct tldap_sync_search_state state;
1300
1301         ZERO_STRUCT(state);
1302         state.mem_ctx = mem_ctx;
1303         state.rc = TLDAP_SUCCESS;
1304
1305         ev = event_context_init(frame);
1306         if (ev == NULL) {
1307                 state.rc = TLDAP_NO_MEMORY;
1308                 goto fail;
1309         }
1310
1311         req = tldap_search_send(frame, ev, ld, base, scope, filter,
1312                                 attrs, num_attrs, attrsonly,
1313                                 sctrls, num_sctrls, cctrls, num_cctrls,
1314                                 timelimit, sizelimit, deref);
1315         if (req == NULL) {
1316                 state.rc = TLDAP_NO_MEMORY;
1317                 goto fail;
1318         }
1319
1320         tevent_req_set_callback(req, tldap_search_cb, &state);
1321
1322         while (tevent_req_is_in_progress(req)
1323                && (state.rc == TLDAP_SUCCESS)) {
1324                 if (tevent_loop_once(ev) == -1) {
1325                         return TLDAP_OPERATIONS_ERROR;
1326                 }
1327         }
1328
1329         if (state.rc != TLDAP_SUCCESS) {
1330                 return state.rc;
1331         }
1332
1333         if (entries != NULL) {
1334                 *entries = state.entries;
1335         } else {
1336                 TALLOC_FREE(state.entries);
1337         }
1338         if (refs != NULL) {
1339                 *refs = state.refs;
1340         } else {
1341                 TALLOC_FREE(state.refs);
1342         }
1343         tldap_save_msg(ld, req);
1344 fail:
1345         TALLOC_FREE(frame);
1346         return state.rc;
1347 }
1348
1349 static bool tldap_parse_search_entry(struct tldap_message *msg)
1350 {
1351         int num_attribs = 0;
1352
1353         asn1_start_tag(msg->data, msg->type);
1354
1355         /* dn */
1356
1357         asn1_read_OctetString_talloc(msg, msg->data, &msg->dn);
1358         if (msg->dn == NULL) {
1359                 return false;
1360         }
1361
1362         /*
1363          * Attributes: We overallocate msg->attribs by one, so that while
1364          * looping over the attributes we can directly parse into the last
1365          * array element. Same for the values in the inner loop.
1366          */
1367
1368         msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
1369         if (msg->attribs == NULL) {
1370                 return false;
1371         }
1372
1373         asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1374         while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
1375                 struct tldap_attribute *attrib;
1376                 int num_values = 0;
1377
1378                 attrib = &msg->attribs[num_attribs];
1379                 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
1380                 if (attrib->values == NULL) {
1381                         return false;
1382                 }
1383                 asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1384                 asn1_read_OctetString_talloc(msg->attribs, msg->data,
1385                                              &attrib->name);
1386                 asn1_start_tag(msg->data, ASN1_SET);
1387
1388                 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
1389                         asn1_read_OctetString(msg->data, msg,
1390                                               &attrib->values[num_values]);
1391
1392                         attrib->values = talloc_realloc(
1393                                 msg->attribs, attrib->values, DATA_BLOB,
1394                                 num_values + 2);
1395                         if (attrib->values == NULL) {
1396                                 return false;
1397                         }
1398                         num_values += 1;
1399                 }
1400                 attrib->values = talloc_realloc(msg->attribs, attrib->values,
1401                                                 DATA_BLOB, num_values);
1402                 attrib->num_values = num_values;
1403
1404                 asn1_end_tag(msg->data); /* ASN1_SET */
1405                 asn1_end_tag(msg->data); /* ASN1_SEQUENCE(0) */
1406                 msg->attribs = talloc_realloc(
1407                         msg, msg->attribs, struct tldap_attribute,
1408                         num_attribs + 2);
1409                 if (msg->attribs == NULL) {
1410                         return false;
1411                 }
1412                 num_attribs += 1;
1413         }
1414         msg->attribs = talloc_realloc(
1415                 msg, msg->attribs, struct tldap_attribute, num_attribs);
1416         asn1_end_tag(msg->data);
1417         if (msg->data->has_error) {
1418                 return false;
1419         }
1420         return true;
1421 }
1422
1423 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
1424 {
1425         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1426                 return false;
1427         }
1428         *dn = msg->dn;
1429         return true;
1430 }
1431
1432 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
1433                             struct tldap_attribute **attributes)
1434 {
1435         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1436                 return false;
1437         }
1438         *attributes = msg->attribs;
1439         *num_attributes = talloc_array_length(msg->attribs);
1440         return true;
1441 }
1442
1443 static bool tldap_decode_controls(struct tldap_req_state *state)
1444 {
1445         struct tldap_message *msg = state->result;
1446         struct asn1_data *data = msg->data;
1447         struct tldap_control *sctrls = NULL;
1448         int num_controls = 0;
1449
1450         msg->res_sctrls = NULL;
1451
1452         if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1453                 return true;
1454         }
1455
1456         asn1_start_tag(data, ASN1_CONTEXT(0));
1457
1458         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1459                 struct tldap_control *c;
1460                 char *oid = NULL;
1461
1462                 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
1463                                         num_controls + 1);
1464                 if (sctrls == NULL) {
1465                         return false;
1466                 }
1467                 c = &sctrls[num_controls];
1468
1469                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1470                 asn1_read_OctetString_talloc(msg, data, &oid);
1471                 if ((data->has_error) || (oid == NULL)) {
1472                         return false;
1473                 }
1474                 c->oid = oid;
1475                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1476                         asn1_read_BOOLEAN(data, &c->critical);
1477                 } else {
1478                         c->critical = false;
1479                 }
1480                 c->value = data_blob_null;
1481                 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
1482                     !asn1_read_OctetString(data, msg, &c->value)) {
1483                         return false;
1484                 }
1485                 asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
1486
1487                 num_controls += 1;
1488         }
1489
1490         asn1_end_tag(data);     /* ASN1_CONTEXT(0) */
1491
1492         if (data->has_error) {
1493                 TALLOC_FREE(sctrls);
1494                 return false;
1495         }
1496         msg->res_sctrls = sctrls;
1497         return true;
1498 }
1499
1500 static void tldap_simple_done(struct tevent_req *subreq, int type)
1501 {
1502         struct tevent_req *req = tevent_req_callback_data(
1503                 subreq, struct tevent_req);
1504         struct tldap_req_state *state = tevent_req_data(
1505                 req, struct tldap_req_state);
1506         int err;
1507
1508         err = tldap_msg_recv(subreq, state, &state->result);
1509         TALLOC_FREE(subreq);
1510         if (err != TLDAP_SUCCESS) {
1511                 tevent_req_error(req, err);
1512                 return;
1513         }
1514         if (state->result->type != type) {
1515                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1516                 return;
1517         }
1518         if (!asn1_start_tag(state->result->data, state->result->type) ||
1519             !tldap_decode_response(state) ||
1520             !asn1_end_tag(state->result->data) ||
1521             !tldap_decode_controls(state)) {
1522                 tevent_req_error(req, TLDAP_DECODING_ERROR);
1523                 return;
1524         }
1525         if (state->result->lderr != TLDAP_SUCCESS) {
1526                 tevent_req_error(req, state->result->lderr);
1527                 return;
1528         }
1529         tevent_req_done(req);
1530 }
1531
1532 static int tldap_simple_recv(struct tevent_req *req)
1533 {
1534         int err;
1535         if (tevent_req_is_ldap_error(req, &err)) {
1536                 return err;
1537         }
1538         return TLDAP_SUCCESS;
1539 }
1540
1541 static void tldap_add_done(struct tevent_req *subreq);
1542
1543 struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
1544                                   struct tevent_context *ev,
1545                                   struct tldap_context *ld,
1546                                   const char *dn,
1547                                   struct tldap_mod *attributes,
1548                                   int num_attributes,
1549                                   struct tldap_control *sctrls,
1550                                   int num_sctrls,
1551                                   struct tldap_control *cctrls,
1552                                   int num_cctrls)
1553 {
1554         struct tevent_req *req, *subreq;
1555         struct tldap_req_state *state;
1556         int i, j;
1557
1558         req = tldap_req_create(mem_ctx, ld, &state);
1559         if (req == NULL) {
1560                 return NULL;
1561         }
1562
1563         asn1_push_tag(state->out, TLDAP_REQ_ADD);
1564         asn1_write_OctetString(state->out, dn, strlen(dn));
1565         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1566
1567         for (i=0; i<num_attributes; i++) {
1568                 struct tldap_mod *attrib = &attributes[i];
1569                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1570                 asn1_write_OctetString(state->out, attrib->attribute,
1571                                        strlen(attrib->attribute));
1572                 asn1_push_tag(state->out, ASN1_SET);
1573                 for (j=0; j<attrib->num_values; j++) {
1574                         asn1_write_OctetString(state->out,
1575                                                attrib->values[j].data,
1576                                                attrib->values[j].length);
1577                 }
1578                 asn1_pop_tag(state->out);
1579                 asn1_pop_tag(state->out);
1580         }
1581
1582         asn1_pop_tag(state->out);
1583         asn1_pop_tag(state->out);
1584
1585         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1586                                 sctrls, num_sctrls);
1587         if (tevent_req_nomem(subreq, req)) {
1588                 return tevent_req_post(req, ev);
1589         }
1590         tevent_req_set_callback(subreq, tldap_add_done, req);
1591         return req;
1592 }
1593
1594 static void tldap_add_done(struct tevent_req *subreq)
1595 {
1596         return tldap_simple_done(subreq, TLDAP_RES_ADD);
1597 }
1598
1599 int tldap_add_recv(struct tevent_req *req)
1600 {
1601         return tldap_simple_recv(req);
1602 }
1603
1604 int tldap_add(struct tldap_context *ld, const char *dn,
1605               int num_attributes, struct tldap_mod *attributes,
1606               struct tldap_control *sctrls, int num_sctrls,
1607               struct tldap_control *cctrls, int num_cctrls)
1608 {
1609         TALLOC_CTX *frame = talloc_stackframe();
1610         struct tevent_context *ev;
1611         struct tevent_req *req;
1612         int result;
1613
1614         ev = event_context_init(frame);
1615         if (ev == NULL) {
1616                 result = TLDAP_NO_MEMORY;
1617                 goto fail;
1618         }
1619
1620         req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
1621                              sctrls, num_sctrls, cctrls, num_cctrls);
1622         if (req == NULL) {
1623                 result = TLDAP_NO_MEMORY;
1624                 goto fail;
1625         }
1626
1627         if (!tevent_req_poll(req, ev)) {
1628                 result = TLDAP_OPERATIONS_ERROR;
1629                 goto fail;
1630         }
1631
1632         result = tldap_add_recv(req);
1633         tldap_save_msg(ld, req);
1634  fail:
1635         TALLOC_FREE(frame);
1636         return result;
1637 }
1638
1639 static void tldap_modify_done(struct tevent_req *subreq);
1640
1641 struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
1642                                      struct tevent_context *ev,
1643                                      struct tldap_context *ld,
1644                                      const char *dn,
1645                                      int num_mods, struct tldap_mod *mods,
1646                                      struct tldap_control *sctrls,
1647                                      int num_sctrls,
1648                                      struct tldap_control *cctrls,
1649                                      int num_cctrls)
1650 {
1651         struct tevent_req *req, *subreq;
1652         struct tldap_req_state *state;
1653         int i, j;
1654
1655         req = tldap_req_create(mem_ctx, ld, &state);
1656         if (req == NULL) {
1657                 return NULL;
1658         }
1659
1660         asn1_push_tag(state->out, TLDAP_REQ_MODIFY);
1661         asn1_write_OctetString(state->out, dn, strlen(dn));
1662         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1663
1664         for (i=0; i<num_mods; i++) {
1665                 struct tldap_mod *mod = &mods[i];
1666                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1667                 asn1_write_enumerated(state->out, mod->mod_op),
1668                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1669                 asn1_write_OctetString(state->out, mod->attribute,
1670                                        strlen(mod->attribute));
1671                 asn1_push_tag(state->out, ASN1_SET);
1672                 for (j=0; j<mod->num_values; j++) {
1673                         asn1_write_OctetString(state->out,
1674                                                mod->values[j].data,
1675                                                mod->values[j].length);
1676                 }
1677                 asn1_pop_tag(state->out);
1678                 asn1_pop_tag(state->out);
1679                 asn1_pop_tag(state->out);
1680         }
1681
1682         asn1_pop_tag(state->out);
1683         asn1_pop_tag(state->out);
1684
1685         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1686                                 sctrls, num_sctrls);
1687         if (tevent_req_nomem(subreq, req)) {
1688                 return tevent_req_post(req, ev);
1689         }
1690         tevent_req_set_callback(subreq, tldap_modify_done, req);
1691         return req;
1692 }
1693
1694 static void tldap_modify_done(struct tevent_req *subreq)
1695 {
1696         return tldap_simple_done(subreq, TLDAP_RES_MODIFY);
1697 }
1698
1699 int tldap_modify_recv(struct tevent_req *req)
1700 {
1701         return tldap_simple_recv(req);
1702 }
1703
1704 int tldap_modify(struct tldap_context *ld, const char *dn,
1705                  int num_mods, struct tldap_mod *mods,
1706                  struct tldap_control *sctrls, int num_sctrls,
1707                  struct tldap_control *cctrls, int num_cctrls)
1708  {
1709         TALLOC_CTX *frame = talloc_stackframe();
1710         struct tevent_context *ev;
1711         struct tevent_req *req;
1712         int result;
1713
1714         ev = event_context_init(frame);
1715         if (ev == NULL) {
1716                 result = TLDAP_NO_MEMORY;
1717                 goto fail;
1718         }
1719
1720         req = tldap_modify_send(frame, ev, ld, dn, num_mods, mods,
1721                                 sctrls, num_sctrls, cctrls, num_cctrls);
1722         if (req == NULL) {
1723                 result = TLDAP_NO_MEMORY;
1724                 goto fail;
1725         }
1726
1727         if (!tevent_req_poll(req, ev)) {
1728                 result = TLDAP_OPERATIONS_ERROR;
1729                 goto fail;
1730         }
1731
1732         result = tldap_modify_recv(req);
1733         tldap_save_msg(ld, req);
1734  fail:
1735         TALLOC_FREE(frame);
1736         return result;
1737 }
1738
1739 static void tldap_delete_done(struct tevent_req *subreq);
1740
1741 struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
1742                                      struct tevent_context *ev,
1743                                      struct tldap_context *ld,
1744                                      const char *dn,
1745                                      struct tldap_control *sctrls,
1746                                      int num_sctrls,
1747                                      struct tldap_control *cctrls,
1748                                      int num_cctrls)
1749 {
1750         struct tevent_req *req, *subreq;
1751         struct tldap_req_state *state;
1752
1753         req = tldap_req_create(mem_ctx, ld, &state);
1754         if (req == NULL) {
1755                 return NULL;
1756         }
1757
1758         asn1_push_tag(state->out, TLDAP_REQ_DELETE);
1759         asn1_write(state->out, dn, strlen(dn));
1760         asn1_pop_tag(state->out);
1761
1762         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1763                                 sctrls, num_sctrls);
1764         if (tevent_req_nomem(subreq, req)) {
1765                 return tevent_req_post(req, ev);
1766         }
1767         tevent_req_set_callback(subreq, tldap_delete_done, req);
1768         return req;
1769 }
1770
1771 static void tldap_delete_done(struct tevent_req *subreq)
1772 {
1773         return tldap_simple_done(subreq, TLDAP_RES_DELETE);
1774 }
1775
1776 int tldap_delete_recv(struct tevent_req *req)
1777 {
1778         return tldap_simple_recv(req);
1779 }
1780
1781 int tldap_delete(struct tldap_context *ld, const char *dn,
1782                  struct tldap_control *sctrls, int num_sctrls,
1783                  struct tldap_control *cctrls, int num_cctrls)
1784 {
1785         TALLOC_CTX *frame = talloc_stackframe();
1786         struct tevent_context *ev;
1787         struct tevent_req *req;
1788         int result;
1789
1790         ev = event_context_init(frame);
1791         if (ev == NULL) {
1792                 result = TLDAP_NO_MEMORY;
1793                 goto fail;
1794         }
1795
1796         req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
1797                                 cctrls, num_cctrls);
1798         if (req == NULL) {
1799                 result = TLDAP_NO_MEMORY;
1800                 goto fail;
1801         }
1802
1803         if (!tevent_req_poll(req, ev)) {
1804                 result = TLDAP_OPERATIONS_ERROR;
1805                 goto fail;
1806         }
1807
1808         result = tldap_delete_recv(req);
1809         tldap_save_msg(ld, req);
1810  fail:
1811         TALLOC_FREE(frame);
1812         return result;
1813 }
1814
1815 int tldap_msg_id(const struct tldap_message *msg)
1816 {
1817         return msg->id;
1818 }
1819
1820 int tldap_msg_type(const struct tldap_message *msg)
1821 {
1822         return msg->type;
1823 }
1824
1825 const char *tldap_msg_matcheddn(struct tldap_message *msg)
1826 {
1827         if (msg == NULL) {
1828                 return NULL;
1829         }
1830         return msg->res_matcheddn;
1831 }
1832
1833 const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
1834 {
1835         if (msg == NULL) {
1836                 return NULL;
1837         }
1838         return msg->res_diagnosticmessage;
1839 }
1840
1841 const char *tldap_msg_referral(struct tldap_message *msg)
1842 {
1843         if (msg == NULL) {
1844                 return NULL;
1845         }
1846         return msg->res_referral;
1847 }
1848
1849 void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
1850                       struct tldap_control **sctrls)
1851 {
1852         if (msg == NULL) {
1853                 *sctrls = NULL;
1854                 *num_sctrls = 0;
1855         }
1856         *sctrls = msg->res_sctrls;
1857         *num_sctrls = talloc_array_length(msg->res_sctrls);
1858 }
1859
1860 struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
1861 {
1862         return ld->last_msg;
1863 }
1864
1865 const char *tldap_err2string(int rc)
1866 {
1867         const char *res = NULL;
1868
1869         /*
1870          * This would normally be a table, but the error codes are not fully
1871          * sequential. Let the compiler figure out the optimum implementation
1872          * :-)
1873          */
1874
1875         switch (rc) {
1876         case TLDAP_SUCCESS:
1877                 res = "TLDAP_SUCCESS";
1878                 break;
1879         case TLDAP_OPERATIONS_ERROR:
1880                 res = "TLDAP_OPERATIONS_ERROR";
1881                 break;
1882         case TLDAP_PROTOCOL_ERROR:
1883                 res = "TLDAP_PROTOCOL_ERROR";
1884                 break;
1885         case TLDAP_TIMELIMIT_EXCEEDED:
1886                 res = "TLDAP_TIMELIMIT_EXCEEDED";
1887                 break;
1888         case TLDAP_SIZELIMIT_EXCEEDED:
1889                 res = "TLDAP_SIZELIMIT_EXCEEDED";
1890                 break;
1891         case TLDAP_COMPARE_FALSE:
1892                 res = "TLDAP_COMPARE_FALSE";
1893                 break;
1894         case TLDAP_COMPARE_TRUE:
1895                 res = "TLDAP_COMPARE_TRUE";
1896                 break;
1897         case TLDAP_STRONG_AUTH_NOT_SUPPORTED:
1898                 res = "TLDAP_STRONG_AUTH_NOT_SUPPORTED";
1899                 break;
1900         case TLDAP_STRONG_AUTH_REQUIRED:
1901                 res = "TLDAP_STRONG_AUTH_REQUIRED";
1902                 break;
1903         case TLDAP_REFERRAL:
1904                 res = "TLDAP_REFERRAL";
1905                 break;
1906         case TLDAP_ADMINLIMIT_EXCEEDED:
1907                 res = "TLDAP_ADMINLIMIT_EXCEEDED";
1908                 break;
1909         case TLDAP_UNAVAILABLE_CRITICAL_EXTENSION:
1910                 res = "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION";
1911                 break;
1912         case TLDAP_CONFIDENTIALITY_REQUIRED:
1913                 res = "TLDAP_CONFIDENTIALITY_REQUIRED";
1914                 break;
1915         case TLDAP_SASL_BIND_IN_PROGRESS:
1916                 res = "TLDAP_SASL_BIND_IN_PROGRESS";
1917                 break;
1918         case TLDAP_NO_SUCH_ATTRIBUTE:
1919                 res = "TLDAP_NO_SUCH_ATTRIBUTE";
1920                 break;
1921         case TLDAP_UNDEFINED_TYPE:
1922                 res = "TLDAP_UNDEFINED_TYPE";
1923                 break;
1924         case TLDAP_INAPPROPRIATE_MATCHING:
1925                 res = "TLDAP_INAPPROPRIATE_MATCHING";
1926                 break;
1927         case TLDAP_CONSTRAINT_VIOLATION:
1928                 res = "TLDAP_CONSTRAINT_VIOLATION";
1929                 break;
1930         case TLDAP_TYPE_OR_VALUE_EXISTS:
1931                 res = "TLDAP_TYPE_OR_VALUE_EXISTS";
1932                 break;
1933         case TLDAP_INVALID_SYNTAX:
1934                 res = "TLDAP_INVALID_SYNTAX";
1935                 break;
1936         case TLDAP_NO_SUCH_OBJECT:
1937                 res = "TLDAP_NO_SUCH_OBJECT";
1938                 break;
1939         case TLDAP_ALIAS_PROBLEM:
1940                 res = "TLDAP_ALIAS_PROBLEM";
1941                 break;
1942         case TLDAP_INVALID_DN_SYNTAX:
1943                 res = "TLDAP_INVALID_DN_SYNTAX";
1944                 break;
1945         case TLDAP_IS_LEAF:
1946                 res = "TLDAP_IS_LEAF";
1947                 break;
1948         case TLDAP_ALIAS_DEREF_PROBLEM:
1949                 res = "TLDAP_ALIAS_DEREF_PROBLEM";
1950                 break;
1951         case TLDAP_INAPPROPRIATE_AUTH:
1952                 res = "TLDAP_INAPPROPRIATE_AUTH";
1953                 break;
1954         case TLDAP_INVALID_CREDENTIALS:
1955                 res = "TLDAP_INVALID_CREDENTIALS";
1956                 break;
1957         case TLDAP_INSUFFICIENT_ACCESS:
1958                 res = "TLDAP_INSUFFICIENT_ACCESS";
1959                 break;
1960         case TLDAP_BUSY:
1961                 res = "TLDAP_BUSY";
1962                 break;
1963         case TLDAP_UNAVAILABLE:
1964                 res = "TLDAP_UNAVAILABLE";
1965                 break;
1966         case TLDAP_UNWILLING_TO_PERFORM:
1967                 res = "TLDAP_UNWILLING_TO_PERFORM";
1968                 break;
1969         case TLDAP_LOOP_DETECT:
1970                 res = "TLDAP_LOOP_DETECT";
1971                 break;
1972         case TLDAP_NAMING_VIOLATION:
1973                 res = "TLDAP_NAMING_VIOLATION";
1974                 break;
1975         case TLDAP_OBJECT_CLASS_VIOLATION:
1976                 res = "TLDAP_OBJECT_CLASS_VIOLATION";
1977                 break;
1978         case TLDAP_NOT_ALLOWED_ON_NONLEAF:
1979                 res = "TLDAP_NOT_ALLOWED_ON_NONLEAF";
1980                 break;
1981         case TLDAP_NOT_ALLOWED_ON_RDN:
1982                 res = "TLDAP_NOT_ALLOWED_ON_RDN";
1983                 break;
1984         case TLDAP_ALREADY_EXISTS:
1985                 res = "TLDAP_ALREADY_EXISTS";
1986                 break;
1987         case TLDAP_NO_OBJECT_CLASS_MODS:
1988                 res = "TLDAP_NO_OBJECT_CLASS_MODS";
1989                 break;
1990         case TLDAP_RESULTS_TOO_LARGE:
1991                 res = "TLDAP_RESULTS_TOO_LARGE";
1992                 break;
1993         case TLDAP_AFFECTS_MULTIPLE_DSAS:
1994                 res = "TLDAP_AFFECTS_MULTIPLE_DSAS";
1995                 break;
1996         case TLDAP_OTHER:
1997                 res = "TLDAP_OTHER";
1998                 break;
1999         case TLDAP_SERVER_DOWN:
2000                 res = "TLDAP_SERVER_DOWN";
2001                 break;
2002         case TLDAP_LOCAL_ERROR:
2003                 res = "TLDAP_LOCAL_ERROR";
2004                 break;
2005         case TLDAP_ENCODING_ERROR:
2006                 res = "TLDAP_ENCODING_ERROR";
2007                 break;
2008         case TLDAP_DECODING_ERROR:
2009                 res = "TLDAP_DECODING_ERROR";
2010                 break;
2011         case TLDAP_TIMEOUT:
2012                 res = "TLDAP_TIMEOUT";
2013                 break;
2014         case TLDAP_AUTH_UNKNOWN:
2015                 res = "TLDAP_AUTH_UNKNOWN";
2016                 break;
2017         case TLDAP_FILTER_ERROR:
2018                 res = "TLDAP_FILTER_ERROR";
2019                 break;
2020         case TLDAP_USER_CANCELLED:
2021                 res = "TLDAP_USER_CANCELLED";
2022                 break;
2023         case TLDAP_PARAM_ERROR:
2024                 res = "TLDAP_PARAM_ERROR";
2025                 break;
2026         case TLDAP_NO_MEMORY:
2027                 res = "TLDAP_NO_MEMORY";
2028                 break;
2029         case TLDAP_CONNECT_ERROR:
2030                 res = "TLDAP_CONNECT_ERROR";
2031                 break;
2032         case TLDAP_NOT_SUPPORTED:
2033                 res = "TLDAP_NOT_SUPPORTED";
2034                 break;
2035         case TLDAP_CONTROL_NOT_FOUND:
2036                 res = "TLDAP_CONTROL_NOT_FOUND";
2037                 break;
2038         case TLDAP_NO_RESULTS_RETURNED:
2039                 res = "TLDAP_NO_RESULTS_RETURNED";
2040                 break;
2041         case TLDAP_MORE_RESULTS_TO_RETURN:
2042                 res = "TLDAP_MORE_RESULTS_TO_RETURN";
2043                 break;
2044         case TLDAP_CLIENT_LOOP:
2045                 res = "TLDAP_CLIENT_LOOP";
2046                 break;
2047         case TLDAP_REFERRAL_LIMIT_EXCEEDED:
2048                 res = "TLDAP_REFERRAL_LIMIT_EXCEEDED";
2049                 break;
2050         default:
2051                 res = talloc_asprintf(talloc_tos(), "Unknown LDAP Error (%d)",
2052                                       rc);
2053                 break;
2054         }
2055         if (res == NULL) {
2056                 res = "Unknown LDAP Error";
2057         }
2058         return res;
2059 }