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