376e03f80c389f8d85f2070803559cbd2a5b644a
[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_destructor(req);
595         tevent_req_done(req);
596
597  done:
598         if (talloc_array_length(ld->pending) > 0) {
599                 state = tevent_req_data(ld->pending[0],
600                                         struct tldap_msg_state);
601                 subreq = read_ldap_send(ld->pending, state->ev, ld->fd);
602                 if (subreq == NULL) {
603                         status = TLDAP_NO_MEMORY;
604                         goto fail;
605                 }
606                 tevent_req_set_callback(subreq, tldap_msg_received, ld);
607         }
608         return;
609
610  fail:
611         while (talloc_array_length(ld->pending) > 0) {
612                 req = ld->pending[0];
613                 talloc_set_destructor(req, NULL);
614                 tldap_msg_destructor(req);
615                 tevent_req_error(req, status);
616         }
617 }
618
619 static int tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
620                           struct tldap_message **pmsg)
621 {
622         struct tldap_msg_state *state = tevent_req_data(
623                 req, struct tldap_msg_state);
624         struct tldap_message *msg;
625         int err;
626         uint8_t msgtype;
627
628         if (tevent_req_is_ldap_error(req, &err)) {
629                 return err;
630         }
631
632         if (!asn1_peek_uint8(state->data, &msgtype)) {
633                 return TLDAP_PROTOCOL_ERROR;
634         }
635
636         if (pmsg == NULL) {
637                 return TLDAP_SUCCESS;
638         }
639
640         msg = talloc_zero(mem_ctx, struct tldap_message);
641         if (msg == NULL) {
642                 return TLDAP_NO_MEMORY;
643         }
644         msg->id = state->id;
645
646         msg->inbuf = talloc_move(msg, &state->inbuf);
647         msg->data = talloc_move(msg, &state->data);
648         msg->type = msgtype;
649
650         *pmsg = msg;
651         return TLDAP_SUCCESS;
652 }
653
654 struct tldap_req_state {
655         int id;
656         struct asn1_data *out;
657         struct tldap_message *result;
658 };
659
660 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
661                                            struct tldap_context *ld,
662                                            struct tldap_req_state **pstate)
663 {
664         struct tevent_req *req;
665         struct tldap_req_state *state;
666
667         req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
668         if (req == NULL) {
669                 return NULL;
670         }
671         ZERO_STRUCTP(state);
672         state->out = asn1_init(state);
673         if (state->out == NULL) {
674                 TALLOC_FREE(req);
675                 return NULL;
676         }
677         state->result = NULL;
678         state->id = tldap_next_msgid(ld);
679
680         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
681         asn1_write_Integer(state->out, state->id);
682
683         *pstate = state;
684         return req;
685 }
686
687 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
688 {
689         struct tldap_req_state *state = tevent_req_data(
690                 req, struct tldap_req_state);
691
692         TALLOC_FREE(ld->last_msg);
693         ld->last_msg = talloc_move(ld, &state->result);
694 }
695
696 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
697 {
698         char *result = talloc_array(mem_ctx, char, blob.length+1);
699         memcpy(result, blob.data, blob.length);
700         result[blob.length] = '\0';
701         return result;
702 }
703
704 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
705                                          struct asn1_data *data,
706                                          char **result)
707 {
708         DATA_BLOB string;
709         if (!asn1_read_OctetString(data, mem_ctx, &string))
710                 return false;
711         *result = blob2string_talloc(mem_ctx, string);
712         data_blob_free(&string);
713         return true;
714 }
715
716 static bool tldap_decode_controls(struct tldap_req_state *state);
717
718 static bool tldap_decode_response(struct tldap_req_state *state)
719 {
720         struct asn1_data *data = state->result->data;
721         struct tldap_message *msg = state->result;
722         bool ok = true;
723
724         ok &= asn1_read_enumerated(data, &msg->lderr);
725         ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
726         ok &= asn1_read_OctetString_talloc(msg, data,
727                                            &msg->res_diagnosticmessage);
728         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
729                 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
730                 ok &= asn1_read_OctetString_talloc(msg, data,
731                                                    &msg->res_referral);
732                 ok &= asn1_end_tag(data);
733         } else {
734                 msg->res_referral = NULL;
735         }
736
737         return ok;
738 }
739
740 static void tldap_sasl_bind_done(struct tevent_req *subreq);
741
742 struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
743                                         struct tevent_context *ev,
744                                         struct tldap_context *ld,
745                                         const char *dn,
746                                         const char *mechanism,
747                                         DATA_BLOB *creds,
748                                         struct tldap_control *sctrls,
749                                         int num_sctrls,
750                                         struct tldap_control *cctrls,
751                                         int num_cctrls)
752 {
753         struct tevent_req *req, *subreq;
754         struct tldap_req_state *state;
755
756         req = tldap_req_create(mem_ctx, ld, &state);
757         if (req == NULL) {
758                 return NULL;
759         }
760
761         if (dn == NULL) {
762                 dn = "";
763         }
764
765         asn1_push_tag(state->out, TLDAP_REQ_BIND);
766         asn1_write_Integer(state->out, ld->ld_version);
767         asn1_write_OctetString(state->out, dn, (dn != NULL) ? strlen(dn) : 0);
768
769         if (mechanism == NULL) {
770                 asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0));
771                 asn1_write(state->out, creds->data, creds->length);
772                 asn1_pop_tag(state->out);
773         } else {
774                 asn1_push_tag(state->out, ASN1_CONTEXT(3));
775                 asn1_write_OctetString(state->out, mechanism,
776                                        strlen(mechanism));
777                 if ((creds != NULL) && (creds->data != NULL)) {
778                         asn1_write_OctetString(state->out, creds->data,
779                                                creds->length);
780                 }
781                 asn1_pop_tag(state->out);
782         }
783
784         if (!asn1_pop_tag(state->out)) {
785                 tevent_req_error(req, TLDAP_ENCODING_ERROR);
786                 return tevent_req_post(req, ev);
787         }
788
789         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
790                                 sctrls, num_sctrls);
791         if (tevent_req_nomem(subreq, req)) {
792                 return tevent_req_post(req, ev);
793         }
794         tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
795         return req;
796 }
797
798 static void tldap_sasl_bind_done(struct tevent_req *subreq)
799 {
800         struct tevent_req *req = tevent_req_callback_data(
801                 subreq, struct tevent_req);
802         struct tldap_req_state *state = tevent_req_data(
803                 req, struct tldap_req_state);
804         int err;
805
806         err = tldap_msg_recv(subreq, state, &state->result);
807         TALLOC_FREE(subreq);
808         if (err != TLDAP_SUCCESS) {
809                 tevent_req_error(req, err);
810                 return;
811         }
812         if (state->result->type != TLDAP_RES_BIND) {
813                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
814                 return;
815         }
816         if (!asn1_start_tag(state->result->data, state->result->type) ||
817             !tldap_decode_response(state) ||
818             !asn1_end_tag(state->result->data)) {
819                 tevent_req_error(req, TLDAP_DECODING_ERROR);
820                 return;
821         }
822         /*
823          * TODO: pull the reply blob
824          */
825         if (state->result->lderr != TLDAP_SUCCESS) {
826                 tevent_req_error(req, state->result->lderr);
827                 return;
828         }
829         tevent_req_done(req);
830 }
831
832 int tldap_sasl_bind_recv(struct tevent_req *req)
833 {
834         int err;
835
836         if (tevent_req_is_ldap_error(req, &err)) {
837                 return err;
838         }
839         return TLDAP_SUCCESS;
840 }
841
842 int tldap_sasl_bind(struct tldap_context *ld,
843                     const char *dn,
844                     const char *mechanism,
845                     DATA_BLOB *creds,
846                     struct tldap_control *sctrls,
847                     int num_sctrls,
848                     struct tldap_control *cctrls,
849                     int num_cctrls)
850 {
851         TALLOC_CTX *frame = talloc_stackframe();
852         struct tevent_context *ev;
853         struct tevent_req *req;
854         int result;
855
856         ev = event_context_init(frame);
857         if (ev == NULL) {
858                 result = TLDAP_NO_MEMORY;
859                 goto fail;
860         }
861
862         req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
863                                    sctrls, num_sctrls, cctrls, num_cctrls);
864         if (req == NULL) {
865                 result = TLDAP_NO_MEMORY;
866                 goto fail;
867         }
868
869         if (!tevent_req_poll(req, ev)) {
870                 result = TLDAP_OPERATIONS_ERROR;
871                 goto fail;
872         }
873
874         result = tldap_sasl_bind_recv(req);
875         tldap_save_msg(ld, req);
876  fail:
877         TALLOC_FREE(frame);
878         return result;
879 }
880
881 struct tevent_req *tldap_simple_bind_send(TALLOC_CTX *mem_ctx,
882                                           struct tevent_context *ev,
883                                           struct tldap_context *ld,
884                                           const char *dn,
885                                           const char *passwd)
886 {
887         DATA_BLOB cred;
888
889         if (passwd != NULL) {
890                 cred.data = (uint8_t *)passwd;
891                 cred.length = strlen(passwd);
892         } else {
893                 cred.data = (uint8_t *)"";
894                 cred.length = 0;
895         }
896         return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
897                                     NULL, 0);
898 }
899
900 int tldap_simple_bind_recv(struct tevent_req *req)
901 {
902         return tldap_sasl_bind_recv(req);
903 }
904
905 int tldap_simple_bind(struct tldap_context *ld, const char *dn,
906                       const char *passwd)
907 {
908         DATA_BLOB cred;
909
910         if (passwd != NULL) {
911                 cred.data = (uint8_t *)passwd;
912                 cred.length = strlen(passwd);
913         } else {
914                 cred.data = (uint8_t *)"";
915                 cred.length = 0;
916         }
917         return tldap_sasl_bind(ld, dn, NULL, &cred, NULL, 0, NULL, 0);
918 }
919
920 /*****************************************************************************/
921
922 /*
923  * This piece has a dependency on ldb, the ldb_parse_tree() function is used.
924  * In case we want to separate out tldap, we need to copy or rewrite it.
925  */
926
927 #include "lib/ldb/include/ldb.h"
928 #include "lib/ldb/include/ldb_errors.h"
929
930 static bool ldap_push_filter(struct asn1_data *data,
931                              struct ldb_parse_tree *tree)
932 {
933         int i;
934
935         switch (tree->operation) {
936         case LDB_OP_AND:
937         case LDB_OP_OR:
938                 asn1_push_tag(data,
939                               ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
940                 for (i=0; i<tree->u.list.num_elements; i++) {
941                         if (!ldap_push_filter(data,
942                                               tree->u.list.elements[i])) {
943                                 return false;
944                         }
945                 }
946                 asn1_pop_tag(data);
947                 break;
948
949         case LDB_OP_NOT:
950                 asn1_push_tag(data, ASN1_CONTEXT(2));
951                 if (!ldap_push_filter(data, tree->u.isnot.child)) {
952                         return false;
953                 }
954                 asn1_pop_tag(data);
955                 break;
956
957         case LDB_OP_EQUALITY:
958                 /* equality test */
959                 asn1_push_tag(data, ASN1_CONTEXT(3));
960                 asn1_write_OctetString(data, tree->u.equality.attr,
961                                       strlen(tree->u.equality.attr));
962                 asn1_write_OctetString(data, tree->u.equality.value.data,
963                                       tree->u.equality.value.length);
964                 asn1_pop_tag(data);
965                 break;
966
967         case LDB_OP_SUBSTRING:
968                 /*
969                   SubstringFilter ::= SEQUENCE {
970                           type            AttributeDescription,
971                           -- at least one must be present
972                           substrings      SEQUENCE OF CHOICE {
973                                   initial [0] LDAPString,
974                                   any     [1] LDAPString,
975                                   final   [2] LDAPString } }
976                 */
977                 asn1_push_tag(data, ASN1_CONTEXT(4));
978                 asn1_write_OctetString(data, tree->u.substring.attr,
979                                        strlen(tree->u.substring.attr));
980                 asn1_push_tag(data, ASN1_SEQUENCE(0));
981                 i = 0;
982                 if (!tree->u.substring.start_with_wildcard) {
983                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
984                         asn1_write_DATA_BLOB_LDAPString(
985                                 data, tree->u.substring.chunks[i]);
986                         asn1_pop_tag(data);
987                         i++;
988                 }
989                 while (tree->u.substring.chunks[i]) {
990                         int ctx;
991
992                         if ((!tree->u.substring.chunks[i + 1]) &&
993                             (tree->u.substring.end_with_wildcard == 0)) {
994                                 ctx = 2;
995                         } else {
996                                 ctx = 1;
997                         }
998                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
999                         asn1_write_DATA_BLOB_LDAPString(
1000                                 data, tree->u.substring.chunks[i]);
1001                         asn1_pop_tag(data);
1002                         i++;
1003                 }
1004                 asn1_pop_tag(data);
1005                 asn1_pop_tag(data);
1006                 break;
1007
1008         case LDB_OP_GREATER:
1009                 /* greaterOrEqual test */
1010                 asn1_push_tag(data, ASN1_CONTEXT(5));
1011                 asn1_write_OctetString(data, tree->u.comparison.attr,
1012                                       strlen(tree->u.comparison.attr));
1013                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1014                                       tree->u.comparison.value.length);
1015                 asn1_pop_tag(data);
1016                 break;
1017
1018         case LDB_OP_LESS:
1019                 /* lessOrEqual test */
1020                 asn1_push_tag(data, ASN1_CONTEXT(6));
1021                 asn1_write_OctetString(data, tree->u.comparison.attr,
1022                                       strlen(tree->u.comparison.attr));
1023                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1024                                       tree->u.comparison.value.length);
1025                 asn1_pop_tag(data);
1026                 break;
1027
1028         case LDB_OP_PRESENT:
1029                 /* present test */
1030                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
1031                 asn1_write_LDAPString(data, tree->u.present.attr);
1032                 asn1_pop_tag(data);
1033                 return !data->has_error;
1034
1035         case LDB_OP_APPROX:
1036                 /* approx test */
1037                 asn1_push_tag(data, ASN1_CONTEXT(8));
1038                 asn1_write_OctetString(data, tree->u.comparison.attr,
1039                                       strlen(tree->u.comparison.attr));
1040                 asn1_write_OctetString(data, tree->u.comparison.value.data,
1041                                       tree->u.comparison.value.length);
1042                 asn1_pop_tag(data);
1043                 break;
1044
1045         case LDB_OP_EXTENDED:
1046                 /*
1047                   MatchingRuleAssertion ::= SEQUENCE {
1048                   matchingRule    [1] MatchingRuleID OPTIONAL,
1049                   type            [2] AttributeDescription OPTIONAL,
1050                   matchValue      [3] AssertionValue,
1051                   dnAttributes    [4] BOOLEAN DEFAULT FALSE
1052                   }
1053                 */
1054                 asn1_push_tag(data, ASN1_CONTEXT(9));
1055                 if (tree->u.extended.rule_id) {
1056                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
1057                         asn1_write_LDAPString(data, tree->u.extended.rule_id);
1058                         asn1_pop_tag(data);
1059                 }
1060                 if (tree->u.extended.attr) {
1061                         asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
1062                         asn1_write_LDAPString(data, tree->u.extended.attr);
1063                         asn1_pop_tag(data);
1064                 }
1065                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
1066                 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
1067                 asn1_pop_tag(data);
1068                 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
1069                 asn1_write_uint8(data, tree->u.extended.dnAttributes);
1070                 asn1_pop_tag(data);
1071                 asn1_pop_tag(data);
1072                 break;
1073
1074         default:
1075                 return false;
1076         }
1077         return !data->has_error;
1078 }
1079
1080 static bool tldap_push_filter(struct asn1_data *data, const char *filter)
1081 {
1082         struct ldb_parse_tree *tree;
1083         bool ret;
1084
1085         tree = ldb_parse_tree(talloc_tos(), filter);
1086         if (tree == NULL) {
1087                 return false;
1088         }
1089         ret = ldap_push_filter(data, tree);
1090         TALLOC_FREE(tree);
1091         return ret;
1092 }
1093
1094 /*****************************************************************************/
1095
1096 static void tldap_search_done(struct tevent_req *subreq);
1097
1098 struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
1099                                      struct tevent_context *ev,
1100                                      struct tldap_context *ld,
1101                                      const char *base, int scope,
1102                                      const char *filter,
1103                                      const char **attrs,
1104                                      int num_attrs,
1105                                      int attrsonly,
1106                                      struct tldap_control *sctrls,
1107                                      int num_sctrls,
1108                                      struct tldap_control *cctrls,
1109                                      int num_cctrls,
1110                                      int timelimit,
1111                                      int sizelimit,
1112                                      int deref)
1113 {
1114         struct tevent_req *req, *subreq;
1115         struct tldap_req_state *state;
1116         int i;
1117
1118         req = tldap_req_create(mem_ctx, ld, &state);
1119         if (req == NULL) {
1120                 return NULL;
1121         }
1122
1123         asn1_push_tag(state->out, TLDAP_REQ_SEARCH);
1124         asn1_write_OctetString(state->out, base, strlen(base));
1125         asn1_write_enumerated(state->out, scope);
1126         asn1_write_enumerated(state->out, deref);
1127         asn1_write_Integer(state->out, sizelimit);
1128         asn1_write_Integer(state->out, timelimit);
1129         asn1_write_BOOLEAN(state->out, attrsonly);
1130
1131         if (!tldap_push_filter(state->out, filter)) {
1132                 goto encoding_error;
1133         }
1134
1135         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1136         for (i=0; i<num_attrs; i++) {
1137                 asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]));
1138         }
1139         asn1_pop_tag(state->out);
1140         asn1_pop_tag(state->out);
1141
1142         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1143                                 sctrls, num_sctrls);
1144         if (tevent_req_nomem(subreq, req)) {
1145                 return tevent_req_post(req, ev);
1146         }
1147         tevent_req_set_callback(subreq, tldap_search_done, req);
1148         return req;
1149
1150  encoding_error:
1151         tevent_req_error(req, TLDAP_ENCODING_ERROR);
1152         return tevent_req_post(req, ev);
1153 }
1154
1155 static void tldap_search_done(struct tevent_req *subreq)
1156 {
1157         struct tevent_req *req = tevent_req_callback_data(
1158                 subreq, struct tevent_req);
1159         struct tldap_req_state *state = tevent_req_data(
1160                 req, struct tldap_req_state);
1161         int err;
1162
1163         err = tldap_msg_recv(subreq, state, &state->result);
1164         if (err != TLDAP_SUCCESS) {
1165                 tevent_req_error(req, err);
1166                 return;
1167         }
1168         switch (state->result->type) {
1169         case TLDAP_RES_SEARCH_ENTRY:
1170         case TLDAP_RES_SEARCH_REFERENCE:
1171                 tevent_req_notify_callback(req);
1172                 if (!tldap_msg_set_pending(subreq)) {
1173                         tevent_req_nomem(NULL, req);
1174                         return;
1175                 }
1176                 break;
1177         case TLDAP_RES_SEARCH_RESULT:
1178                 TALLOC_FREE(subreq);
1179                 if (!asn1_start_tag(state->result->data,
1180                                     state->result->type) ||
1181                     !tldap_decode_response(state) ||
1182                     !asn1_end_tag(state->result->data) ||
1183                     !tldap_decode_controls(state)) {
1184                         tevent_req_error(req, TLDAP_DECODING_ERROR);
1185                         return;
1186                 }
1187                 tevent_req_done(req);
1188                 break;
1189         default:
1190                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1191                 return;
1192         }
1193 }
1194
1195 int tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1196                       struct tldap_message **pmsg)
1197 {
1198         struct tldap_req_state *state = tevent_req_data(
1199                 req, struct tldap_req_state);
1200         int err;
1201
1202         if (!tevent_req_is_in_progress(req)
1203             && tevent_req_is_ldap_error(req, &err)) {
1204                 return err;
1205         }
1206
1207         if (tevent_req_is_in_progress(req)) {
1208                 switch (state->result->type) {
1209                 case TLDAP_RES_SEARCH_ENTRY:
1210                 case TLDAP_RES_SEARCH_REFERENCE:
1211                         break;
1212                 default:
1213                         return TLDAP_OPERATIONS_ERROR;
1214                 }
1215         }
1216
1217         *pmsg = talloc_move(mem_ctx, &state->result);
1218         return TLDAP_SUCCESS;
1219 }
1220
1221 struct tldap_sync_search_state {
1222         TALLOC_CTX *mem_ctx;
1223         struct tldap_message **entries;
1224         struct tldap_message **refs;
1225         int rc;
1226 };
1227
1228 static void tldap_search_cb(struct tevent_req *req)
1229 {
1230         struct tldap_sync_search_state *state =
1231                 (struct tldap_sync_search_state *)
1232                 tevent_req_callback_data_void(req);
1233         struct tldap_message *msg, **tmp;
1234         int rc, num_entries, num_refs;
1235
1236         rc = tldap_search_recv(req, talloc_tos(), &msg);
1237         if (rc != TLDAP_SUCCESS) {
1238                 state->rc = rc;
1239                 return;
1240         }
1241
1242         switch (tldap_msg_type(msg)) {
1243         case TLDAP_RES_SEARCH_ENTRY:
1244                 num_entries = talloc_array_length(state->entries);
1245                 tmp = talloc_realloc(state->mem_ctx, state->entries,
1246                                      struct tldap_message *, num_entries + 1);
1247                 if (tmp == NULL) {
1248                         state->rc = TLDAP_NO_MEMORY;
1249                         return;
1250                 }
1251                 state->entries = tmp;
1252                 state->entries[num_entries] = talloc_move(state->entries,
1253                                                           &msg);
1254                 break;
1255         case TLDAP_RES_SEARCH_REFERENCE:
1256                 num_refs = talloc_array_length(state->refs);
1257                 tmp = talloc_realloc(state->mem_ctx, state->refs,
1258                                      struct tldap_message *, num_refs + 1);
1259                 if (tmp == NULL) {
1260                         state->rc = TLDAP_NO_MEMORY;
1261                         return;
1262                 }
1263                 state->refs = tmp;
1264                 state->refs[num_refs] = talloc_move(state->refs, &msg);
1265                 break;
1266         case TLDAP_RES_SEARCH_RESULT:
1267                 state->rc = TLDAP_SUCCESS;
1268                 break;
1269         default:
1270                 state->rc = TLDAP_PROTOCOL_ERROR;
1271                 break;
1272         }
1273 }
1274
1275 int tldap_search(struct tldap_context *ld,
1276                  const char *base, int scope, const char *filter,
1277                  const char **attrs, int num_attrs, int attrsonly,
1278                  struct tldap_control *sctrls, int num_sctrls,
1279                  struct tldap_control *cctrls, int num_cctrls,
1280                  int timelimit, int sizelimit, int deref,
1281                  TALLOC_CTX *mem_ctx, struct tldap_message ***entries,
1282                  struct tldap_message ***refs)
1283 {
1284         TALLOC_CTX *frame = talloc_stackframe();
1285         struct tevent_context *ev;
1286         struct tevent_req *req;
1287         struct tldap_sync_search_state state;
1288
1289         ZERO_STRUCT(state);
1290         state.mem_ctx = mem_ctx;
1291         state.rc = TLDAP_SUCCESS;
1292
1293         ev = event_context_init(frame);
1294         if (ev == NULL) {
1295                 state.rc = TLDAP_NO_MEMORY;
1296                 goto fail;
1297         }
1298
1299         req = tldap_search_send(frame, ev, ld, base, scope, filter,
1300                                 attrs, num_attrs, attrsonly,
1301                                 sctrls, num_sctrls, cctrls, num_cctrls,
1302                                 timelimit, sizelimit, deref);
1303         if (req == NULL) {
1304                 state.rc = TLDAP_NO_MEMORY;
1305                 goto fail;
1306         }
1307
1308         tevent_req_set_callback(req, tldap_search_cb, &state);
1309
1310         while (tevent_req_is_in_progress(req)
1311                && (state.rc == TLDAP_SUCCESS)) {
1312                 if (tevent_loop_once(ev) == -1) {
1313                         return TLDAP_OPERATIONS_ERROR;
1314                 }
1315         }
1316
1317         if (state.rc != TLDAP_SUCCESS) {
1318                 return state.rc;
1319         }
1320
1321         if (entries != NULL) {
1322                 *entries = state.entries;
1323         } else {
1324                 TALLOC_FREE(state.entries);
1325         }
1326         if (refs != NULL) {
1327                 *refs = state.refs;
1328         } else {
1329                 TALLOC_FREE(state.refs);
1330         }
1331         tldap_save_msg(ld, req);
1332 fail:
1333         TALLOC_FREE(frame);
1334         return state.rc;
1335 }
1336
1337 static bool tldap_parse_search_entry(struct tldap_message *msg)
1338 {
1339         int num_attribs = 0;
1340
1341         asn1_start_tag(msg->data, msg->type);
1342
1343         /* dn */
1344
1345         asn1_read_OctetString_talloc(msg, msg->data, &msg->dn);
1346         if (msg->dn == NULL) {
1347                 return false;
1348         }
1349
1350         /*
1351          * Attributes: We overallocate msg->attribs by one, so that while
1352          * looping over the attributes we can directly parse into the last
1353          * array element. Same for the values in the inner loop.
1354          */
1355
1356         msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
1357         if (msg->attribs == NULL) {
1358                 return false;
1359         }
1360
1361         asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1362         while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
1363                 struct tldap_attribute *attrib;
1364                 int num_values = 0;
1365
1366                 attrib = &msg->attribs[num_attribs];
1367                 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
1368                 if (attrib->values == NULL) {
1369                         return false;
1370                 }
1371                 asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
1372                 asn1_read_OctetString_talloc(msg->attribs, msg->data,
1373                                              &attrib->name);
1374                 asn1_start_tag(msg->data, ASN1_SET);
1375
1376                 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
1377                         asn1_read_OctetString(msg->data, msg,
1378                                               &attrib->values[num_values]);
1379
1380                         attrib->values = talloc_realloc(
1381                                 msg->attribs, attrib->values, DATA_BLOB,
1382                                 num_values + 2);
1383                         if (attrib->values == NULL) {
1384                                 return false;
1385                         }
1386                         num_values += 1;
1387                 }
1388                 attrib->values = talloc_realloc(msg->attribs, attrib->values,
1389                                                 DATA_BLOB, num_values);
1390                 attrib->num_values = num_values;
1391
1392                 asn1_end_tag(msg->data); /* ASN1_SET */
1393                 asn1_end_tag(msg->data); /* ASN1_SEQUENCE(0) */
1394                 msg->attribs = talloc_realloc(
1395                         msg, msg->attribs, struct tldap_attribute,
1396                         num_attribs + 2);
1397                 if (msg->attribs == NULL) {
1398                         return false;
1399                 }
1400                 num_attribs += 1;
1401         }
1402         msg->attribs = talloc_realloc(
1403                 msg, msg->attribs, struct tldap_attribute, num_attribs);
1404         asn1_end_tag(msg->data);
1405         if (msg->data->has_error) {
1406                 return false;
1407         }
1408         return true;
1409 }
1410
1411 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
1412 {
1413         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1414                 return false;
1415         }
1416         *dn = msg->dn;
1417         return true;
1418 }
1419
1420 bool tldap_entry_attributes(struct tldap_message *msg, int *num_attributes,
1421                             struct tldap_attribute **attributes)
1422 {
1423         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
1424                 return false;
1425         }
1426         *attributes = msg->attribs;
1427         *num_attributes = talloc_array_length(msg->attribs);
1428         return true;
1429 }
1430
1431 static bool tldap_decode_controls(struct tldap_req_state *state)
1432 {
1433         struct tldap_message *msg = state->result;
1434         struct asn1_data *data = msg->data;
1435         struct tldap_control *sctrls = NULL;
1436         int num_controls = 0;
1437
1438         msg->res_sctrls = NULL;
1439
1440         if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1441                 return true;
1442         }
1443
1444         asn1_start_tag(data, ASN1_CONTEXT(0));
1445
1446         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1447                 struct tldap_control *c;
1448                 char *oid = NULL;
1449
1450                 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
1451                                         num_controls + 1);
1452                 if (sctrls == NULL) {
1453                         return false;
1454                 }
1455                 c = &sctrls[num_controls];
1456
1457                 asn1_start_tag(data, ASN1_SEQUENCE(0));
1458                 asn1_read_OctetString_talloc(msg, data, &oid);
1459                 if ((data->has_error) || (oid == NULL)) {
1460                         return false;
1461                 }
1462                 c->oid = oid;
1463                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
1464                         asn1_read_BOOLEAN(data, &c->critical);
1465                 } else {
1466                         c->critical = false;
1467                 }
1468                 c->value = data_blob_null;
1469                 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
1470                     !asn1_read_OctetString(data, msg, &c->value)) {
1471                         return false;
1472                 }
1473                 asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
1474
1475                 num_controls += 1;
1476         }
1477
1478         asn1_end_tag(data);     /* ASN1_CONTEXT(0) */
1479
1480         if (data->has_error) {
1481                 TALLOC_FREE(sctrls);
1482                 return false;
1483         }
1484         msg->res_sctrls = sctrls;
1485         return true;
1486 }
1487
1488 static void tldap_simple_done(struct tevent_req *subreq, int type)
1489 {
1490         struct tevent_req *req = tevent_req_callback_data(
1491                 subreq, struct tevent_req);
1492         struct tldap_req_state *state = tevent_req_data(
1493                 req, struct tldap_req_state);
1494         int err;
1495
1496         err = tldap_msg_recv(subreq, state, &state->result);
1497         TALLOC_FREE(subreq);
1498         if (err != TLDAP_SUCCESS) {
1499                 tevent_req_error(req, err);
1500                 return;
1501         }
1502         if (state->result->type != type) {
1503                 tevent_req_error(req, TLDAP_PROTOCOL_ERROR);
1504                 return;
1505         }
1506         if (!asn1_start_tag(state->result->data, state->result->type) ||
1507             !tldap_decode_response(state) ||
1508             !asn1_end_tag(state->result->data) ||
1509             !tldap_decode_controls(state)) {
1510                 tevent_req_error(req, TLDAP_DECODING_ERROR);
1511                 return;
1512         }
1513         if (state->result->lderr != TLDAP_SUCCESS) {
1514                 tevent_req_error(req, state->result->lderr);
1515                 return;
1516         }
1517         tevent_req_done(req);
1518 }
1519
1520 static int tldap_simple_recv(struct tevent_req *req)
1521 {
1522         int err;
1523         if (tevent_req_is_ldap_error(req, &err)) {
1524                 return err;
1525         }
1526         return TLDAP_SUCCESS;
1527 }
1528
1529 static void tldap_add_done(struct tevent_req *subreq);
1530
1531 struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
1532                                   struct tevent_context *ev,
1533                                   struct tldap_context *ld,
1534                                   const char *dn,
1535                                   struct tldap_mod *attributes,
1536                                   int num_attributes,
1537                                   struct tldap_control *sctrls,
1538                                   int num_sctrls,
1539                                   struct tldap_control *cctrls,
1540                                   int num_cctrls)
1541 {
1542         struct tevent_req *req, *subreq;
1543         struct tldap_req_state *state;
1544         int i, j;
1545
1546         req = tldap_req_create(mem_ctx, ld, &state);
1547         if (req == NULL) {
1548                 return NULL;
1549         }
1550
1551         asn1_push_tag(state->out, TLDAP_REQ_ADD);
1552         asn1_write_OctetString(state->out, dn, strlen(dn));
1553         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1554
1555         for (i=0; i<num_attributes; i++) {
1556                 struct tldap_mod *attrib = &attributes[i];
1557                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1558                 asn1_write_OctetString(state->out, attrib->attribute,
1559                                        strlen(attrib->attribute));
1560                 asn1_push_tag(state->out, ASN1_SET);
1561                 for (j=0; j<attrib->num_values; j++) {
1562                         asn1_write_OctetString(state->out,
1563                                                attrib->values[j].data,
1564                                                attrib->values[j].length);
1565                 }
1566                 asn1_pop_tag(state->out);
1567                 asn1_pop_tag(state->out);
1568         }
1569
1570         asn1_pop_tag(state->out);
1571         asn1_pop_tag(state->out);
1572
1573         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1574                                 sctrls, num_sctrls);
1575         if (tevent_req_nomem(subreq, req)) {
1576                 return tevent_req_post(req, ev);
1577         }
1578         tevent_req_set_callback(subreq, tldap_add_done, req);
1579         return req;
1580 }
1581
1582 static void tldap_add_done(struct tevent_req *subreq)
1583 {
1584         return tldap_simple_done(subreq, TLDAP_RES_ADD);
1585 }
1586
1587 int tldap_add_recv(struct tevent_req *req)
1588 {
1589         return tldap_simple_recv(req);
1590 }
1591
1592 int tldap_add(struct tldap_context *ld, const char *dn,
1593               int num_attributes, struct tldap_mod *attributes,
1594               struct tldap_control *sctrls, int num_sctrls,
1595               struct tldap_control *cctrls, int num_cctrls)
1596 {
1597         TALLOC_CTX *frame = talloc_stackframe();
1598         struct tevent_context *ev;
1599         struct tevent_req *req;
1600         int result;
1601
1602         ev = event_context_init(frame);
1603         if (ev == NULL) {
1604                 result = TLDAP_NO_MEMORY;
1605                 goto fail;
1606         }
1607
1608         req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
1609                              sctrls, num_sctrls, cctrls, num_cctrls);
1610         if (req == NULL) {
1611                 result = TLDAP_NO_MEMORY;
1612                 goto fail;
1613         }
1614
1615         if (!tevent_req_poll(req, ev)) {
1616                 result = TLDAP_OPERATIONS_ERROR;
1617                 goto fail;
1618         }
1619
1620         result = tldap_add_recv(req);
1621         tldap_save_msg(ld, req);
1622  fail:
1623         TALLOC_FREE(frame);
1624         return result;
1625 }
1626
1627 static void tldap_modify_done(struct tevent_req *subreq);
1628
1629 struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
1630                                      struct tevent_context *ev,
1631                                      struct tldap_context *ld,
1632                                      const char *dn,
1633                                      int num_mods, struct tldap_mod *mods,
1634                                      struct tldap_control *sctrls,
1635                                      int num_sctrls,
1636                                      struct tldap_control *cctrls,
1637                                      int num_cctrls)
1638 {
1639         struct tevent_req *req, *subreq;
1640         struct tldap_req_state *state;
1641         int i, j;
1642
1643         req = tldap_req_create(mem_ctx, ld, &state);
1644         if (req == NULL) {
1645                 return NULL;
1646         }
1647
1648         asn1_push_tag(state->out, TLDAP_REQ_MODIFY);
1649         asn1_write_OctetString(state->out, dn, strlen(dn));
1650         asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1651
1652         for (i=0; i<num_mods; i++) {
1653                 struct tldap_mod *mod = &mods[i];
1654                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1655                 asn1_write_enumerated(state->out, mod->mod_op),
1656                 asn1_push_tag(state->out, ASN1_SEQUENCE(0));
1657                 asn1_write_OctetString(state->out, mod->attribute,
1658                                        strlen(mod->attribute));
1659                 asn1_push_tag(state->out, ASN1_SET);
1660                 for (j=0; j<mod->num_values; j++) {
1661                         asn1_write_OctetString(state->out,
1662                                                mod->values[j].data,
1663                                                mod->values[j].length);
1664                 }
1665                 asn1_pop_tag(state->out);
1666                 asn1_pop_tag(state->out);
1667                 asn1_pop_tag(state->out);
1668         }
1669
1670         asn1_pop_tag(state->out);
1671         asn1_pop_tag(state->out);
1672
1673         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1674                                 sctrls, num_sctrls);
1675         if (tevent_req_nomem(subreq, req)) {
1676                 return tevent_req_post(req, ev);
1677         }
1678         tevent_req_set_callback(subreq, tldap_modify_done, req);
1679         return req;
1680 }
1681
1682 static void tldap_modify_done(struct tevent_req *subreq)
1683 {
1684         return tldap_simple_done(subreq, TLDAP_RES_MODIFY);
1685 }
1686
1687 int tldap_modify_recv(struct tevent_req *req)
1688 {
1689         return tldap_simple_recv(req);
1690 }
1691
1692 int tldap_modify(struct tldap_context *ld, const char *dn,
1693                  int num_mods, struct tldap_mod *mods,
1694                  struct tldap_control *sctrls, int num_sctrls,
1695                  struct tldap_control *cctrls, int num_cctrls)
1696  {
1697         TALLOC_CTX *frame = talloc_stackframe();
1698         struct tevent_context *ev;
1699         struct tevent_req *req;
1700         int result;
1701
1702         ev = event_context_init(frame);
1703         if (ev == NULL) {
1704                 result = TLDAP_NO_MEMORY;
1705                 goto fail;
1706         }
1707
1708         req = tldap_modify_send(frame, ev, ld, dn, num_mods, mods,
1709                                 sctrls, num_sctrls, cctrls, num_cctrls);
1710         if (req == NULL) {
1711                 result = TLDAP_NO_MEMORY;
1712                 goto fail;
1713         }
1714
1715         if (!tevent_req_poll(req, ev)) {
1716                 result = TLDAP_OPERATIONS_ERROR;
1717                 goto fail;
1718         }
1719
1720         result = tldap_modify_recv(req);
1721         tldap_save_msg(ld, req);
1722  fail:
1723         TALLOC_FREE(frame);
1724         return result;
1725 }
1726
1727 static void tldap_delete_done(struct tevent_req *subreq);
1728
1729 struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
1730                                      struct tevent_context *ev,
1731                                      struct tldap_context *ld,
1732                                      const char *dn,
1733                                      struct tldap_control *sctrls,
1734                                      int num_sctrls,
1735                                      struct tldap_control *cctrls,
1736                                      int num_cctrls)
1737 {
1738         struct tevent_req *req, *subreq;
1739         struct tldap_req_state *state;
1740
1741         req = tldap_req_create(mem_ctx, ld, &state);
1742         if (req == NULL) {
1743                 return NULL;
1744         }
1745
1746         asn1_push_tag(state->out, TLDAP_REQ_DELETE);
1747         asn1_write(state->out, dn, strlen(dn));
1748         asn1_pop_tag(state->out);
1749
1750         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1751                                 sctrls, num_sctrls);
1752         if (tevent_req_nomem(subreq, req)) {
1753                 return tevent_req_post(req, ev);
1754         }
1755         tevent_req_set_callback(subreq, tldap_delete_done, req);
1756         return req;
1757 }
1758
1759 static void tldap_delete_done(struct tevent_req *subreq)
1760 {
1761         return tldap_simple_done(subreq, TLDAP_RES_DELETE);
1762 }
1763
1764 int tldap_delete_recv(struct tevent_req *req)
1765 {
1766         return tldap_simple_recv(req);
1767 }
1768
1769 int tldap_delete(struct tldap_context *ld, const char *dn,
1770                  struct tldap_control *sctrls, int num_sctrls,
1771                  struct tldap_control *cctrls, int num_cctrls)
1772 {
1773         TALLOC_CTX *frame = talloc_stackframe();
1774         struct tevent_context *ev;
1775         struct tevent_req *req;
1776         int result;
1777
1778         ev = event_context_init(frame);
1779         if (ev == NULL) {
1780                 result = TLDAP_NO_MEMORY;
1781                 goto fail;
1782         }
1783
1784         req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
1785                                 cctrls, num_cctrls);
1786         if (req == NULL) {
1787                 result = TLDAP_NO_MEMORY;
1788                 goto fail;
1789         }
1790
1791         if (!tevent_req_poll(req, ev)) {
1792                 result = TLDAP_OPERATIONS_ERROR;
1793                 goto fail;
1794         }
1795
1796         result = tldap_delete_recv(req);
1797         tldap_save_msg(ld, req);
1798  fail:
1799         TALLOC_FREE(frame);
1800         return result;
1801 }
1802
1803 int tldap_msg_id(const struct tldap_message *msg)
1804 {
1805         return msg->id;
1806 }
1807
1808 int tldap_msg_type(const struct tldap_message *msg)
1809 {
1810         return msg->type;
1811 }
1812
1813 const char *tldap_msg_matcheddn(struct tldap_message *msg)
1814 {
1815         if (msg == NULL) {
1816                 return NULL;
1817         }
1818         return msg->res_matcheddn;
1819 }
1820
1821 const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
1822 {
1823         if (msg == NULL) {
1824                 return NULL;
1825         }
1826         return msg->res_diagnosticmessage;
1827 }
1828
1829 const char *tldap_msg_referral(struct tldap_message *msg)
1830 {
1831         if (msg == NULL) {
1832                 return NULL;
1833         }
1834         return msg->res_referral;
1835 }
1836
1837 void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
1838                       struct tldap_control **sctrls)
1839 {
1840         if (msg == NULL) {
1841                 *sctrls = NULL;
1842                 *num_sctrls = 0;
1843         }
1844         *sctrls = msg->res_sctrls;
1845         *num_sctrls = talloc_array_length(msg->res_sctrls);
1846 }
1847
1848 struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
1849 {
1850         return ld->last_msg;
1851 }
1852
1853 const char *tldap_err2string(int rc)
1854 {
1855         const char *res = NULL;
1856
1857         /*
1858          * This would normally be a table, but the error codes are not fully
1859          * sequential. Let the compiler figure out the optimum implementation
1860          * :-)
1861          */
1862
1863         switch (rc) {
1864         case TLDAP_SUCCESS:
1865                 res = "TLDAP_SUCCESS";
1866                 break;
1867         case TLDAP_OPERATIONS_ERROR:
1868                 res = "TLDAP_OPERATIONS_ERROR";
1869                 break;
1870         case TLDAP_PROTOCOL_ERROR:
1871                 res = "TLDAP_PROTOCOL_ERROR";
1872                 break;
1873         case TLDAP_TIMELIMIT_EXCEEDED:
1874                 res = "TLDAP_TIMELIMIT_EXCEEDED";
1875                 break;
1876         case TLDAP_SIZELIMIT_EXCEEDED:
1877                 res = "TLDAP_SIZELIMIT_EXCEEDED";
1878                 break;
1879         case TLDAP_COMPARE_FALSE:
1880                 res = "TLDAP_COMPARE_FALSE";
1881                 break;
1882         case TLDAP_COMPARE_TRUE:
1883                 res = "TLDAP_COMPARE_TRUE";
1884                 break;
1885         case TLDAP_STRONG_AUTH_NOT_SUPPORTED:
1886                 res = "TLDAP_STRONG_AUTH_NOT_SUPPORTED";
1887                 break;
1888         case TLDAP_STRONG_AUTH_REQUIRED:
1889                 res = "TLDAP_STRONG_AUTH_REQUIRED";
1890                 break;
1891         case TLDAP_REFERRAL:
1892                 res = "TLDAP_REFERRAL";
1893                 break;
1894         case TLDAP_ADMINLIMIT_EXCEEDED:
1895                 res = "TLDAP_ADMINLIMIT_EXCEEDED";
1896                 break;
1897         case TLDAP_UNAVAILABLE_CRITICAL_EXTENSION:
1898                 res = "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION";
1899                 break;
1900         case TLDAP_CONFIDENTIALITY_REQUIRED:
1901                 res = "TLDAP_CONFIDENTIALITY_REQUIRED";
1902                 break;
1903         case TLDAP_SASL_BIND_IN_PROGRESS:
1904                 res = "TLDAP_SASL_BIND_IN_PROGRESS";
1905                 break;
1906         case TLDAP_NO_SUCH_ATTRIBUTE:
1907                 res = "TLDAP_NO_SUCH_ATTRIBUTE";
1908                 break;
1909         case TLDAP_UNDEFINED_TYPE:
1910                 res = "TLDAP_UNDEFINED_TYPE";
1911                 break;
1912         case TLDAP_INAPPROPRIATE_MATCHING:
1913                 res = "TLDAP_INAPPROPRIATE_MATCHING";
1914                 break;
1915         case TLDAP_CONSTRAINT_VIOLATION:
1916                 res = "TLDAP_CONSTRAINT_VIOLATION";
1917                 break;
1918         case TLDAP_TYPE_OR_VALUE_EXISTS:
1919                 res = "TLDAP_TYPE_OR_VALUE_EXISTS";
1920                 break;
1921         case TLDAP_INVALID_SYNTAX:
1922                 res = "TLDAP_INVALID_SYNTAX";
1923                 break;
1924         case TLDAP_NO_SUCH_OBJECT:
1925                 res = "TLDAP_NO_SUCH_OBJECT";
1926                 break;
1927         case TLDAP_ALIAS_PROBLEM:
1928                 res = "TLDAP_ALIAS_PROBLEM";
1929                 break;
1930         case TLDAP_INVALID_DN_SYNTAX:
1931                 res = "TLDAP_INVALID_DN_SYNTAX";
1932                 break;
1933         case TLDAP_IS_LEAF:
1934                 res = "TLDAP_IS_LEAF";
1935                 break;
1936         case TLDAP_ALIAS_DEREF_PROBLEM:
1937                 res = "TLDAP_ALIAS_DEREF_PROBLEM";
1938                 break;
1939         case TLDAP_INAPPROPRIATE_AUTH:
1940                 res = "TLDAP_INAPPROPRIATE_AUTH";
1941                 break;
1942         case TLDAP_INVALID_CREDENTIALS:
1943                 res = "TLDAP_INVALID_CREDENTIALS";
1944                 break;
1945         case TLDAP_INSUFFICIENT_ACCESS:
1946                 res = "TLDAP_INSUFFICIENT_ACCESS";
1947                 break;
1948         case TLDAP_BUSY:
1949                 res = "TLDAP_BUSY";
1950                 break;
1951         case TLDAP_UNAVAILABLE:
1952                 res = "TLDAP_UNAVAILABLE";
1953                 break;
1954         case TLDAP_UNWILLING_TO_PERFORM:
1955                 res = "TLDAP_UNWILLING_TO_PERFORM";
1956                 break;
1957         case TLDAP_LOOP_DETECT:
1958                 res = "TLDAP_LOOP_DETECT";
1959                 break;
1960         case TLDAP_NAMING_VIOLATION:
1961                 res = "TLDAP_NAMING_VIOLATION";
1962                 break;
1963         case TLDAP_OBJECT_CLASS_VIOLATION:
1964                 res = "TLDAP_OBJECT_CLASS_VIOLATION";
1965                 break;
1966         case TLDAP_NOT_ALLOWED_ON_NONLEAF:
1967                 res = "TLDAP_NOT_ALLOWED_ON_NONLEAF";
1968                 break;
1969         case TLDAP_NOT_ALLOWED_ON_RDN:
1970                 res = "TLDAP_NOT_ALLOWED_ON_RDN";
1971                 break;
1972         case TLDAP_ALREADY_EXISTS:
1973                 res = "TLDAP_ALREADY_EXISTS";
1974                 break;
1975         case TLDAP_NO_OBJECT_CLASS_MODS:
1976                 res = "TLDAP_NO_OBJECT_CLASS_MODS";
1977                 break;
1978         case TLDAP_RESULTS_TOO_LARGE:
1979                 res = "TLDAP_RESULTS_TOO_LARGE";
1980                 break;
1981         case TLDAP_AFFECTS_MULTIPLE_DSAS:
1982                 res = "TLDAP_AFFECTS_MULTIPLE_DSAS";
1983                 break;
1984         case TLDAP_OTHER:
1985                 res = "TLDAP_OTHER";
1986                 break;
1987         case TLDAP_SERVER_DOWN:
1988                 res = "TLDAP_SERVER_DOWN";
1989                 break;
1990         case TLDAP_LOCAL_ERROR:
1991                 res = "TLDAP_LOCAL_ERROR";
1992                 break;
1993         case TLDAP_ENCODING_ERROR:
1994                 res = "TLDAP_ENCODING_ERROR";
1995                 break;
1996         case TLDAP_DECODING_ERROR:
1997                 res = "TLDAP_DECODING_ERROR";
1998                 break;
1999         case TLDAP_TIMEOUT:
2000                 res = "TLDAP_TIMEOUT";
2001                 break;
2002         case TLDAP_AUTH_UNKNOWN:
2003                 res = "TLDAP_AUTH_UNKNOWN";
2004                 break;
2005         case TLDAP_FILTER_ERROR:
2006                 res = "TLDAP_FILTER_ERROR";
2007                 break;
2008         case TLDAP_USER_CANCELLED:
2009                 res = "TLDAP_USER_CANCELLED";
2010                 break;
2011         case TLDAP_PARAM_ERROR:
2012                 res = "TLDAP_PARAM_ERROR";
2013                 break;
2014         case TLDAP_NO_MEMORY:
2015                 res = "TLDAP_NO_MEMORY";
2016                 break;
2017         case TLDAP_CONNECT_ERROR:
2018                 res = "TLDAP_CONNECT_ERROR";
2019                 break;
2020         case TLDAP_NOT_SUPPORTED:
2021                 res = "TLDAP_NOT_SUPPORTED";
2022                 break;
2023         case TLDAP_CONTROL_NOT_FOUND:
2024                 res = "TLDAP_CONTROL_NOT_FOUND";
2025                 break;
2026         case TLDAP_NO_RESULTS_RETURNED:
2027                 res = "TLDAP_NO_RESULTS_RETURNED";
2028                 break;
2029         case TLDAP_MORE_RESULTS_TO_RETURN:
2030                 res = "TLDAP_MORE_RESULTS_TO_RETURN";
2031                 break;
2032         case TLDAP_CLIENT_LOOP:
2033                 res = "TLDAP_CLIENT_LOOP";
2034                 break;
2035         case TLDAP_REFERRAL_LIMIT_EXCEEDED:
2036                 res = "TLDAP_REFERRAL_LIMIT_EXCEEDED";
2037                 break;
2038         default:
2039                 res = talloc_asprintf(talloc_tos(), "Unknown LDAP Error (%d)",
2040                                       rc);
2041                 break;
2042         }
2043         if (res == NULL) {
2044                 res = "Unknown LDAP Error";
2045         }
2046         return res;
2047 }