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