python:tests: Store keys as bytes rather than as lists of ints
[samba.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 "replace.h"
21 #include "tldap.h"
22 #include "system/network.h"
23 #include "system/locale.h"
24 #include "lib/util/talloc_stack.h"
25 #include "lib/util/samba_util.h"
26 #include "lib/util_tsock.h"
27 #include "../lib/util/asn1.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../lib/util/tevent_unix.h"
30 #include "../libcli/util/ntstatus.h"
31 #include "../source4/lib/tls/tls.h"
32
33 static TLDAPRC tldap_simple_recv(struct tevent_req *req);
34 static bool tldap_msg_set_pending(struct tevent_req *req);
35
36 #define TEVENT_TLDAP_RC_MAGIC (0x87bcd26e)
37
38 bool tevent_req_ldap_error(struct tevent_req *req, TLDAPRC rc)
39 {
40         uint64_t err;
41
42         if (TLDAP_RC_IS_SUCCESS(rc)) {
43                 return false;
44         }
45
46         err = TEVENT_TLDAP_RC_MAGIC;
47         err <<= 32;
48         err |= TLDAP_RC_V(rc);
49
50         return tevent_req_error(req, err);
51 }
52
53 bool tevent_req_is_ldap_error(struct tevent_req *req, TLDAPRC *perr)
54 {
55         enum tevent_req_state state;
56         uint64_t err;
57
58         if (!tevent_req_is_error(req, &state, &err)) {
59                 return false;
60         }
61         switch (state) {
62         case TEVENT_REQ_TIMED_OUT:
63                 *perr = TLDAP_TIMEOUT;
64                 break;
65         case TEVENT_REQ_NO_MEMORY:
66                 *perr = TLDAP_NO_MEMORY;
67                 break;
68         case TEVENT_REQ_USER_ERROR:
69                 if ((err >> 32) != TEVENT_TLDAP_RC_MAGIC) {
70                         abort();
71                 }
72                 *perr = TLDAP_RC(err & 0xffffffff);
73                 break;
74         default:
75                 *perr = TLDAP_OPERATIONS_ERROR;
76                 break;
77         }
78         return true;
79 }
80
81 struct tldap_ctx_attribute {
82         char *name;
83         void *ptr;
84 };
85
86 struct tldap_context {
87         int ld_version;
88         struct tstream_context *plain;
89         bool starttls_needed;
90         struct tstream_context *tls;
91         struct tstream_context *gensec;
92         struct tstream_context *active;
93         int msgid;
94         struct tevent_queue *outgoing;
95         struct tevent_req **pending;
96         struct tevent_req *read_req;
97
98         /* For the sync wrappers we need something like get_last_error... */
99         struct tldap_message *last_msg;
100
101         /* debug */
102         void (*log_fn)(void *context, enum tldap_debug_level level,
103                        const char *fmt, va_list ap);
104         void *log_private;
105
106         struct tldap_ctx_attribute *ctx_attrs;
107 };
108
109 struct tldap_message {
110         struct asn1_data *data;
111         uint8_t *inbuf;
112         int type;
113         int id;
114
115         /* RESULT_ENTRY */
116         char *dn;
117         struct tldap_attribute *attribs;
118
119         /* Error data sent by the server */
120         TLDAPRC lderr;
121         char *res_matcheddn;
122         char *res_diagnosticmessage;
123         char *res_referral;
124         DATA_BLOB res_serverSaslCreds;
125         struct {
126                 char *oid;
127                 DATA_BLOB blob;
128         } res_extended;
129         struct tldap_control *res_sctrls;
130
131         /* Controls sent by the server */
132         struct tldap_control *ctrls;
133 };
134
135 void tldap_set_debug(struct tldap_context *ld,
136                      void (*log_fn)(void *log_private,
137                                     enum tldap_debug_level level,
138                                     const char *fmt,
139                                     va_list ap) PRINTF_ATTRIBUTE(3,0),
140                      void *log_private)
141 {
142         ld->log_fn = log_fn;
143         ld->log_private = log_private;
144 }
145
146 static void tldap_debug(
147         struct tldap_context *ld,
148         enum tldap_debug_level level,
149         const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
150
151 static void tldap_debug(struct tldap_context *ld,
152                          enum tldap_debug_level level,
153                          const char *fmt, ...)
154 {
155         va_list ap;
156         if (!ld) {
157                 return;
158         }
159         if (ld->log_fn == NULL) {
160                 return;
161         }
162         va_start(ap, fmt);
163         ld->log_fn(ld->log_private, level, fmt, ap);
164         va_end(ap);
165 }
166
167 static int tldap_next_msgid(struct tldap_context *ld)
168 {
169         int result;
170
171         result = ld->msgid++;
172         if (ld->msgid == INT_MAX) {
173                 ld->msgid = 1;
174         }
175         return result;
176 }
177
178 struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
179 {
180         struct tldap_context *ctx;
181         int ret;
182
183         ctx = talloc_zero(mem_ctx, struct tldap_context);
184         if (ctx == NULL) {
185                 return NULL;
186         }
187         ret = tstream_bsd_existing_socket(ctx, fd, &ctx->plain);
188         if (ret == -1) {
189                 TALLOC_FREE(ctx);
190                 return NULL;
191         }
192         ctx->active = ctx->plain;
193         ctx->msgid = 1;
194         ctx->ld_version = 3;
195         ctx->outgoing = tevent_queue_create(ctx, "tldap_outgoing");
196         if (ctx->outgoing == NULL) {
197                 TALLOC_FREE(ctx);
198                 return NULL;
199         }
200         return ctx;
201 }
202
203 bool tldap_connection_ok(struct tldap_context *ld)
204 {
205         int ret;
206
207         if (ld == NULL) {
208                 return false;
209         }
210
211         if (ld->active == NULL) {
212                 return false;
213         }
214
215         ret = tstream_pending_bytes(ld->active);
216         if (ret == -1) {
217                 return false;
218         }
219
220         return true;
221 }
222
223 static size_t tldap_pending_reqs(struct tldap_context *ld)
224 {
225         return talloc_array_length(ld->pending);
226 }
227
228 struct tstream_context *tldap_get_plain_tstream(struct tldap_context *ld)
229 {
230         return ld->plain;
231 }
232
233 void tldap_set_starttls_needed(struct tldap_context *ld, bool needed)
234 {
235         if (ld == NULL) {
236                 return;
237         }
238
239         ld->starttls_needed = needed;
240 }
241
242 bool tldap_get_starttls_needed(struct tldap_context *ld)
243 {
244         if (ld == NULL) {
245                 return false;
246         }
247
248         return ld->starttls_needed;
249 }
250
251 bool tldap_has_tls_tstream(struct tldap_context *ld)
252 {
253         return ld->tls != NULL && ld->active == ld->tls;
254 }
255
256 const DATA_BLOB *tldap_tls_channel_bindings(struct tldap_context *ld)
257 {
258         return tstream_tls_channel_bindings(ld->tls);
259 }
260
261 void tldap_set_tls_tstream(struct tldap_context *ld,
262                            struct tstream_context **stream)
263 {
264         TALLOC_FREE(ld->tls);
265         if (stream != NULL) {
266                 ld->tls = talloc_move(ld, stream);
267         }
268         if (ld->tls != NULL) {
269                 ld->active = ld->tls;
270         } else {
271                 ld->active = ld->plain;
272         }
273 }
274
275 bool tldap_has_gensec_tstream(struct tldap_context *ld)
276 {
277         return ld->gensec != NULL && ld->active == ld->gensec;
278 }
279
280 void tldap_set_gensec_tstream(struct tldap_context *ld,
281                               struct tstream_context **stream)
282 {
283         TALLOC_FREE(ld->gensec);
284         if (stream != NULL) {
285                 ld->gensec = talloc_move(ld, stream);
286         }
287         if (ld->gensec != NULL) {
288                 ld->active = ld->gensec;
289         } else {
290                 ld->active = ld->plain;
291         }
292 }
293
294 static struct tldap_ctx_attribute *tldap_context_findattr(
295         struct tldap_context *ld, const char *name)
296 {
297         size_t i, num_attrs;
298
299         num_attrs = talloc_array_length(ld->ctx_attrs);
300
301         for (i=0; i<num_attrs; i++) {
302                 if (strcmp(ld->ctx_attrs[i].name, name) == 0) {
303                         return &ld->ctx_attrs[i];
304                 }
305         }
306         return NULL;
307 }
308
309 bool tldap_context_setattr(struct tldap_context *ld,
310                            const char *name, const void *_pptr)
311 {
312         struct tldap_ctx_attribute *tmp, *attr;
313         char *tmpname;
314         int num_attrs;
315         void **pptr = (void **)discard_const_p(void,_pptr);
316
317         attr = tldap_context_findattr(ld, name);
318         if (attr != NULL) {
319                 /*
320                  * We don't actually delete attrs, we don't expect tons of
321                  * attributes being shuffled around.
322                  */
323                 TALLOC_FREE(attr->ptr);
324                 if (*pptr != NULL) {
325                         attr->ptr = talloc_move(ld->ctx_attrs, pptr);
326                         *pptr = NULL;
327                 }
328                 return true;
329         }
330
331         tmpname = talloc_strdup(ld, name);
332         if (tmpname == NULL) {
333                 return false;
334         }
335
336         num_attrs = talloc_array_length(ld->ctx_attrs);
337
338         tmp = talloc_realloc(ld, ld->ctx_attrs, struct tldap_ctx_attribute,
339                              num_attrs+1);
340         if (tmp == NULL) {
341                 TALLOC_FREE(tmpname);
342                 return false;
343         }
344         tmp[num_attrs].name = talloc_move(tmp, &tmpname);
345         if (*pptr != NULL) {
346                 tmp[num_attrs].ptr = talloc_move(tmp, pptr);
347         } else {
348                 tmp[num_attrs].ptr = NULL;
349         }
350         *pptr = NULL;
351         ld->ctx_attrs = tmp;
352         return true;
353 }
354
355 void *tldap_context_getattr(struct tldap_context *ld, const char *name)
356 {
357         struct tldap_ctx_attribute *attr = tldap_context_findattr(ld, name);
358
359         if (attr == NULL) {
360                 return NULL;
361         }
362         return attr->ptr;
363 }
364
365 struct read_ldap_state {
366         uint8_t *buf;
367 };
368
369 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data);
370 static void read_ldap_done(struct tevent_req *subreq);
371
372 static struct tevent_req *read_ldap_send(TALLOC_CTX *mem_ctx,
373                                          struct tevent_context *ev,
374                                          struct tstream_context *conn)
375 {
376         struct tevent_req *req, *subreq;
377         struct read_ldap_state *state;
378
379         req = tevent_req_create(mem_ctx, &state, struct read_ldap_state);
380         if (req == NULL) {
381                 return NULL;
382         }
383
384         subreq = tstream_read_packet_send(state, ev, conn, 7, read_ldap_more,
385                                           state);
386         if (tevent_req_nomem(subreq, req)) {
387                 return tevent_req_post(req, ev);
388         }
389         tevent_req_set_callback(subreq, read_ldap_done, req);
390         return req;
391 }
392
393 static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data)
394 {
395         const DATA_BLOB blob = data_blob_const(buf, buflen);
396         size_t pdu_len = 0;
397         int ret;
398
399         if (buflen < 7) {
400                 /*
401                  * We need at least 6 bytes to workout the length
402                  * of the pdu.
403                  *
404                  * And we have asked for 7 because the that's
405                  * the size of the smallest possible LDAP pdu.
406                  */
407                 return -1;
408         }
409
410         ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), &pdu_len);
411         if (ret == 0) {
412                 return 0;
413         }
414         if (ret == EAGAIN) {
415                 return pdu_len - buflen;
416         }
417
418         return -1;
419 }
420
421 static void read_ldap_done(struct tevent_req *subreq)
422 {
423         struct tevent_req *req = tevent_req_callback_data(
424                 subreq, struct tevent_req);
425         struct read_ldap_state *state = tevent_req_data(
426                 req, struct read_ldap_state);
427         ssize_t nread;
428         int err;
429
430         nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
431         TALLOC_FREE(subreq);
432         if (nread == -1) {
433                 tevent_req_error(req, err);
434                 return;
435         }
436         tevent_req_done(req);
437 }
438
439 static ssize_t read_ldap_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
440                               uint8_t **pbuf, int *perrno)
441 {
442         struct read_ldap_state *state = tevent_req_data(
443                 req, struct read_ldap_state);
444
445         if (tevent_req_is_unix_error(req, perrno)) {
446                 return -1;
447         }
448         *pbuf = talloc_move(mem_ctx, &state->buf);
449         return talloc_get_size(*pbuf);
450 }
451
452 struct tldap_msg_state {
453         struct tldap_context *ld;
454         struct tevent_context *ev;
455         int id;
456         struct iovec iov;
457
458         struct asn1_data *data;
459         uint8_t *inbuf;
460 };
461
462 static bool tldap_push_controls(struct asn1_data *data,
463                                 struct tldap_control *sctrls,
464                                 int num_sctrls)
465 {
466         int i;
467
468         if ((sctrls == NULL) || (num_sctrls == 0)) {
469                 return true;
470         }
471
472         if (!asn1_push_tag(data, ASN1_CONTEXT(0))) return false;
473
474         for (i=0; i<num_sctrls; i++) {
475                 struct tldap_control *c = &sctrls[i];
476                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
477                 if (!asn1_write_OctetString(data, c->oid, strlen(c->oid))) return false;
478                 if (c->critical) {
479                         if (!asn1_write_BOOLEAN(data, true)) return false;
480                 }
481                 if (c->value.data != NULL) {
482                         if (!asn1_write_OctetString(data, c->value.data,
483                                                c->value.length)) return false;
484                 }
485                 if (!asn1_pop_tag(data)) return false; /* ASN1_SEQUENCE(0) */
486         }
487
488         return asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
489 }
490
491 #define tldap_context_disconnect(ld, status) \
492         _tldap_context_disconnect(ld, status, __location__)
493
494 static void _tldap_context_disconnect(struct tldap_context *ld,
495                                       TLDAPRC status,
496                                       const char *location)
497 {
498         if (ld->active == NULL) {
499                 /*
500                  * We don't need to tldap_debug() on
501                  * a potential 2nd run.
502                  *
503                  * The rest of the function would just
504                  * be a noop for the 2nd run anyway.
505                  */
506                 return;
507         }
508
509         tldap_debug(ld, TLDAP_DEBUG_WARNING,
510                     "tldap_context_disconnect: %s at %s\n",
511                     tldap_rc2string(status),
512                     location);
513         tevent_queue_stop(ld->outgoing);
514         TALLOC_FREE(ld->read_req);
515         ld->active = NULL;
516         TALLOC_FREE(ld->gensec);
517         TALLOC_FREE(ld->tls);
518         TALLOC_FREE(ld->plain);
519
520         while (talloc_array_length(ld->pending) > 0) {
521                 struct tevent_req *req = NULL;
522                 struct tldap_msg_state *state = NULL;
523
524                 req = ld->pending[0];
525                 state = tevent_req_data(req, struct tldap_msg_state);
526                 tevent_req_defer_callback(req, state->ev);
527                 tevent_req_ldap_error(req, status);
528         }
529 }
530
531 static void tldap_msg_sent(struct tevent_req *subreq);
532 static void tldap_msg_received(struct tevent_req *subreq);
533
534 static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
535                                          struct tevent_context *ev,
536                                          struct tldap_context *ld,
537                                          int id, struct asn1_data *data,
538                                          struct tldap_control *sctrls,
539                                          int num_sctrls)
540 {
541         struct tevent_req *req, *subreq;
542         struct tldap_msg_state *state;
543         DATA_BLOB blob;
544         bool ok;
545
546         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
547                     id);
548
549         req = tevent_req_create(mem_ctx, &state, struct tldap_msg_state);
550         if (req == NULL) {
551                 return NULL;
552         }
553         state->ld = ld;
554         state->ev = ev;
555         state->id = id;
556
557         ok = tldap_connection_ok(ld);
558         if (!ok) {
559                 tevent_req_ldap_error(req, TLDAP_SERVER_DOWN);
560                 return tevent_req_post(req, ev);
561         }
562
563         if (!tldap_push_controls(data, sctrls, num_sctrls)) {
564                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
565                 return tevent_req_post(req, ev);
566         }
567
568
569         if (!asn1_pop_tag(data)) {
570                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
571                 return tevent_req_post(req, ev);
572         }
573
574         if (!asn1_blob(data, &blob)) {
575                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
576                 return tevent_req_post(req, ev);
577         }
578
579         if (!tldap_msg_set_pending(req)) {
580                 tevent_req_oom(req);
581                 return tevent_req_post(req, ev);;
582         }
583
584         state->iov.iov_base = (void *)blob.data;
585         state->iov.iov_len = blob.length;
586
587         subreq = tstream_writev_queue_send(state, ev, ld->active, ld->outgoing,
588                                            &state->iov, 1);
589         if (tevent_req_nomem(subreq, req)) {
590                 return tevent_req_post(req, ev);
591         }
592         tevent_req_set_callback(subreq, tldap_msg_sent, req);
593         return req;
594 }
595
596 static void tldap_msg_unset_pending(struct tevent_req *req)
597 {
598         struct tldap_msg_state *state = tevent_req_data(
599                 req, struct tldap_msg_state);
600         struct tldap_context *ld = state->ld;
601         int num_pending = tldap_pending_reqs(ld);
602         int i;
603
604         tevent_req_set_cleanup_fn(req, NULL);
605
606         for (i=0; i<num_pending; i++) {
607                 if (req == ld->pending[i]) {
608                         break;
609                 }
610         }
611         if (i == num_pending) {
612                 /*
613                  * Something's seriously broken. Just returning here is the
614                  * right thing nevertheless, the point of this routine is to
615                  * remove ourselves from cli->pending.
616                  */
617                 return;
618         }
619
620         if (num_pending == 1) {
621                 TALLOC_FREE(ld->pending);
622                 return;
623         }
624
625         /*
626          * Remove ourselves from the cli->pending array
627          */
628         if (num_pending > 1) {
629                 ld->pending[i] = ld->pending[num_pending-1];
630         }
631
632         /*
633          * No NULL check here, we're shrinking by sizeof(void *), and
634          * talloc_realloc just adjusts the size for this.
635          */
636         ld->pending = talloc_realloc(NULL, ld->pending, struct tevent_req *,
637                                      num_pending - 1);
638 }
639
640 static void tldap_msg_cleanup(struct tevent_req *req,
641                               enum tevent_req_state req_state)
642 {
643         tldap_msg_unset_pending(req);
644 }
645
646 static bool tldap_msg_set_pending(struct tevent_req *req)
647 {
648         struct tldap_msg_state *state = tevent_req_data(
649                 req, struct tldap_msg_state);
650         struct tldap_context *ld;
651         struct tevent_req **pending;
652         int num_pending;
653
654         ld = state->ld;
655         num_pending = tldap_pending_reqs(ld);
656
657         pending = talloc_realloc(ld, ld->pending, struct tevent_req *,
658                                  num_pending+1);
659         if (pending == NULL) {
660                 return false;
661         }
662         pending[num_pending] = req;
663         ld->pending = pending;
664         tevent_req_set_cleanup_fn(req, tldap_msg_cleanup);
665
666         if (ld->read_req != NULL) {
667                 return true;
668         }
669
670         /*
671          * We're the first one, add the read_ldap request that waits for the
672          * answer from the server
673          */
674         ld->read_req = read_ldap_send(ld->pending, state->ev, ld->active);
675         if (ld->read_req == NULL) {
676                 tldap_msg_unset_pending(req);
677                 return false;
678         }
679         tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
680         return true;
681 }
682
683 static void tldap_msg_sent(struct tevent_req *subreq)
684 {
685         struct tevent_req *req = tevent_req_callback_data(
686                 subreq, struct tevent_req);
687         struct tldap_msg_state *state = tevent_req_data(
688                 req, struct tldap_msg_state);
689         ssize_t nwritten;
690         int err;
691
692         nwritten = tstream_writev_queue_recv(subreq, &err);
693         TALLOC_FREE(subreq);
694         if (nwritten == -1) {
695                 tldap_context_disconnect(state->ld, TLDAP_SERVER_DOWN);
696                 return;
697         }
698 }
699
700 static int tldap_msg_msgid(struct tevent_req *req)
701 {
702         struct tldap_msg_state *state = tevent_req_data(
703                 req, struct tldap_msg_state);
704
705         return state->id;
706 }
707
708 static void tldap_msg_received(struct tevent_req *subreq)
709 {
710         struct tldap_context *ld = tevent_req_callback_data(
711                 subreq, struct tldap_context);
712         struct tevent_req *req;
713         struct tldap_msg_state *state;
714         struct asn1_data *data;
715         uint8_t *inbuf;
716         ssize_t received;
717         size_t num_pending;
718         size_t i;
719         int err;
720         TLDAPRC status = TLDAP_PROTOCOL_ERROR;
721         int id;
722         uint8_t type;
723         bool ok;
724
725         received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
726         TALLOC_FREE(subreq);
727         ld->read_req = NULL;
728         if (received == -1) {
729                 status = TLDAP_SERVER_DOWN;
730                 goto fail;
731         }
732
733         data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
734         if (data == NULL) {
735                 /*
736                  * We have to disconnect all, we can't tell which of
737                  * the requests this reply is for.
738                  */
739                 status = TLDAP_NO_MEMORY;
740                 goto fail;
741         }
742         asn1_load_nocopy(data, inbuf, received);
743
744         ok = true;
745         ok &= asn1_start_tag(data, ASN1_SEQUENCE(0));
746         ok &= asn1_read_Integer(data, &id);
747         ok &= asn1_peek_uint8(data, &type);
748
749         if (!ok) {
750                 status = TLDAP_PROTOCOL_ERROR;
751                 goto fail;
752         }
753
754         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
755                     "type %d\n", id, (int)type);
756
757         if (id == 0) {
758                 tldap_debug(
759                         ld,
760                         TLDAP_DEBUG_WARNING,
761                         "tldap_msg_received: got msgid 0 of "
762                         "type %"PRIu8", disconnecting\n",
763                         type);
764                 tldap_context_disconnect(ld, TLDAP_SERVER_DOWN);
765                 return;
766         }
767
768         num_pending = talloc_array_length(ld->pending);
769
770         for (i=0; i<num_pending; i++) {
771                 if (id == tldap_msg_msgid(ld->pending[i])) {
772                         break;
773                 }
774         }
775         if (i == num_pending) {
776                 /* Dump unexpected reply */
777                 tldap_debug(ld, TLDAP_DEBUG_WARNING, "tldap_msg_received: "
778                             "No request pending for msg %d\n", id);
779                 TALLOC_FREE(data);
780                 TALLOC_FREE(inbuf);
781                 goto done;
782         }
783
784         req = ld->pending[i];
785         state = tevent_req_data(req, struct tldap_msg_state);
786
787         state->inbuf = talloc_move(state, &inbuf);
788         state->data = talloc_move(state, &data);
789
790         tldap_msg_unset_pending(req);
791         num_pending = talloc_array_length(ld->pending);
792
793         tevent_req_defer_callback(req, state->ev);
794         tevent_req_done(req);
795
796  done:
797         if (num_pending == 0) {
798                 return;
799         }
800
801         state = tevent_req_data(ld->pending[0], struct tldap_msg_state);
802         ld->read_req = read_ldap_send(ld->pending, state->ev, ld->active);
803         if (ld->read_req == NULL) {
804                 status = TLDAP_NO_MEMORY;
805                 goto fail;
806         }
807         tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
808         return;
809
810  fail:
811         tldap_context_disconnect(ld, status);
812 }
813
814 static TLDAPRC tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
815                               struct tldap_message **pmsg)
816 {
817         struct tldap_msg_state *state = tevent_req_data(
818                 req, struct tldap_msg_state);
819         struct tldap_message *msg;
820         TLDAPRC err;
821         uint8_t msgtype;
822
823         if (tevent_req_is_ldap_error(req, &err)) {
824                 return err;
825         }
826
827         if (!asn1_peek_uint8(state->data, &msgtype)) {
828                 return TLDAP_PROTOCOL_ERROR;
829         }
830
831         if (pmsg == NULL) {
832                 return TLDAP_SUCCESS;
833         }
834
835         msg = talloc_zero(mem_ctx, struct tldap_message);
836         if (msg == NULL) {
837                 return TLDAP_NO_MEMORY;
838         }
839         msg->id = state->id;
840
841         msg->inbuf = talloc_move(msg, &state->inbuf);
842         msg->data = talloc_move(msg, &state->data);
843         msg->type = msgtype;
844
845         *pmsg = msg;
846         return TLDAP_SUCCESS;
847 }
848
849 struct tldap_req_state {
850         int id;
851         struct asn1_data *out;
852         struct tldap_message *result;
853 };
854
855 static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
856                                            struct tldap_context *ld,
857                                            struct tldap_req_state **pstate)
858 {
859         struct tevent_req *req;
860         struct tldap_req_state *state;
861
862         req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
863         if (req == NULL) {
864                 return NULL;
865         }
866         state->out = asn1_init(state, ASN1_MAX_TREE_DEPTH);
867         if (state->out == NULL) {
868                 goto err;
869         }
870         state->id = tldap_next_msgid(ld);
871
872         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
873         if (!asn1_write_Integer(state->out, state->id)) goto err;
874
875         *pstate = state;
876         return req;
877
878   err:
879
880         TALLOC_FREE(req);
881         return NULL;
882 }
883
884 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
885 {
886         struct tldap_req_state *state = tevent_req_data(
887                 req, struct tldap_req_state);
888
889         TALLOC_FREE(ld->last_msg);
890         ld->last_msg = talloc_move(ld, &state->result);
891 }
892
893 static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
894 {
895         char *result = talloc_array(mem_ctx, char, blob.length+1);
896
897         if (result == NULL) {
898                 return NULL;
899         }
900
901         memcpy(result, blob.data, blob.length);
902         result[blob.length] = '\0';
903         return result;
904 }
905
906 static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
907                                          struct asn1_data *data,
908                                          char **presult)
909 {
910         DATA_BLOB string;
911         char *result;
912         if (!asn1_read_OctetString(data, mem_ctx, &string))
913                 return false;
914
915         result = blob2string_talloc(mem_ctx, string);
916
917         data_blob_free(&string);
918
919         if (result == NULL) {
920                 return false;
921         }
922         *presult = result;
923         return true;
924 }
925
926 static bool tldap_decode_controls(struct tldap_req_state *state);
927
928 static bool tldap_decode_response(struct tldap_req_state *state)
929 {
930         struct asn1_data *data = state->result->data;
931         struct tldap_message *msg = state->result;
932         int rc;
933         bool ok = true;
934
935         ok &= asn1_read_enumerated(data, &rc);
936         if (ok) {
937                 msg->lderr = TLDAP_RC(rc);
938         }
939
940         ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
941         ok &= asn1_read_OctetString_talloc(msg, data,
942                                            &msg->res_diagnosticmessage);
943         if (!ok) return ok;
944         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
945                 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
946                 ok &= asn1_read_OctetString_talloc(msg, data,
947                                                    &msg->res_referral);
948                 ok &= asn1_end_tag(data);
949         } else {
950                 msg->res_referral = NULL;
951         }
952
953         return ok;
954 }
955
956 static void tldap_sasl_bind_done(struct tevent_req *subreq);
957
958 struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
959                                         struct tevent_context *ev,
960                                         struct tldap_context *ld,
961                                         const char *dn,
962                                         const char *mechanism,
963                                         DATA_BLOB *creds,
964                                         struct tldap_control *sctrls,
965                                         int num_sctrls,
966                                         struct tldap_control *cctrls,
967                                         int num_cctrls)
968 {
969         struct tevent_req *req, *subreq;
970         struct tldap_req_state *state;
971
972         req = tldap_req_create(mem_ctx, ld, &state);
973         if (req == NULL) {
974                 return NULL;
975         }
976
977         if (dn == NULL) {
978                 dn = "";
979         }
980
981         if (!asn1_push_tag(state->out, TLDAP_REQ_BIND)) goto err;
982         if (!asn1_write_Integer(state->out, ld->ld_version)) goto err;
983         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
984
985         if (mechanism == NULL) {
986                 if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0))) goto err;
987                 if (!asn1_write(state->out, creds->data, creds->length)) goto err;
988                 if (!asn1_pop_tag(state->out)) goto err;
989         } else {
990                 if (!asn1_push_tag(state->out, ASN1_CONTEXT(3))) goto err;
991                 if (!asn1_write_OctetString(state->out, mechanism,
992                                        strlen(mechanism))) goto err;
993                 if ((creds != NULL) && (creds->data != NULL)) {
994                         if (!asn1_write_OctetString(state->out, creds->data,
995                                                creds->length)) goto err;
996                 }
997                 if (!asn1_pop_tag(state->out)) goto err;
998         }
999
1000         if (!asn1_pop_tag(state->out)) goto err;
1001
1002         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1003                                 sctrls, num_sctrls);
1004         if (tevent_req_nomem(subreq, req)) {
1005                 return tevent_req_post(req, ev);
1006         }
1007         tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
1008         return req;
1009
1010   err:
1011
1012         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
1013         return tevent_req_post(req, ev);
1014 }
1015
1016 static void tldap_sasl_bind_done(struct tevent_req *subreq)
1017 {
1018         struct tevent_req *req = tevent_req_callback_data(
1019                 subreq, struct tevent_req);
1020         struct tldap_req_state *state = tevent_req_data(
1021                 req, struct tldap_req_state);
1022         TLDAPRC rc;
1023         bool ok;
1024
1025         rc = tldap_msg_recv(subreq, state, &state->result);
1026         TALLOC_FREE(subreq);
1027         if (tevent_req_ldap_error(req, rc)) {
1028                 return;
1029         }
1030         if (state->result->type != TLDAP_RES_BIND) {
1031                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
1032                 return;
1033         }
1034
1035         ok = asn1_start_tag(state->result->data, TLDAP_RES_BIND);
1036         ok &= tldap_decode_response(state);
1037
1038         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(7))) {
1039                 int len;
1040
1041                 ok &= asn1_start_tag(state->result->data,
1042                                      ASN1_CONTEXT_SIMPLE(7));
1043                 if (!ok) {
1044                         goto decode_error;
1045                 }
1046
1047                 len = asn1_tag_remaining(state->result->data);
1048                 if (len == -1) {
1049                         goto decode_error;
1050                 }
1051
1052                 state->result->res_serverSaslCreds =
1053                         data_blob_talloc(state->result, NULL, len);
1054                 if (state->result->res_serverSaslCreds.data == NULL) {
1055                         goto decode_error;
1056                 }
1057
1058                 ok = asn1_read(state->result->data,
1059                                state->result->res_serverSaslCreds.data,
1060                                state->result->res_serverSaslCreds.length);
1061
1062                 ok &= asn1_end_tag(state->result->data);
1063         }
1064
1065         ok &= asn1_end_tag(state->result->data);
1066
1067         if (!ok) {
1068                 goto decode_error;
1069         }
1070
1071         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr) &&
1072             !TLDAP_RC_EQUAL(state->result->lderr,
1073                             TLDAP_SASL_BIND_IN_PROGRESS)) {
1074                 tevent_req_ldap_error(req, state->result->lderr);
1075                 return;
1076         }
1077         tevent_req_done(req);
1078         return;
1079
1080 decode_error:
1081         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
1082         return;
1083 }
1084
1085 TLDAPRC tldap_sasl_bind_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1086                              DATA_BLOB *serverSaslCreds)
1087 {
1088         struct tldap_req_state *state = tevent_req_data(
1089                 req, struct tldap_req_state);
1090         TLDAPRC rc;
1091
1092         if (tevent_req_is_ldap_error(req, &rc)) {
1093                 return rc;
1094         }
1095
1096         if (serverSaslCreds != NULL) {
1097                 serverSaslCreds->data = talloc_move(
1098                         mem_ctx, &state->result->res_serverSaslCreds.data);
1099                 serverSaslCreds->length =
1100                         state->result->res_serverSaslCreds.length;
1101         }
1102
1103         return state->result->lderr;
1104 }
1105
1106 TLDAPRC tldap_sasl_bind(struct tldap_context *ld,
1107                         const char *dn,
1108                         const char *mechanism,
1109                         DATA_BLOB *creds,
1110                         struct tldap_control *sctrls,
1111                         int num_sctrls,
1112                         struct tldap_control *cctrls,
1113                         int num_cctrls,
1114                         TALLOC_CTX *mem_ctx,
1115                         DATA_BLOB *serverSaslCreds)
1116 {
1117         TALLOC_CTX *frame = talloc_stackframe();
1118         struct tevent_context *ev;
1119         struct tevent_req *req;
1120         TLDAPRC rc = TLDAP_NO_MEMORY;
1121
1122         ev = samba_tevent_context_init(frame);
1123         if (ev == NULL) {
1124                 goto fail;
1125         }
1126         req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
1127                                    sctrls, num_sctrls, cctrls, num_cctrls);
1128         if (req == NULL) {
1129                 goto fail;
1130         }
1131         if (!tevent_req_poll(req, ev)) {
1132                 rc = TLDAP_OPERATIONS_ERROR;
1133                 goto fail;
1134         }
1135         rc = tldap_sasl_bind_recv(req, mem_ctx, serverSaslCreds);
1136         tldap_save_msg(ld, req);
1137  fail:
1138         TALLOC_FREE(frame);
1139         return rc;
1140 }
1141
1142 struct tevent_req *tldap_simple_bind_send(TALLOC_CTX *mem_ctx,
1143                                           struct tevent_context *ev,
1144                                           struct tldap_context *ld,
1145                                           const char *dn,
1146                                           const char *passwd)
1147 {
1148         DATA_BLOB cred;
1149
1150         if (passwd != NULL) {
1151                 cred.data = discard_const_p(uint8_t, passwd);
1152                 cred.length = strlen(passwd);
1153         } else {
1154                 cred.data = discard_const_p(uint8_t, "");
1155                 cred.length = 0;
1156         }
1157         return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
1158                                     NULL, 0);
1159 }
1160
1161 TLDAPRC tldap_simple_bind_recv(struct tevent_req *req)
1162 {
1163         return tldap_sasl_bind_recv(req, NULL, NULL);
1164 }
1165
1166 TLDAPRC tldap_simple_bind(struct tldap_context *ld, const char *dn,
1167                           const char *passwd)
1168 {
1169         DATA_BLOB cred;
1170
1171         if (passwd != NULL) {
1172                 cred.data = discard_const_p(uint8_t, passwd);
1173                 cred.length = strlen(passwd);
1174         } else {
1175                 cred.data = discard_const_p(uint8_t, "");
1176                 cred.length = 0;
1177         }
1178         return tldap_sasl_bind(ld, dn, NULL, &cred, NULL, 0, NULL, 0,
1179                                NULL, NULL);
1180 }
1181
1182 /*****************************************************************************/
1183
1184 /* can't use isalpha() as only a strict set is valid for LDAP */
1185
1186 static bool tldap_is_alpha(char c)
1187 {
1188         return (((c >= 'a') && (c <= 'z')) || \
1189                 ((c >= 'A') && (c <= 'Z')));
1190 }
1191
1192 static bool tldap_is_adh(char c)
1193 {
1194         return tldap_is_alpha(c) || isdigit(c) || (c == '-');
1195 }
1196
1197 #define TLDAP_FILTER_AND  ASN1_CONTEXT(0)
1198 #define TLDAP_FILTER_OR   ASN1_CONTEXT(1)
1199 #define TLDAP_FILTER_NOT  ASN1_CONTEXT(2)
1200 #define TLDAP_FILTER_EQ   ASN1_CONTEXT(3)
1201 #define TLDAP_FILTER_SUB  ASN1_CONTEXT(4)
1202 #define TLDAP_FILTER_LE   ASN1_CONTEXT(5)
1203 #define TLDAP_FILTER_GE   ASN1_CONTEXT(6)
1204 #define TLDAP_FILTER_PRES ASN1_CONTEXT_SIMPLE(7)
1205 #define TLDAP_FILTER_APX  ASN1_CONTEXT(8)
1206 #define TLDAP_FILTER_EXT  ASN1_CONTEXT(9)
1207
1208 #define TLDAP_SUB_INI ASN1_CONTEXT_SIMPLE(0)
1209 #define TLDAP_SUB_ANY ASN1_CONTEXT_SIMPLE(1)
1210 #define TLDAP_SUB_FIN ASN1_CONTEXT_SIMPLE(2)
1211
1212
1213 /* oid's should be numerical only in theory,
1214  * but apparently some broken servers may have alphanum aliases instead.
1215  * Do like openldap libraries and allow alphanum aliases for oids, but
1216  * do not allow Tagging options in that case.
1217  */
1218 static bool tldap_is_attrdesc(const char *s, int len, bool no_tagopts)
1219 {
1220         bool is_oid = false;
1221         bool dot = false;
1222         int i;
1223
1224         /* first char has stricter rules */
1225         if (isdigit(*s)) {
1226                 is_oid = true;
1227         } else if (!tldap_is_alpha(*s)) {
1228                 /* bad first char */
1229                 return false;
1230         }
1231
1232         for (i = 1; i < len; i++) {
1233
1234                 if (is_oid) {
1235                         if (isdigit(s[i])) {
1236                                 dot = false;
1237                                 continue;
1238                         }
1239                         if (s[i] == '.') {
1240                                 if (dot) {
1241                                         /* malformed */
1242                                         return false;
1243                                 }
1244                                 dot = true;
1245                                 continue;
1246                         }
1247                 } else {
1248                         if (tldap_is_adh(s[i])) {
1249                                 continue;
1250                         }
1251                 }
1252
1253                 if (s[i] == ';') {
1254                         if (no_tagopts) {
1255                                 /* no tagging options */
1256                                 return false;
1257                         }
1258                         if (dot) {
1259                                 /* malformed */
1260                                 return false;
1261                         }
1262                         if ((i + 1) == len) {
1263                                 /* malformed */
1264                                 return false;
1265                         }
1266
1267                         is_oid = false;
1268                         continue;
1269                 }
1270         }
1271
1272         if (dot) {
1273                 /* malformed */
1274                 return false;
1275         }
1276
1277         return true;
1278 }
1279
1280 /* this function copies the value until the closing parenthesis is found. */
1281 static char *tldap_get_val(TALLOC_CTX *memctx,
1282                            const char *value, const char **_s)
1283 {
1284         const char *s = value;
1285
1286         /* find terminator */
1287         while (*s) {
1288                 s = strchr(s, ')');
1289                 if (s && (*(s - 1) == '\\')) {
1290                         s++;
1291                         continue;
1292                 }
1293                 break;
1294         }
1295         if (!s || !(*s == ')')) {
1296                 /* malformed filter */
1297                 return NULL;
1298         }
1299
1300         *_s = s;
1301
1302         return talloc_strndup(memctx, value, s - value);
1303 }
1304
1305 static int tldap_hex2char(const char *x)
1306 {
1307         if (isxdigit(x[0]) && isxdigit(x[1])) {
1308                 const char h1 = x[0], h2 = x[1];
1309                 int c = 0;
1310
1311                 if (h1 >= 'a') c = h1 - (int)'a' + 10;
1312                 else if (h1 >= 'A') c = h1 - (int)'A' + 10;
1313                 else if (h1 >= '0') c = h1 - (int)'0';
1314                 c = c << 4;
1315                 if (h2 >= 'a') c += h2 - (int)'a' + 10;
1316                 else if (h2 >= 'A') c += h2 - (int)'A' + 10;
1317                 else if (h2 >= '0') c += h2 - (int)'0';
1318
1319                 return c;
1320         }
1321
1322         return -1;
1323 }
1324
1325 static bool tldap_find_first_star(const char *val, const char **star)
1326 {
1327         const char *s;
1328
1329         for (s = val; *s; s++) {
1330                 switch (*s) {
1331                 case '\\':
1332                         if (isxdigit(s[1]) && isxdigit(s[2])) {
1333                                 s += 2;
1334                                 break;
1335                         }
1336                         /* not hex based escape, check older syntax */
1337                         switch (s[1]) {
1338                         case '(':
1339                         case ')':
1340                         case '*':
1341                         case '\\':
1342                                 s++;
1343                                 break;
1344                         default:
1345                                 /* invalid escape sequence */
1346                                 return false;
1347                         }
1348                         break;
1349                 case ')':
1350                         /* end of val, nothing found */
1351                         *star = s;
1352                         return true;
1353
1354                 case '*':
1355                         *star = s;
1356                         return true;
1357                 }
1358         }
1359
1360         /* string ended without closing parenthesis, filter is malformed */
1361         return false;
1362 }
1363
1364 static bool tldap_unescape_inplace(char *value, size_t *val_len)
1365 {
1366         int c;
1367         size_t i, p;
1368
1369         for (i = 0,p = 0; i < *val_len; i++) {
1370
1371                 switch (value[i]) {
1372                 case '(':
1373                 case ')':
1374                 case '*':
1375                         /* these must be escaped */
1376                         return false;
1377
1378                 case '\\':
1379                         if (!value[i + 1]) {
1380                                 /* invalid EOL */
1381                                 return false;
1382                         }
1383                         i++;
1384
1385                         /* LDAPv3 escaped */
1386                         c = tldap_hex2char(&value[i]);
1387                         if (c >= 0 && c < 256) {
1388                                 value[p] = c;
1389                                 i++;
1390                                 p++;
1391                                 break;
1392                         }
1393
1394                         /* LDAPv2 escaped */
1395                         switch (value[i]) {
1396                         case '(':
1397                         case ')':
1398                         case '*':
1399                         case '\\':
1400                                 value[p] = value[i];
1401                                 p++;
1402
1403                                 break;
1404                         default:
1405                                 /* invalid */
1406                                 return false;
1407                         }
1408                         break;
1409
1410                 default:
1411                         value[p] = value[i];
1412                         p++;
1413                 }
1414         }
1415         value[p] = '\0';
1416         *val_len = p;
1417         return true;
1418 }
1419
1420 static bool tldap_push_filter_basic(struct tldap_context *ld,
1421                                     struct asn1_data *data,
1422                                     const char **_s);
1423 static bool tldap_push_filter_substring(struct tldap_context *ld,
1424                                         struct asn1_data *data,
1425                                         const char *val,
1426                                         const char **_s);
1427 static bool tldap_push_filter_int(struct tldap_context *ld,
1428                                   struct asn1_data *data,
1429                                   const char **_s)
1430 {
1431         const char *s = *_s;
1432         bool ret;
1433
1434         if (*s != '(') {
1435                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1436                             "Incomplete or malformed filter\n");
1437                 return false;
1438         }
1439         s++;
1440
1441         /* we are right after a parenthesis,
1442          * find out what op we have at hand */
1443         switch (*s) {
1444         case '&':
1445                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: AND\n");
1446                 if (!asn1_push_tag(data, TLDAP_FILTER_AND)) return false;
1447                 s++;
1448                 break;
1449
1450         case '|':
1451                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: OR\n");
1452                 if (!asn1_push_tag(data, TLDAP_FILTER_OR)) return false;
1453                 s++;
1454                 break;
1455
1456         case '!':
1457                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: NOT\n");
1458                 if (!asn1_push_tag(data, TLDAP_FILTER_NOT)) return false;
1459                 s++;
1460                 ret = tldap_push_filter_int(ld, data, &s);
1461                 if (!ret) {
1462                         return false;
1463                 }
1464                 if (!asn1_pop_tag(data)) return false;
1465                 goto done;
1466
1467         case '(':
1468         case ')':
1469                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1470                             "Invalid parenthesis '%c'\n", *s);
1471                 return false;
1472
1473         case '\0':
1474                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1475                             "Invalid filter termination\n");
1476                 return false;
1477
1478         default:
1479                 ret = tldap_push_filter_basic(ld, data, &s);
1480                 if (!ret) {
1481                         return false;
1482                 }
1483                 goto done;
1484         }
1485
1486         /* only and/or filters get here.
1487          * go through the list of filters */
1488
1489         if (*s == ')') {
1490                 /* RFC 4526: empty and/or */
1491                 if (!asn1_pop_tag(data)) return false;
1492                 goto done;
1493         }
1494
1495         while (*s) {
1496                 ret = tldap_push_filter_int(ld, data, &s);
1497                 if (!ret) {
1498                         return false;
1499                 }
1500
1501                 if (*s == ')') {
1502                         /* end of list, return */
1503                         if (!asn1_pop_tag(data)) return false;
1504                         break;
1505                 }
1506         }
1507
1508 done:
1509         if (*s != ')') {
1510                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1511                             "Incomplete or malformed filter\n");
1512                 return false;
1513         }
1514         s++;
1515
1516         if (asn1_has_error(data)) {
1517                 return false;
1518         }
1519
1520         *_s = s;
1521         return true;
1522 }
1523
1524
1525 static bool tldap_push_filter_basic(struct tldap_context *ld,
1526                                     struct asn1_data *data,
1527                                     const char **_s)
1528 {
1529         TALLOC_CTX *tmpctx = talloc_tos();
1530         const char *s = *_s;
1531         const char *e;
1532         const char *eq;
1533         const char *val;
1534         const char *type;
1535         const char *dn;
1536         const char *rule;
1537         const char *star;
1538         size_t type_len = 0;
1539         char *uval;
1540         size_t uval_len;
1541         bool write_octect = true;
1542         bool ret;
1543
1544         eq = strchr(s, '=');
1545         if (!eq) {
1546                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1547                             "Invalid filter, missing equal sign\n");
1548                 return false;
1549         }
1550
1551         val = eq + 1;
1552         e = eq - 1;
1553
1554         switch (*e) {
1555         case '<':
1556                 if (!asn1_push_tag(data, TLDAP_FILTER_LE)) return false;
1557                 break;
1558
1559         case '>':
1560                 if (!asn1_push_tag(data, TLDAP_FILTER_GE)) return false;
1561                 break;
1562
1563         case '~':
1564                 if (!asn1_push_tag(data, TLDAP_FILTER_APX)) return false;
1565                 break;
1566
1567         case ':':
1568                 if (!asn1_push_tag(data, TLDAP_FILTER_EXT)) return false;
1569                 write_octect = false;
1570
1571                 type = NULL;
1572                 dn = NULL;
1573                 rule = NULL;
1574
1575                 if (*s == ':') { /* [:dn]:rule:= value */
1576                         if (s == e) {
1577                                 /* malformed filter */
1578                                 return false;
1579                         }
1580                         dn = s;
1581                 } else { /* type[:dn][:rule]:= value */
1582                         type = s;
1583                         dn = strchr(s, ':');
1584                         type_len = dn - type;
1585                         if (dn == e) { /* type:= value */
1586                                 dn = NULL;
1587                         }
1588                 }
1589                 if (dn) {
1590                         dn++;
1591
1592                         rule = strchr(dn, ':');
1593                         if (rule == NULL) {
1594                                 return false;
1595                         }
1596                         if ((rule == dn + 1) || rule + 1 == e) {
1597                                 /* malformed filter, contains "::" */
1598                                 return false;
1599                         }
1600
1601                         if (strncasecmp_m(dn, "dn:", 3) != 0) {
1602                                 if (rule == e) {
1603                                         rule = dn;
1604                                         dn = NULL;
1605                                 } else {
1606                                         /* malformed filter. With two
1607                                          * optionals, the first must be "dn"
1608                                          */
1609                                         return false;
1610                                 }
1611                         } else {
1612                                 if (rule == e) {
1613                                         rule = NULL;
1614                                 } else {
1615                                         rule++;
1616                                 }
1617                         }
1618                 }
1619
1620                 if (!type && !dn && !rule) {
1621                         /* malformed filter, there must be at least one */
1622                         return false;
1623                 }
1624
1625                 /*
1626                   MatchingRuleAssertion ::= SEQUENCE {
1627                   matchingRule    [1] MatchingRuleID OPTIONAL,
1628                   type      [2] AttributeDescription OPTIONAL,
1629                   matchValue      [3] AssertionValue,
1630                   dnAttributes    [4] BOOLEAN DEFAULT FALSE
1631                   }
1632                 */
1633
1634                 /* check and add rule */
1635                 if (rule) {
1636                         ret = tldap_is_attrdesc(rule, e - rule, true);
1637                         if (!ret) {
1638                                 return false;
1639                         }
1640                         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
1641                         if (!asn1_write(data, rule, e - rule)) return false;
1642                         if (!asn1_pop_tag(data)) return false;
1643                 }
1644
1645                 /* check and add type */
1646                 if (type) {
1647                         ret = tldap_is_attrdesc(type, type_len, false);
1648                         if (!ret) {
1649                                 return false;
1650                         }
1651                         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
1652                         if (!asn1_write(data, type, type_len)) return false;
1653                         if (!asn1_pop_tag(data)) return false;
1654                 }
1655
1656                 uval = tldap_get_val(tmpctx, val, _s);
1657                 if (!uval) {
1658                         return false;
1659                 }
1660                 uval_len = *_s - val;
1661                 ret = tldap_unescape_inplace(uval, &uval_len);
1662                 if (!ret) {
1663                         return false;
1664                 }
1665
1666                 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
1667                 if (!asn1_write(data, uval, uval_len)) return false;
1668                 if (!asn1_pop_tag(data)) return false;
1669
1670                 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
1671                 if (!asn1_write_uint8(data, dn?1:0)) return false;
1672                 if (!asn1_pop_tag(data)) return false;
1673                 break;
1674
1675         default:
1676                 e = eq;
1677
1678                 ret = tldap_is_attrdesc(s, e - s, false);
1679                 if (!ret) {
1680                         return false;
1681                 }
1682
1683                 if (strncmp(val, "*)", 2) == 0) {
1684                         /* presence */
1685                         if (!asn1_push_tag(data, TLDAP_FILTER_PRES)) return false;
1686                         if (!asn1_write(data, s, e - s)) return false;
1687                         *_s = val + 1;
1688                         write_octect = false;
1689                         break;
1690                 }
1691
1692                 ret = tldap_find_first_star(val, &star);
1693                 if (!ret) {
1694                         return false;
1695                 }
1696                 if (*star == '*') {
1697                         /* substring */
1698                         if (!asn1_push_tag(data, TLDAP_FILTER_SUB)) return false;
1699                         if (!asn1_write_OctetString(data, s, e - s)) return false;
1700                         ret = tldap_push_filter_substring(ld, data, val, &s);
1701                         if (!ret) {
1702                                 return false;
1703                         }
1704                         *_s = s;
1705                         write_octect = false;
1706                         break;
1707                 }
1708
1709                 /* if nothing else, then it is just equality */
1710                 if (!asn1_push_tag(data, TLDAP_FILTER_EQ)) return false;
1711                 write_octect = true;
1712                 break;
1713         }
1714
1715         if (write_octect) {
1716                 uval = tldap_get_val(tmpctx, val, _s);
1717                 if (!uval) {
1718                         return false;
1719                 }
1720                 uval_len = *_s - val;
1721                 ret = tldap_unescape_inplace(uval, &uval_len);
1722                 if (!ret) {
1723                         return false;
1724                 }
1725
1726                 if (!asn1_write_OctetString(data, s, e - s)) return false;
1727                 if (!asn1_write_OctetString(data, uval, uval_len)) return false;
1728         }
1729
1730         if (asn1_has_error(data)) {
1731                 return false;
1732         }
1733         return asn1_pop_tag(data);
1734 }
1735
1736 static bool tldap_push_filter_substring(struct tldap_context *ld,
1737                                         struct asn1_data *data,
1738                                         const char *val,
1739                                         const char **_s)
1740 {
1741         TALLOC_CTX *tmpctx = talloc_tos();
1742         bool initial = true;
1743         const char *star;
1744         char *chunk;
1745         size_t chunk_len;
1746         bool ret;
1747
1748         /*
1749           SubstringFilter ::= SEQUENCE {
1750                   type      AttributeDescription,
1751                   -- at least one must be present
1752                   substrings      SEQUENCE OF CHOICE {
1753                           initial [0] LDAPString,
1754                           any     [1] LDAPString,
1755                           final   [2] LDAPString } }
1756         */
1757         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
1758
1759         do {
1760                 ret = tldap_find_first_star(val, &star);
1761                 if (!ret) {
1762                         return false;
1763                 }
1764                 chunk_len = star - val;
1765
1766                 switch (*star) {
1767                 case '*':
1768                         if (!initial && chunk_len == 0) {
1769                                 /* found '**', which is illegal */
1770                                 return false;
1771                         }
1772                         break;
1773                 case ')':
1774                         if (initial) {
1775                                 /* no stars ?? */
1776                                 return false;
1777                         }
1778                         /* we are done */
1779                         break;
1780                 default:
1781                         /* ?? */
1782                         return false;
1783                 }
1784
1785                 if (initial && chunk_len == 0) {
1786                         val = star + 1;
1787                         initial = false;
1788                         continue;
1789                 }
1790
1791                 chunk = talloc_strndup(tmpctx, val, chunk_len);
1792                 if (!chunk) {
1793                         return false;
1794                 }
1795                 ret = tldap_unescape_inplace(chunk, &chunk_len);
1796                 if (!ret) {
1797                         return false;
1798                 }
1799                 switch (*star) {
1800                 case '*':
1801                         if (initial) {
1802                                 if (!asn1_push_tag(data, TLDAP_SUB_INI)) return false;
1803                                 initial = false;
1804                         } else {
1805                                 if (!asn1_push_tag(data, TLDAP_SUB_ANY)) return false;
1806                         }
1807                         break;
1808                 case ')':
1809                         if (!asn1_push_tag(data, TLDAP_SUB_FIN)) return false;
1810                         break;
1811                 default:
1812                         /* ?? */
1813                         return false;
1814                 }
1815                 if (!asn1_write(data, chunk, chunk_len)) return false;
1816                 if (!asn1_pop_tag(data)) return false;
1817
1818                 val = star + 1;
1819
1820         } while (*star == '*');
1821
1822         *_s = star;
1823
1824         /* end of sequence */
1825         return asn1_pop_tag(data);
1826 }
1827
1828 /* NOTE: although openldap libraries allow for spaces in some places, mostly
1829  * around parentheses, we do not allow any spaces (except in values of
1830  * course) as I couldn't find any place in RFC 4512 or RFC 4515 where
1831  * leading or trailing spaces were allowed.
1832  */
1833 static bool tldap_push_filter(struct tldap_context *ld,
1834                               struct asn1_data *data,
1835                               const char *filter)
1836 {
1837         const char *s = filter;
1838         bool ret;
1839
1840         ret = tldap_push_filter_int(ld, data, &s);
1841         if (ret && *s) {
1842                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
1843                             "Incomplete or malformed filter\n");
1844                 return false;
1845         }
1846         return ret;
1847 }
1848
1849 /*****************************************************************************/
1850
1851 static void tldap_search_done(struct tevent_req *subreq);
1852
1853 struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
1854                                      struct tevent_context *ev,
1855                                      struct tldap_context *ld,
1856                                      const char *base, int scope,
1857                                      const char *filter,
1858                                      const char **attrs,
1859                                      int num_attrs,
1860                                      int attrsonly,
1861                                      struct tldap_control *sctrls,
1862                                      int num_sctrls,
1863                                      struct tldap_control *cctrls,
1864                                      int num_cctrls,
1865                                      int timelimit,
1866                                      int sizelimit,
1867                                      int deref)
1868 {
1869         struct tevent_req *req, *subreq;
1870         struct tldap_req_state *state;
1871         int i;
1872
1873         req = tldap_req_create(mem_ctx, ld, &state);
1874         if (req == NULL) {
1875                 return NULL;
1876         }
1877
1878         if (!asn1_push_tag(state->out, TLDAP_REQ_SEARCH)) goto encoding_error;
1879         if (!asn1_write_OctetString(state->out, base, strlen(base))) goto encoding_error;
1880         if (!asn1_write_enumerated(state->out, scope)) goto encoding_error;
1881         if (!asn1_write_enumerated(state->out, deref)) goto encoding_error;
1882         if (!asn1_write_Integer(state->out, sizelimit)) goto encoding_error;
1883         if (!asn1_write_Integer(state->out, timelimit)) goto encoding_error;
1884         if (!asn1_write_BOOLEAN(state->out, attrsonly)) goto encoding_error;
1885
1886         if (!tldap_push_filter(ld, state->out, filter)) {
1887                 goto encoding_error;
1888         }
1889
1890         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto encoding_error;
1891         for (i=0; i<num_attrs; i++) {
1892                 if (!asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]))) goto encoding_error;
1893         }
1894         if (!asn1_pop_tag(state->out)) goto encoding_error;
1895         if (!asn1_pop_tag(state->out)) goto encoding_error;
1896
1897         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
1898                                 sctrls, num_sctrls);
1899         if (tevent_req_nomem(subreq, req)) {
1900                 return tevent_req_post(req, ev);
1901         }
1902         tevent_req_set_callback(subreq, tldap_search_done, req);
1903         return req;
1904
1905  encoding_error:
1906         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
1907         return tevent_req_post(req, ev);
1908 }
1909
1910 static void tldap_search_done(struct tevent_req *subreq)
1911 {
1912         struct tevent_req *req = tevent_req_callback_data(
1913                 subreq, struct tevent_req);
1914         struct tldap_req_state *state = tevent_req_data(
1915                 req, struct tldap_req_state);
1916         TLDAPRC rc;
1917
1918         rc = tldap_msg_recv(subreq, state, &state->result);
1919         if (tevent_req_ldap_error(req, rc)) {
1920                 return;
1921         }
1922         switch (state->result->type) {
1923         case TLDAP_RES_SEARCH_ENTRY:
1924         case TLDAP_RES_SEARCH_REFERENCE:
1925                 if (!tldap_msg_set_pending(subreq)) {
1926                         tevent_req_oom(req);
1927                         return;
1928                 }
1929                 tevent_req_notify_callback(req);
1930                 break;
1931         case TLDAP_RES_SEARCH_RESULT:
1932                 TALLOC_FREE(subreq);
1933                 if (!asn1_start_tag(state->result->data,
1934                                     state->result->type) ||
1935                     !tldap_decode_response(state) ||
1936                     !asn1_end_tag(state->result->data) ||
1937                     !tldap_decode_controls(state)) {
1938                         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
1939                         return;
1940                 }
1941                 tevent_req_done(req);
1942                 break;
1943         default:
1944                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
1945                 return;
1946         }
1947 }
1948
1949 TLDAPRC tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1950                           struct tldap_message **pmsg)
1951 {
1952         struct tldap_req_state *state = tevent_req_data(
1953                 req, struct tldap_req_state);
1954         TLDAPRC rc;
1955
1956         if (!tevent_req_is_in_progress(req)
1957             && tevent_req_is_ldap_error(req, &rc)) {
1958                 return rc;
1959         }
1960
1961         if (tevent_req_is_in_progress(req)) {
1962                 switch (state->result->type) {
1963                 case TLDAP_RES_SEARCH_ENTRY:
1964                 case TLDAP_RES_SEARCH_REFERENCE:
1965                         break;
1966                 default:
1967                         return TLDAP_OPERATIONS_ERROR;
1968                 }
1969         }
1970
1971         *pmsg = talloc_move(mem_ctx, &state->result);
1972         return TLDAP_SUCCESS;
1973 }
1974
1975 struct tldap_search_all_state {
1976         struct tldap_message **msgs;
1977         struct tldap_message *result;
1978 };
1979
1980 static void tldap_search_all_done(struct tevent_req *subreq);
1981
1982 struct tevent_req *tldap_search_all_send(
1983         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
1984         struct tldap_context *ld, const char *base, int scope,
1985         const char *filter, const char **attrs, int num_attrs, int attrsonly,
1986         struct tldap_control *sctrls, int num_sctrls,
1987         struct tldap_control *cctrls, int num_cctrls,
1988         int timelimit, int sizelimit, int deref)
1989 {
1990         struct tevent_req *req, *subreq;
1991         struct tldap_search_all_state *state;
1992
1993         req = tevent_req_create(mem_ctx, &state,
1994                                 struct tldap_search_all_state);
1995         if (req == NULL) {
1996                 return NULL;
1997         }
1998
1999         subreq = tldap_search_send(state, ev, ld, base, scope, filter,
2000                                    attrs, num_attrs, attrsonly,
2001                                    sctrls, num_sctrls, cctrls, num_cctrls,
2002                                    timelimit, sizelimit, deref);
2003         if (tevent_req_nomem(subreq, req)) {
2004                 return tevent_req_post(req, ev);
2005         }
2006         tevent_req_set_callback(subreq, tldap_search_all_done, req);
2007         return req;
2008 }
2009
2010 static void tldap_search_all_done(struct tevent_req *subreq)
2011 {
2012         struct tevent_req *req = tevent_req_callback_data(
2013                 subreq, struct tevent_req);
2014         struct tldap_search_all_state *state = tevent_req_data(
2015                 req, struct tldap_search_all_state);
2016         struct tldap_message *msg, **tmp;
2017         size_t num_msgs;
2018         TLDAPRC rc;
2019         int msgtype;
2020
2021         rc = tldap_search_recv(subreq, state, &msg);
2022         /* No TALLOC_FREE(subreq), this is multi-step */
2023         if (tevent_req_ldap_error(req, rc)) {
2024                 return;
2025         }
2026
2027         msgtype = tldap_msg_type(msg);
2028         if (msgtype == TLDAP_RES_SEARCH_RESULT) {
2029                 state->result = msg;
2030                 tevent_req_done(req);
2031                 return;
2032         }
2033
2034         num_msgs = talloc_array_length(state->msgs);
2035
2036         tmp = talloc_realloc(state, state->msgs, struct tldap_message *,
2037                              num_msgs + 1);
2038         if (tevent_req_nomem(tmp, req)) {
2039                 return;
2040         }
2041         state->msgs = tmp;
2042         state->msgs[num_msgs] = talloc_move(state->msgs, &msg);
2043 }
2044
2045 TLDAPRC tldap_search_all_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2046                               struct tldap_message ***msgs,
2047                               struct tldap_message **result)
2048 {
2049         struct tldap_search_all_state *state = tevent_req_data(
2050                 req, struct tldap_search_all_state);
2051         TLDAPRC rc;
2052
2053         if (tevent_req_is_ldap_error(req, &rc)) {
2054                 return rc;
2055         }
2056
2057         if (msgs != NULL) {
2058                 *msgs = talloc_move(mem_ctx, &state->msgs);
2059         }
2060         if (result != NULL) {
2061                 *result = talloc_move(mem_ctx, &state->result);
2062         }
2063
2064         return TLDAP_SUCCESS;
2065 }
2066
2067 TLDAPRC tldap_search(struct tldap_context *ld,
2068                      const char *base, int scope, const char *filter,
2069                      const char **attrs, int num_attrs, int attrsonly,
2070                      struct tldap_control *sctrls, int num_sctrls,
2071                      struct tldap_control *cctrls, int num_cctrls,
2072                      int timelimit, int sizelimit, int deref,
2073                      TALLOC_CTX *mem_ctx, struct tldap_message ***pmsgs)
2074 {
2075         TALLOC_CTX *frame;
2076         struct tevent_context *ev;
2077         struct tevent_req *req;
2078         TLDAPRC rc = TLDAP_NO_MEMORY;
2079         struct tldap_message **msgs;
2080         struct tldap_message *result;
2081
2082         if (tldap_pending_reqs(ld)) {
2083                 return TLDAP_BUSY;
2084         }
2085
2086         frame = talloc_stackframe();
2087
2088         ev = samba_tevent_context_init(frame);
2089         if (ev == NULL) {
2090                 goto fail;
2091         }
2092         req = tldap_search_all_send(frame, ev, ld, base, scope, filter,
2093                                     attrs, num_attrs, attrsonly,
2094                                     sctrls, num_sctrls, cctrls, num_cctrls,
2095                                     timelimit, sizelimit, deref);
2096         if (req == NULL) {
2097                 goto fail;
2098         }
2099         if (!tevent_req_poll(req, ev)) {
2100                 rc = TLDAP_OPERATIONS_ERROR;
2101                 goto fail;
2102         }
2103         rc = tldap_search_all_recv(req, frame, &msgs, &result);
2104         TALLOC_FREE(req);
2105         if (!TLDAP_RC_IS_SUCCESS(rc)) {
2106                 goto fail;
2107         }
2108
2109         TALLOC_FREE(ld->last_msg);
2110         ld->last_msg = talloc_move(ld, &result);
2111
2112         if (pmsgs != NULL) {
2113                 *pmsgs = talloc_move(mem_ctx, &msgs);
2114         }
2115 fail:
2116         TALLOC_FREE(frame);
2117         return rc;
2118 }
2119
2120 static bool tldap_parse_search_entry(struct tldap_message *msg)
2121 {
2122         int num_attribs = 0;
2123
2124         if (msg->type != TLDAP_RES_SEARCH_ENTRY) {
2125                 return false;
2126         }
2127         if (!asn1_start_tag(msg->data, TLDAP_RES_SEARCH_ENTRY)) {
2128                 return false;
2129         }
2130
2131         /* dn */
2132
2133         if (!asn1_read_OctetString_talloc(msg, msg->data, &msg->dn)) return false;
2134
2135         if (msg->dn == NULL) {
2136                 return false;
2137         }
2138
2139         /*
2140          * Attributes: We overallocate msg->attribs by one, so that while
2141          * looping over the attributes we can directly parse into the last
2142          * array element. Same for the values in the inner loop.
2143          */
2144
2145         msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
2146         if (msg->attribs == NULL) {
2147                 return false;
2148         }
2149
2150         if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
2151         while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
2152                 struct tldap_attribute *attrib;
2153                 int num_values = 0;
2154
2155                 attrib = &msg->attribs[num_attribs];
2156                 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
2157                 if (attrib->values == NULL) {
2158                         return false;
2159                 }
2160                 if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
2161                 if (!asn1_read_OctetString_talloc(msg->attribs, msg->data,
2162                                              &attrib->name)) return false;
2163                 if (!asn1_start_tag(msg->data, ASN1_SET)) return false;
2164
2165                 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
2166                         if (!asn1_read_OctetString(msg->data, msg,
2167                                               &attrib->values[num_values])) return false;
2168
2169                         attrib->values = talloc_realloc(
2170                                 msg->attribs, attrib->values, DATA_BLOB,
2171                                 num_values + 2);
2172                         if (attrib->values == NULL) {
2173                                 return false;
2174                         }
2175                         num_values += 1;
2176                 }
2177                 attrib->values = talloc_realloc(msg->attribs, attrib->values,
2178                                                 DATA_BLOB, num_values);
2179                 attrib->num_values = num_values;
2180
2181                 if (!asn1_end_tag(msg->data)) return false; /* ASN1_SET */
2182                 if (!asn1_end_tag(msg->data)) return false; /* ASN1_SEQUENCE(0) */
2183                 msg->attribs = talloc_realloc(
2184                         msg, msg->attribs, struct tldap_attribute,
2185                         num_attribs + 2);
2186                 if (msg->attribs == NULL) {
2187                         return false;
2188                 }
2189                 num_attribs += 1;
2190         }
2191         msg->attribs = talloc_realloc(
2192                 msg, msg->attribs, struct tldap_attribute, num_attribs);
2193         return asn1_end_tag(msg->data);
2194 }
2195
2196 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
2197 {
2198         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
2199                 return false;
2200         }
2201         *dn = msg->dn;
2202         return true;
2203 }
2204
2205 bool tldap_entry_attributes(struct tldap_message *msg,
2206                             struct tldap_attribute **attributes,
2207                             int *num_attributes)
2208 {
2209         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
2210                 return false;
2211         }
2212         *attributes = msg->attribs;
2213         *num_attributes = talloc_array_length(msg->attribs);
2214         return true;
2215 }
2216
2217 static bool tldap_decode_controls(struct tldap_req_state *state)
2218 {
2219         struct tldap_message *msg = state->result;
2220         struct asn1_data *data = msg->data;
2221         struct tldap_control *sctrls = NULL;
2222         int num_controls = 0;
2223         bool ret = false;
2224
2225         msg->res_sctrls = NULL;
2226
2227         if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
2228                 return true;
2229         }
2230
2231         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto out;
2232
2233         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
2234                 struct tldap_control *c;
2235                 char *oid = NULL;
2236
2237                 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
2238                                         num_controls + 1);
2239                 if (sctrls == NULL) {
2240                         goto out;
2241                 }
2242                 c = &sctrls[num_controls];
2243
2244                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto out;
2245                 if (!asn1_read_OctetString_talloc(msg, data, &oid)) goto out;
2246                 if (asn1_has_error(data) || (oid == NULL)) {
2247                         goto out;
2248                 }
2249                 c->oid = oid;
2250                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
2251                         if (!asn1_read_BOOLEAN(data, &c->critical)) goto out;
2252                 } else {
2253                         c->critical = false;
2254                 }
2255                 c->value = data_blob_null;
2256                 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
2257                     !asn1_read_OctetString(data, msg, &c->value)) {
2258                         goto out;
2259                 }
2260                 if (!asn1_end_tag(data)) goto out; /* ASN1_SEQUENCE(0) */
2261
2262                 num_controls += 1;
2263         }
2264
2265         if (!asn1_end_tag(data)) goto out;      /* ASN1_CONTEXT(0) */
2266
2267         ret = true;
2268
2269  out:
2270
2271         if (ret) {
2272                 msg->res_sctrls = sctrls;
2273         } else {
2274                 TALLOC_FREE(sctrls);
2275         }
2276         return ret;
2277 }
2278
2279 static void tldap_simple_done(struct tevent_req *subreq, int type)
2280 {
2281         struct tevent_req *req = tevent_req_callback_data(
2282                 subreq, struct tevent_req);
2283         struct tldap_req_state *state = tevent_req_data(
2284                 req, struct tldap_req_state);
2285         TLDAPRC rc;
2286
2287         rc = tldap_msg_recv(subreq, state, &state->result);
2288         TALLOC_FREE(subreq);
2289         if (tevent_req_ldap_error(req, rc)) {
2290                 return;
2291         }
2292         if (state->result->type != type) {
2293                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
2294                 return;
2295         }
2296         if (!asn1_start_tag(state->result->data, state->result->type) ||
2297             !tldap_decode_response(state) ||
2298             !asn1_end_tag(state->result->data) ||
2299             !tldap_decode_controls(state)) {
2300                 tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
2301                 return;
2302         }
2303         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr)) {
2304                 tevent_req_ldap_error(req, state->result->lderr);
2305                 return;
2306         }
2307         tevent_req_done(req);
2308 }
2309
2310 static TLDAPRC tldap_simple_recv(struct tevent_req *req)
2311 {
2312         TLDAPRC rc;
2313         if (tevent_req_is_ldap_error(req, &rc)) {
2314                 return rc;
2315         }
2316         return TLDAP_SUCCESS;
2317 }
2318
2319 static void tldap_add_done(struct tevent_req *subreq);
2320
2321 struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
2322                                   struct tevent_context *ev,
2323                                   struct tldap_context *ld,
2324                                   const char *dn,
2325                                   struct tldap_mod *attributes,
2326                                   int num_attributes,
2327                                   struct tldap_control *sctrls,
2328                                   int num_sctrls,
2329                                   struct tldap_control *cctrls,
2330                                   int num_cctrls)
2331 {
2332         struct tevent_req *req, *subreq;
2333         struct tldap_req_state *state;
2334         int i, j;
2335
2336         req = tldap_req_create(mem_ctx, ld, &state);
2337         if (req == NULL) {
2338                 return NULL;
2339         }
2340
2341         if (!asn1_push_tag(state->out, TLDAP_REQ_ADD)) goto err;
2342         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
2343         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
2344
2345         for (i=0; i<num_attributes; i++) {
2346                 struct tldap_mod *attrib = &attributes[i];
2347                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
2348                 if (!asn1_write_OctetString(state->out, attrib->attribute,
2349                                        strlen(attrib->attribute))) goto err;
2350                 if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
2351                 for (j=0; j<attrib->num_values; j++) {
2352                         if (!asn1_write_OctetString(state->out,
2353                                                attrib->values[j].data,
2354                                                attrib->values[j].length)) goto err;
2355                 }
2356                 if (!asn1_pop_tag(state->out)) goto err;
2357                 if (!asn1_pop_tag(state->out)) goto err;
2358         }
2359
2360         if (!asn1_pop_tag(state->out)) goto err;
2361         if (!asn1_pop_tag(state->out)) goto err;
2362
2363         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2364                                 sctrls, num_sctrls);
2365         if (tevent_req_nomem(subreq, req)) {
2366                 return tevent_req_post(req, ev);
2367         }
2368         tevent_req_set_callback(subreq, tldap_add_done, req);
2369         return req;
2370
2371   err:
2372
2373         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
2374         return tevent_req_post(req, ev);
2375 }
2376
2377 static void tldap_add_done(struct tevent_req *subreq)
2378 {
2379         tldap_simple_done(subreq, TLDAP_RES_ADD);
2380 }
2381
2382 TLDAPRC tldap_add_recv(struct tevent_req *req)
2383 {
2384         return tldap_simple_recv(req);
2385 }
2386
2387 TLDAPRC tldap_add(struct tldap_context *ld, const char *dn,
2388                   struct tldap_mod *attributes, int num_attributes,
2389                   struct tldap_control *sctrls, int num_sctrls,
2390                   struct tldap_control *cctrls, int num_cctrls)
2391 {
2392         TALLOC_CTX *frame = talloc_stackframe();
2393         struct tevent_context *ev;
2394         struct tevent_req *req;
2395         TLDAPRC rc = TLDAP_NO_MEMORY;
2396
2397         ev = samba_tevent_context_init(frame);
2398         if (ev == NULL) {
2399                 goto fail;
2400         }
2401         req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
2402                              sctrls, num_sctrls, cctrls, num_cctrls);
2403         if (req == NULL) {
2404                 goto fail;
2405         }
2406         if (!tevent_req_poll(req, ev)) {
2407                 rc = TLDAP_OPERATIONS_ERROR;
2408                 goto fail;
2409         }
2410         rc = tldap_add_recv(req);
2411         tldap_save_msg(ld, req);
2412  fail:
2413         TALLOC_FREE(frame);
2414         return rc;
2415 }
2416
2417 static void tldap_modify_done(struct tevent_req *subreq);
2418
2419 struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
2420                                      struct tevent_context *ev,
2421                                      struct tldap_context *ld,
2422                                      const char *dn,
2423                                      struct tldap_mod *mods, int num_mods,
2424                                      struct tldap_control *sctrls,
2425                                      int num_sctrls,
2426                                      struct tldap_control *cctrls,
2427                                      int num_cctrls)
2428 {
2429         struct tevent_req *req, *subreq;
2430         struct tldap_req_state *state;
2431         int i, j;
2432
2433         req = tldap_req_create(mem_ctx, ld, &state);
2434         if (req == NULL) {
2435                 return NULL;
2436         }
2437
2438         if (!asn1_push_tag(state->out, TLDAP_REQ_MODIFY)) goto err;
2439         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
2440         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
2441
2442         for (i=0; i<num_mods; i++) {
2443                 struct tldap_mod *mod = &mods[i];
2444                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
2445                 if (!asn1_write_enumerated(state->out, mod->mod_op)) goto err;
2446                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
2447                 if (!asn1_write_OctetString(state->out, mod->attribute,
2448                                        strlen(mod->attribute))) goto err;
2449                 if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
2450                 for (j=0; j<mod->num_values; j++) {
2451                         if (!asn1_write_OctetString(state->out,
2452                                                mod->values[j].data,
2453                                                mod->values[j].length)) goto err;
2454                 }
2455                 if (!asn1_pop_tag(state->out)) goto err;
2456                 if (!asn1_pop_tag(state->out)) goto err;
2457                 if (!asn1_pop_tag(state->out)) goto err;
2458         }
2459
2460         if (!asn1_pop_tag(state->out)) goto err;
2461         if (!asn1_pop_tag(state->out)) goto err;
2462
2463         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2464                                 sctrls, num_sctrls);
2465         if (tevent_req_nomem(subreq, req)) {
2466                 return tevent_req_post(req, ev);
2467         }
2468         tevent_req_set_callback(subreq, tldap_modify_done, req);
2469         return req;
2470
2471   err:
2472
2473         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
2474         return tevent_req_post(req, ev);
2475 }
2476
2477 static void tldap_modify_done(struct tevent_req *subreq)
2478 {
2479         tldap_simple_done(subreq, TLDAP_RES_MODIFY);
2480 }
2481
2482 TLDAPRC tldap_modify_recv(struct tevent_req *req)
2483 {
2484         return tldap_simple_recv(req);
2485 }
2486
2487 TLDAPRC tldap_modify(struct tldap_context *ld, const char *dn,
2488                      struct tldap_mod *mods, int num_mods,
2489                      struct tldap_control *sctrls, int num_sctrls,
2490                      struct tldap_control *cctrls, int num_cctrls)
2491  {
2492         TALLOC_CTX *frame = talloc_stackframe();
2493         struct tevent_context *ev;
2494         struct tevent_req *req;
2495         TLDAPRC rc = TLDAP_NO_MEMORY;
2496
2497         ev = samba_tevent_context_init(frame);
2498         if (ev == NULL) {
2499                 goto fail;
2500         }
2501         req = tldap_modify_send(frame, ev, ld, dn, mods, num_mods,
2502                                 sctrls, num_sctrls, cctrls, num_cctrls);
2503         if (req == NULL) {
2504                 goto fail;
2505         }
2506         if (!tevent_req_poll(req, ev)) {
2507                 rc = TLDAP_OPERATIONS_ERROR;
2508                 goto fail;
2509         }
2510         rc = tldap_modify_recv(req);
2511         tldap_save_msg(ld, req);
2512  fail:
2513         TALLOC_FREE(frame);
2514         return rc;
2515 }
2516
2517 static void tldap_delete_done(struct tevent_req *subreq);
2518
2519 struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
2520                                      struct tevent_context *ev,
2521                                      struct tldap_context *ld,
2522                                      const char *dn,
2523                                      struct tldap_control *sctrls,
2524                                      int num_sctrls,
2525                                      struct tldap_control *cctrls,
2526                                      int num_cctrls)
2527 {
2528         struct tevent_req *req, *subreq;
2529         struct tldap_req_state *state;
2530
2531         req = tldap_req_create(mem_ctx, ld, &state);
2532         if (req == NULL) {
2533                 return NULL;
2534         }
2535
2536         if (!asn1_push_tag(state->out, TLDAP_REQ_DELETE)) goto err;
2537         if (!asn1_write(state->out, dn, strlen(dn))) goto err;
2538         if (!asn1_pop_tag(state->out)) goto err;
2539
2540         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2541                                 sctrls, num_sctrls);
2542         if (tevent_req_nomem(subreq, req)) {
2543                 return tevent_req_post(req, ev);
2544         }
2545         tevent_req_set_callback(subreq, tldap_delete_done, req);
2546         return req;
2547
2548   err:
2549
2550         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
2551         return tevent_req_post(req, ev);
2552 }
2553
2554 static void tldap_delete_done(struct tevent_req *subreq)
2555 {
2556         tldap_simple_done(subreq, TLDAP_RES_DELETE);
2557 }
2558
2559 TLDAPRC tldap_delete_recv(struct tevent_req *req)
2560 {
2561         return tldap_simple_recv(req);
2562 }
2563
2564 TLDAPRC tldap_delete(struct tldap_context *ld, const char *dn,
2565                      struct tldap_control *sctrls, int num_sctrls,
2566                      struct tldap_control *cctrls, int num_cctrls)
2567 {
2568         TALLOC_CTX *frame = talloc_stackframe();
2569         struct tevent_context *ev;
2570         struct tevent_req *req;
2571         TLDAPRC rc = TLDAP_NO_MEMORY;
2572
2573         ev = samba_tevent_context_init(frame);
2574         if (ev == NULL) {
2575                 goto fail;
2576         }
2577         req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
2578                                 cctrls, num_cctrls);
2579         if (req == NULL) {
2580                 goto fail;
2581         }
2582         if (!tevent_req_poll(req, ev)) {
2583                 rc = TLDAP_OPERATIONS_ERROR;
2584                 goto fail;
2585         }
2586         rc = tldap_delete_recv(req);
2587         tldap_save_msg(ld, req);
2588  fail:
2589         TALLOC_FREE(frame);
2590         return rc;
2591 }
2592
2593 static void tldap_extended_done(struct tevent_req *subreq);
2594
2595 struct tevent_req *tldap_extended_send(TALLOC_CTX *mem_ctx,
2596                                        struct tevent_context *ev,
2597                                        struct tldap_context *ld,
2598                                        const char *in_oid,
2599                                        const DATA_BLOB *in_blob,
2600                                        struct tldap_control *sctrls,
2601                                        int num_sctrls,
2602                                        struct tldap_control *cctrls,
2603                                        int num_cctrls)
2604 {
2605         struct tevent_req *req, *subreq;
2606         struct tldap_req_state *state;
2607
2608         req = tldap_req_create(mem_ctx, ld, &state);
2609         if (req == NULL) {
2610                 return NULL;
2611         }
2612
2613         if (!asn1_push_tag(state->out, TLDAP_REQ_EXTENDED)) goto err;
2614
2615         if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0))) goto err;
2616         if (!asn1_write(state->out, in_oid, strlen(in_oid))) goto err;
2617         if (!asn1_pop_tag(state->out)) goto err;
2618
2619         if (in_blob != NULL) {
2620                 if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(1))) goto err;
2621                 if (!asn1_write_OctetString(state->out, in_blob->data, in_blob->length)) goto err;
2622                 if (!asn1_pop_tag(state->out)) goto err;
2623         }
2624
2625         if (!asn1_pop_tag(state->out)) goto err;
2626
2627         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
2628                                 sctrls, num_sctrls);
2629         if (tevent_req_nomem(subreq, req)) {
2630                 return tevent_req_post(req, ev);
2631         }
2632         tevent_req_set_callback(subreq, tldap_extended_done, req);
2633         return req;
2634
2635   err:
2636
2637         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
2638         return tevent_req_post(req, ev);
2639 }
2640
2641 static void tldap_extended_done(struct tevent_req *subreq)
2642 {
2643         struct tevent_req *req = tevent_req_callback_data(
2644                 subreq, struct tevent_req);
2645         struct tldap_req_state *state = tevent_req_data(
2646                 req, struct tldap_req_state);
2647         TLDAPRC rc;
2648         bool ok;
2649
2650         rc = tldap_msg_recv(subreq, state, &state->result);
2651         TALLOC_FREE(subreq);
2652         if (tevent_req_ldap_error(req, rc)) {
2653                 return;
2654         }
2655         if (state->result->type != TLDAP_RES_EXTENDED) {
2656                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
2657                 return;
2658         }
2659
2660         ok = asn1_start_tag(state->result->data, TLDAP_RES_EXTENDED);
2661         ok &= tldap_decode_response(state);
2662
2663         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(10))) {
2664                 ok &= asn1_start_tag(state->result->data,
2665                                      ASN1_CONTEXT_SIMPLE(10));
2666                 if (!ok) {
2667                         goto decode_error;
2668                 }
2669
2670                 ok &= asn1_read_LDAPString(state->result->data,
2671                                            state->result,
2672                                            &state->result->res_extended.oid);
2673
2674                 ok &= asn1_end_tag(state->result->data);
2675         }
2676
2677         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(11))) {
2678                 int len;
2679
2680                 ok &= asn1_start_tag(state->result->data,
2681                                      ASN1_CONTEXT_SIMPLE(11));
2682                 if (!ok) {
2683                         goto decode_error;
2684                 }
2685
2686                 len = asn1_tag_remaining(state->result->data);
2687                 if (len == -1) {
2688                         goto decode_error;
2689                 }
2690
2691                 state->result->res_extended.blob =
2692                         data_blob_talloc(state->result, NULL, len);
2693                 if (state->result->res_extended.blob.data == NULL) {
2694                         goto decode_error;
2695                 }
2696
2697                 ok = asn1_read(state->result->data,
2698                                state->result->res_extended.blob.data,
2699                                state->result->res_extended.blob.length);
2700
2701                 ok &= asn1_end_tag(state->result->data);
2702         }
2703
2704         ok &= asn1_end_tag(state->result->data);
2705
2706         if (!ok) {
2707                 goto decode_error;
2708         }
2709
2710         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr)) {
2711                 tevent_req_ldap_error(req, state->result->lderr);
2712                 return;
2713         }
2714         tevent_req_done(req);
2715         return;
2716
2717 decode_error:
2718         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
2719         return;
2720 }
2721
2722 TLDAPRC tldap_extended_recv(struct tevent_req *req,
2723                             TALLOC_CTX *mem_ctx,
2724                             char **out_oid,
2725                             DATA_BLOB *out_blob)
2726 {
2727         struct tldap_req_state *state = tevent_req_data(
2728                 req, struct tldap_req_state);
2729         TLDAPRC rc;
2730
2731         if (tevent_req_is_ldap_error(req, &rc)) {
2732                 return rc;
2733         }
2734
2735         if (out_oid != NULL) {
2736                 *out_oid = talloc_move(mem_ctx,
2737                                 &state->result->res_extended.oid);
2738         }
2739
2740         if (out_blob != NULL) {
2741                 out_blob->data = talloc_move(mem_ctx,
2742                                 &state->result->res_extended.blob.data);
2743                 out_blob->length =
2744                                 state->result->res_extended.blob.length;
2745         }
2746
2747         return state->result->lderr;
2748 }
2749
2750 TLDAPRC tldap_extended(struct tldap_context *ld,
2751                         const char *in_oid,
2752                         const DATA_BLOB *in_blob,
2753                         struct tldap_control *sctrls,
2754                         int num_sctrls,
2755                         struct tldap_control *cctrls,
2756                         int num_cctrls,
2757                         TALLOC_CTX *mem_ctx,
2758                         char **out_oid,
2759                         DATA_BLOB *out_blob)
2760 {
2761         TALLOC_CTX *frame = talloc_stackframe();
2762         struct tevent_context *ev;
2763         struct tevent_req *req;
2764         TLDAPRC rc = TLDAP_NO_MEMORY;
2765
2766         ev = samba_tevent_context_init(frame);
2767         if (ev == NULL) {
2768                 goto fail;
2769         }
2770         req = tldap_extended_send(frame, ev, ld,
2771                                   in_oid, in_blob,
2772                                   sctrls, num_sctrls,
2773                                   cctrls, num_cctrls);
2774         if (req == NULL) {
2775                 goto fail;
2776         }
2777         if (!tevent_req_poll(req, ev)) {
2778                 rc = TLDAP_OPERATIONS_ERROR;
2779                 goto fail;
2780         }
2781         rc = tldap_extended_recv(req, mem_ctx, out_oid, out_blob);
2782         tldap_save_msg(ld, req);
2783  fail:
2784         TALLOC_FREE(frame);
2785         return rc;
2786 }
2787
2788 int tldap_msg_id(const struct tldap_message *msg)
2789 {
2790         return msg->id;
2791 }
2792
2793 int tldap_msg_type(const struct tldap_message *msg)
2794 {
2795         return msg->type;
2796 }
2797
2798 const char *tldap_msg_matcheddn(struct tldap_message *msg)
2799 {
2800         if (msg == NULL) {
2801                 return NULL;
2802         }
2803         return msg->res_matcheddn;
2804 }
2805
2806 const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
2807 {
2808         if (msg == NULL) {
2809                 return NULL;
2810         }
2811         return msg->res_diagnosticmessage;
2812 }
2813
2814 const char *tldap_msg_referral(struct tldap_message *msg)
2815 {
2816         if (msg == NULL) {
2817                 return NULL;
2818         }
2819         return msg->res_referral;
2820 }
2821
2822 void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
2823                       struct tldap_control **sctrls)
2824 {
2825         if (msg == NULL) {
2826                 *sctrls = NULL;
2827                 *num_sctrls = 0;
2828                 return;
2829         }
2830         *sctrls = msg->res_sctrls;
2831         *num_sctrls = talloc_array_length(msg->res_sctrls);
2832 }
2833
2834 struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
2835 {
2836         return ld->last_msg;
2837 }
2838
2839 static const struct { TLDAPRC rc; const char *string; } tldaprc_errmap[] =
2840 {
2841         { TLDAP_SUCCESS,
2842           "TLDAP_SUCCESS" },
2843         { TLDAP_OPERATIONS_ERROR,
2844           "TLDAP_OPERATIONS_ERROR" },
2845         { TLDAP_PROTOCOL_ERROR,
2846           "TLDAP_PROTOCOL_ERROR" },
2847         { TLDAP_TIMELIMIT_EXCEEDED,
2848           "TLDAP_TIMELIMIT_EXCEEDED" },
2849         { TLDAP_SIZELIMIT_EXCEEDED,
2850           "TLDAP_SIZELIMIT_EXCEEDED" },
2851         { TLDAP_COMPARE_FALSE,
2852           "TLDAP_COMPARE_FALSE" },
2853         { TLDAP_COMPARE_TRUE,
2854           "TLDAP_COMPARE_TRUE" },
2855         { TLDAP_STRONG_AUTH_NOT_SUPPORTED,
2856           "TLDAP_STRONG_AUTH_NOT_SUPPORTED" },
2857         { TLDAP_STRONG_AUTH_REQUIRED,
2858           "TLDAP_STRONG_AUTH_REQUIRED" },
2859         { TLDAP_REFERRAL,
2860           "TLDAP_REFERRAL" },
2861         { TLDAP_ADMINLIMIT_EXCEEDED,
2862           "TLDAP_ADMINLIMIT_EXCEEDED" },
2863         { TLDAP_UNAVAILABLE_CRITICAL_EXTENSION,
2864           "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION" },
2865         { TLDAP_CONFIDENTIALITY_REQUIRED,
2866           "TLDAP_CONFIDENTIALITY_REQUIRED" },
2867         { TLDAP_SASL_BIND_IN_PROGRESS,
2868           "TLDAP_SASL_BIND_IN_PROGRESS" },
2869         { TLDAP_NO_SUCH_ATTRIBUTE,
2870           "TLDAP_NO_SUCH_ATTRIBUTE" },
2871         { TLDAP_UNDEFINED_TYPE,
2872           "TLDAP_UNDEFINED_TYPE" },
2873         { TLDAP_INAPPROPRIATE_MATCHING,
2874           "TLDAP_INAPPROPRIATE_MATCHING" },
2875         { TLDAP_CONSTRAINT_VIOLATION,
2876           "TLDAP_CONSTRAINT_VIOLATION" },
2877         { TLDAP_TYPE_OR_VALUE_EXISTS,
2878           "TLDAP_TYPE_OR_VALUE_EXISTS" },
2879         { TLDAP_INVALID_SYNTAX,
2880           "TLDAP_INVALID_SYNTAX" },
2881         { TLDAP_NO_SUCH_OBJECT,
2882           "TLDAP_NO_SUCH_OBJECT" },
2883         { TLDAP_ALIAS_PROBLEM,
2884           "TLDAP_ALIAS_PROBLEM" },
2885         { TLDAP_INVALID_DN_SYNTAX,
2886           "TLDAP_INVALID_DN_SYNTAX" },
2887         { TLDAP_IS_LEAF,
2888           "TLDAP_IS_LEAF" },
2889         { TLDAP_ALIAS_DEREF_PROBLEM,
2890           "TLDAP_ALIAS_DEREF_PROBLEM" },
2891         { TLDAP_INAPPROPRIATE_AUTH,
2892           "TLDAP_INAPPROPRIATE_AUTH" },
2893         { TLDAP_INVALID_CREDENTIALS,
2894           "TLDAP_INVALID_CREDENTIALS" },
2895         { TLDAP_INSUFFICIENT_ACCESS,
2896           "TLDAP_INSUFFICIENT_ACCESS" },
2897         { TLDAP_BUSY,
2898           "TLDAP_BUSY" },
2899         { TLDAP_UNAVAILABLE,
2900           "TLDAP_UNAVAILABLE" },
2901         { TLDAP_UNWILLING_TO_PERFORM,
2902           "TLDAP_UNWILLING_TO_PERFORM" },
2903         { TLDAP_LOOP_DETECT,
2904           "TLDAP_LOOP_DETECT" },
2905         { TLDAP_NAMING_VIOLATION,
2906           "TLDAP_NAMING_VIOLATION" },
2907         { TLDAP_OBJECT_CLASS_VIOLATION,
2908           "TLDAP_OBJECT_CLASS_VIOLATION" },
2909         { TLDAP_NOT_ALLOWED_ON_NONLEAF,
2910           "TLDAP_NOT_ALLOWED_ON_NONLEAF" },
2911         { TLDAP_NOT_ALLOWED_ON_RDN,
2912           "TLDAP_NOT_ALLOWED_ON_RDN" },
2913         { TLDAP_ALREADY_EXISTS,
2914           "TLDAP_ALREADY_EXISTS" },
2915         { TLDAP_NO_OBJECT_CLASS_MODS,
2916           "TLDAP_NO_OBJECT_CLASS_MODS" },
2917         { TLDAP_RESULTS_TOO_LARGE,
2918           "TLDAP_RESULTS_TOO_LARGE" },
2919         { TLDAP_AFFECTS_MULTIPLE_DSAS,
2920           "TLDAP_AFFECTS_MULTIPLE_DSAS" },
2921         { TLDAP_OTHER,
2922           "TLDAP_OTHER" },
2923         { TLDAP_SERVER_DOWN,
2924           "TLDAP_SERVER_DOWN" },
2925         { TLDAP_LOCAL_ERROR,
2926           "TLDAP_LOCAL_ERROR" },
2927         { TLDAP_ENCODING_ERROR,
2928           "TLDAP_ENCODING_ERROR" },
2929         { TLDAP_DECODING_ERROR,
2930           "TLDAP_DECODING_ERROR" },
2931         { TLDAP_TIMEOUT,
2932           "TLDAP_TIMEOUT" },
2933         { TLDAP_AUTH_UNKNOWN,
2934           "TLDAP_AUTH_UNKNOWN" },
2935         { TLDAP_FILTER_ERROR,
2936           "TLDAP_FILTER_ERROR" },
2937         { TLDAP_USER_CANCELLED,
2938           "TLDAP_USER_CANCELLED" },
2939         { TLDAP_PARAM_ERROR,
2940           "TLDAP_PARAM_ERROR" },
2941         { TLDAP_NO_MEMORY,
2942           "TLDAP_NO_MEMORY" },
2943         { TLDAP_CONNECT_ERROR,
2944           "TLDAP_CONNECT_ERROR" },
2945         { TLDAP_NOT_SUPPORTED,
2946           "TLDAP_NOT_SUPPORTED" },
2947         { TLDAP_CONTROL_NOT_FOUND,
2948           "TLDAP_CONTROL_NOT_FOUND" },
2949         { TLDAP_NO_RESULTS_RETURNED,
2950           "TLDAP_NO_RESULTS_RETURNED" },
2951         { TLDAP_MORE_RESULTS_TO_RETURN,
2952           "TLDAP_MORE_RESULTS_TO_RETURN" },
2953         { TLDAP_CLIENT_LOOP,
2954           "TLDAP_CLIENT_LOOP" },
2955         { TLDAP_REFERRAL_LIMIT_EXCEEDED,
2956           "TLDAP_REFERRAL_LIMIT_EXCEEDED" },
2957 };
2958
2959 const char *tldap_rc2string(TLDAPRC rc)
2960 {
2961         size_t i;
2962
2963         for (i=0; i<ARRAY_SIZE(tldaprc_errmap); i++) {
2964                 if (TLDAP_RC_EQUAL(rc, tldaprc_errmap[i].rc)) {
2965                         return tldaprc_errmap[i].string;
2966                 }
2967         }
2968
2969         return "Unknown LDAP Error";
2970 }