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