LCOV - code coverage report
Current view: top level - source3/lib - tldap.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 799 1487 53.7 %
Date: 2024-05-31 13:13:24 Functions: 64 93 68.8 %

          Line data    Source code
       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        4754 : bool tevent_req_ldap_error(struct tevent_req *req, TLDAPRC rc)
      39             : {
      40           0 :         uint64_t err;
      41             : 
      42        4754 :         if (TLDAP_RC_IS_SUCCESS(rc)) {
      43        4754 :                 return false;
      44             :         }
      45             : 
      46           0 :         err = TEVENT_TLDAP_RC_MAGIC;
      47           0 :         err <<= 32;
      48           0 :         err |= TLDAP_RC_V(rc);
      49             : 
      50           0 :         return tevent_req_error(req, err);
      51             : }
      52             : 
      53        2888 : bool tevent_req_is_ldap_error(struct tevent_req *req, TLDAPRC *perr)
      54             : {
      55           0 :         enum tevent_req_state state;
      56           0 :         uint64_t err;
      57             : 
      58        2888 :         if (!tevent_req_is_error(req, &state, &err)) {
      59        2888 :                 return false;
      60             :         }
      61           0 :         switch (state) {
      62           0 :         case TEVENT_REQ_TIMED_OUT:
      63           0 :                 *perr = TLDAP_TIMEOUT;
      64           0 :                 break;
      65           0 :         case TEVENT_REQ_NO_MEMORY:
      66           0 :                 *perr = TLDAP_NO_MEMORY;
      67           0 :                 break;
      68           0 :         case TEVENT_REQ_USER_ERROR:
      69           0 :                 if ((err >> 32) != TEVENT_TLDAP_RC_MAGIC) {
      70           0 :                         abort();
      71             :                 }
      72           0 :                 *perr = TLDAP_RC(err & 0xffffffff);
      73           0 :                 break;
      74           0 :         default:
      75           0 :                 *perr = TLDAP_OPERATIONS_ERROR;
      76           0 :                 break;
      77             :         }
      78           0 :         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           0 : 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           0 :         ld->log_fn = log_fn;
     143           0 :         ld->log_private = log_private;
     144           0 : }
     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        2868 : static void tldap_debug(struct tldap_context *ld,
     152             :                          enum tldap_debug_level level,
     153             :                          const char *fmt, ...)
     154             : {
     155           0 :         va_list ap;
     156        2868 :         if (!ld) {
     157        2868 :                 return;
     158             :         }
     159        2868 :         if (ld->log_fn == NULL) {
     160        2868 :                 return;
     161             :         }
     162           0 :         va_start(ap, fmt);
     163           0 :         ld->log_fn(ld->log_private, level, fmt, ap);
     164           0 :         va_end(ap);
     165             : }
     166             : 
     167         442 : static int tldap_next_msgid(struct tldap_context *ld)
     168             : {
     169           0 :         int result;
     170             : 
     171         442 :         result = ld->msgid++;
     172         442 :         if (ld->msgid == INT_MAX) {
     173           0 :                 ld->msgid = 1;
     174             :         }
     175         442 :         return result;
     176             : }
     177             : 
     178           8 : struct tldap_context *tldap_context_create(TALLOC_CTX *mem_ctx, int fd)
     179             : {
     180           0 :         struct tldap_context *ctx;
     181           0 :         int ret;
     182             : 
     183           8 :         ctx = talloc_zero(mem_ctx, struct tldap_context);
     184           8 :         if (ctx == NULL) {
     185           0 :                 return NULL;
     186             :         }
     187           8 :         ret = tstream_bsd_existing_socket(ctx, fd, &ctx->plain);
     188           8 :         if (ret == -1) {
     189           0 :                 TALLOC_FREE(ctx);
     190           0 :                 return NULL;
     191             :         }
     192           8 :         ctx->active = ctx->plain;
     193           8 :         ctx->msgid = 1;
     194           8 :         ctx->ld_version = 3;
     195           8 :         ctx->outgoing = tevent_queue_create(ctx, "tldap_outgoing");
     196           8 :         if (ctx->outgoing == NULL) {
     197           0 :                 TALLOC_FREE(ctx);
     198           0 :                 return NULL;
     199             :         }
     200           8 :         return ctx;
     201             : }
     202             : 
     203         446 : bool tldap_connection_ok(struct tldap_context *ld)
     204             : {
     205           0 :         int ret;
     206             : 
     207         446 :         if (ld == NULL) {
     208           0 :                 return false;
     209             :         }
     210             : 
     211         446 :         if (ld->active == NULL) {
     212           0 :                 return false;
     213             :         }
     214             : 
     215         446 :         ret = tstream_pending_bytes(ld->active);
     216         446 :         if (ret == -1) {
     217           0 :                 return false;
     218             :         }
     219             : 
     220         446 :         return true;
     221             : }
     222             : 
     223        4804 : static size_t tldap_pending_reqs(struct tldap_context *ld)
     224             : {
     225        4804 :         return talloc_array_length(ld->pending);
     226             : }
     227             : 
     228           8 : struct tstream_context *tldap_get_plain_tstream(struct tldap_context *ld)
     229             : {
     230           8 :         return ld->plain;
     231             : }
     232             : 
     233           6 : void tldap_set_starttls_needed(struct tldap_context *ld, bool needed)
     234             : {
     235           6 :         if (ld == NULL) {
     236           0 :                 return;
     237             :         }
     238             : 
     239           6 :         ld->starttls_needed = needed;
     240             : }
     241             : 
     242           4 : bool tldap_get_starttls_needed(struct tldap_context *ld)
     243             : {
     244           4 :         if (ld == NULL) {
     245           0 :                 return false;
     246             :         }
     247             : 
     248           4 :         return ld->starttls_needed;
     249             : }
     250             : 
     251          12 : bool tldap_has_tls_tstream(struct tldap_context *ld)
     252             : {
     253          12 :         return ld->tls != NULL && ld->active == ld->tls;
     254             : }
     255             : 
     256           4 : const DATA_BLOB *tldap_tls_channel_bindings(struct tldap_context *ld)
     257             : {
     258           4 :         return tstream_tls_channel_bindings(ld->tls);
     259             : }
     260             : 
     261           4 : void tldap_set_tls_tstream(struct tldap_context *ld,
     262             :                            struct tstream_context **stream)
     263             : {
     264           4 :         TALLOC_FREE(ld->tls);
     265           4 :         if (stream != NULL) {
     266           4 :                 ld->tls = talloc_move(ld, stream);
     267             :         }
     268           4 :         if (ld->tls != NULL) {
     269           4 :                 ld->active = ld->tls;
     270             :         } else {
     271           0 :                 ld->active = ld->plain;
     272             :         }
     273           4 : }
     274             : 
     275           4 : bool tldap_has_gensec_tstream(struct tldap_context *ld)
     276             : {
     277           4 :         return ld->gensec != NULL && ld->active == ld->gensec;
     278             : }
     279             : 
     280           4 : void tldap_set_gensec_tstream(struct tldap_context *ld,
     281             :                               struct tstream_context **stream)
     282             : {
     283           4 :         TALLOC_FREE(ld->gensec);
     284           4 :         if (stream != NULL) {
     285           4 :                 ld->gensec = talloc_move(ld, stream);
     286             :         }
     287           4 :         if (ld->gensec != NULL) {
     288           4 :                 ld->active = ld->gensec;
     289             :         } else {
     290           0 :                 ld->active = ld->plain;
     291             :         }
     292           4 : }
     293             : 
     294          16 : static struct tldap_ctx_attribute *tldap_context_findattr(
     295             :         struct tldap_context *ld, const char *name)
     296             : {
     297           0 :         size_t i, num_attrs;
     298             : 
     299          16 :         num_attrs = talloc_array_length(ld->ctx_attrs);
     300             : 
     301          16 :         for (i=0; i<num_attrs; i++) {
     302           8 :                 if (strcmp(ld->ctx_attrs[i].name, name) == 0) {
     303           8 :                         return &ld->ctx_attrs[i];
     304             :                 }
     305             :         }
     306           8 :         return NULL;
     307             : }
     308             : 
     309           8 : bool tldap_context_setattr(struct tldap_context *ld,
     310             :                            const char *name, const void *_pptr)
     311             : {
     312           0 :         struct tldap_ctx_attribute *tmp, *attr;
     313           0 :         char *tmpname;
     314           0 :         int num_attrs;
     315           8 :         void **pptr = (void **)discard_const_p(void,_pptr);
     316             : 
     317           8 :         attr = tldap_context_findattr(ld, name);
     318           8 :         if (attr != NULL) {
     319             :                 /*
     320             :                  * We don't actually delete attrs, we don't expect tons of
     321             :                  * attributes being shuffled around.
     322             :                  */
     323           0 :                 TALLOC_FREE(attr->ptr);
     324           0 :                 if (*pptr != NULL) {
     325           0 :                         attr->ptr = talloc_move(ld->ctx_attrs, pptr);
     326           0 :                         *pptr = NULL;
     327             :                 }
     328           0 :                 return true;
     329             :         }
     330             : 
     331           8 :         tmpname = talloc_strdup(ld, name);
     332           8 :         if (tmpname == NULL) {
     333           0 :                 return false;
     334             :         }
     335             : 
     336           8 :         num_attrs = talloc_array_length(ld->ctx_attrs);
     337             : 
     338           8 :         tmp = talloc_realloc(ld, ld->ctx_attrs, struct tldap_ctx_attribute,
     339             :                              num_attrs+1);
     340           8 :         if (tmp == NULL) {
     341           0 :                 TALLOC_FREE(tmpname);
     342           0 :                 return false;
     343             :         }
     344           8 :         tmp[num_attrs].name = talloc_move(tmp, &tmpname);
     345           8 :         if (*pptr != NULL) {
     346           8 :                 tmp[num_attrs].ptr = talloc_move(tmp, pptr);
     347             :         } else {
     348           0 :                 tmp[num_attrs].ptr = NULL;
     349             :         }
     350           8 :         *pptr = NULL;
     351           8 :         ld->ctx_attrs = tmp;
     352           8 :         return true;
     353             : }
     354             : 
     355           8 : void *tldap_context_getattr(struct tldap_context *ld, const char *name)
     356             : {
     357           8 :         struct tldap_ctx_attribute *attr = tldap_context_findattr(ld, name);
     358             : 
     359           8 :         if (attr == NULL) {
     360           0 :                 return NULL;
     361             :         }
     362           8 :         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        2386 : static struct tevent_req *read_ldap_send(TALLOC_CTX *mem_ctx,
     373             :                                          struct tevent_context *ev,
     374             :                                          struct tstream_context *conn)
     375             : {
     376           0 :         struct tevent_req *req, *subreq;
     377           0 :         struct read_ldap_state *state;
     378             : 
     379        2386 :         req = tevent_req_create(mem_ctx, &state, struct read_ldap_state);
     380        2386 :         if (req == NULL) {
     381           0 :                 return NULL;
     382             :         }
     383             : 
     384        2386 :         subreq = tstream_read_packet_send(state, ev, conn, 7, read_ldap_more,
     385             :                                           state);
     386        2386 :         if (tevent_req_nomem(subreq, req)) {
     387           0 :                 return tevent_req_post(req, ev);
     388             :         }
     389        2386 :         tevent_req_set_callback(subreq, read_ldap_done, req);
     390        2386 :         return req;
     391             : }
     392             : 
     393        4772 : static ssize_t read_ldap_more(uint8_t *buf, size_t buflen, void *private_data)
     394             : {
     395        4772 :         const DATA_BLOB blob = data_blob_const(buf, buflen);
     396        4772 :         size_t pdu_len = 0;
     397           0 :         int ret;
     398             : 
     399        4772 :         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           0 :                 return -1;
     408             :         }
     409             : 
     410        4772 :         ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), &pdu_len);
     411        4772 :         if (ret == 0) {
     412        2386 :                 return 0;
     413             :         }
     414        2386 :         if (ret == EAGAIN) {
     415        2386 :                 return pdu_len - buflen;
     416             :         }
     417             : 
     418           0 :         return -1;
     419             : }
     420             : 
     421        2386 : static void read_ldap_done(struct tevent_req *subreq)
     422             : {
     423        2386 :         struct tevent_req *req = tevent_req_callback_data(
     424             :                 subreq, struct tevent_req);
     425        2386 :         struct read_ldap_state *state = tevent_req_data(
     426             :                 req, struct read_ldap_state);
     427           0 :         ssize_t nread;
     428           0 :         int err;
     429             : 
     430        2386 :         nread = tstream_read_packet_recv(subreq, state, &state->buf, &err);
     431        2386 :         TALLOC_FREE(subreq);
     432        2386 :         if (nread == -1) {
     433           0 :                 tevent_req_error(req, err);
     434           0 :                 return;
     435             :         }
     436        2386 :         tevent_req_done(req);
     437             : }
     438             : 
     439        2386 : static ssize_t read_ldap_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     440             :                               uint8_t **pbuf, int *perrno)
     441             : {
     442        2386 :         struct read_ldap_state *state = tevent_req_data(
     443             :                 req, struct read_ldap_state);
     444             : 
     445        2386 :         if (tevent_req_is_unix_error(req, perrno)) {
     446           0 :                 return -1;
     447             :         }
     448        2386 :         *pbuf = talloc_move(mem_ctx, &state->buf);
     449        2386 :         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         442 : static bool tldap_push_controls(struct asn1_data *data,
     463             :                                 struct tldap_control *sctrls,
     464             :                                 int num_sctrls)
     465             : {
     466           0 :         int i;
     467             : 
     468         442 :         if ((sctrls == NULL) || (num_sctrls == 0)) {
     469          34 :                 return true;
     470             :         }
     471             : 
     472         408 :         if (!asn1_push_tag(data, ASN1_CONTEXT(0))) return false;
     473             : 
     474         816 :         for (i=0; i<num_sctrls; i++) {
     475         408 :                 struct tldap_control *c = &sctrls[i];
     476         408 :                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
     477         408 :                 if (!asn1_write_OctetString(data, c->oid, strlen(c->oid))) return false;
     478         408 :                 if (c->critical) {
     479         408 :                         if (!asn1_write_BOOLEAN(data, true)) return false;
     480             :                 }
     481         408 :                 if (c->value.data != NULL) {
     482         400 :                         if (!asn1_write_OctetString(data, c->value.data,
     483           0 :                                                c->value.length)) return false;
     484             :                 }
     485         408 :                 if (!asn1_pop_tag(data)) return false; /* ASN1_SEQUENCE(0) */
     486             :         }
     487             : 
     488         408 :         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           0 : static void _tldap_context_disconnect(struct tldap_context *ld,
     495             :                                       TLDAPRC status,
     496             :                                       const char *location)
     497             : {
     498           0 :         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           0 :                 return;
     507             :         }
     508             : 
     509           0 :         tldap_debug(ld, TLDAP_DEBUG_WARNING,
     510             :                     "tldap_context_disconnect: %s at %s\n",
     511             :                     tldap_rc2string(status),
     512             :                     location);
     513           0 :         tevent_queue_stop(ld->outgoing);
     514           0 :         TALLOC_FREE(ld->read_req);
     515           0 :         ld->active = NULL;
     516           0 :         TALLOC_FREE(ld->gensec);
     517           0 :         TALLOC_FREE(ld->tls);
     518           0 :         TALLOC_FREE(ld->plain);
     519             : 
     520           0 :         while (talloc_array_length(ld->pending) > 0) {
     521           0 :                 struct tevent_req *req = NULL;
     522           0 :                 struct tldap_msg_state *state = NULL;
     523             : 
     524           0 :                 req = ld->pending[0];
     525           0 :                 state = tevent_req_data(req, struct tldap_msg_state);
     526           0 :                 tevent_req_defer_callback(req, state->ev);
     527           0 :                 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         442 : 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           0 :         struct tevent_req *req, *subreq;
     542           0 :         struct tldap_msg_state *state;
     543           0 :         DATA_BLOB blob;
     544           0 :         bool ok;
     545             : 
     546         442 :         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_send: sending msg %d\n",
     547             :                     id);
     548             : 
     549         442 :         req = tevent_req_create(mem_ctx, &state, struct tldap_msg_state);
     550         442 :         if (req == NULL) {
     551           0 :                 return NULL;
     552             :         }
     553         442 :         state->ld = ld;
     554         442 :         state->ev = ev;
     555         442 :         state->id = id;
     556             : 
     557         442 :         ok = tldap_connection_ok(ld);
     558         442 :         if (!ok) {
     559           0 :                 tevent_req_ldap_error(req, TLDAP_SERVER_DOWN);
     560           0 :                 return tevent_req_post(req, ev);
     561             :         }
     562             : 
     563         442 :         if (!tldap_push_controls(data, sctrls, num_sctrls)) {
     564           0 :                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
     565           0 :                 return tevent_req_post(req, ev);
     566             :         }
     567             : 
     568             : 
     569         442 :         if (!asn1_pop_tag(data)) {
     570           0 :                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
     571           0 :                 return tevent_req_post(req, ev);
     572             :         }
     573             : 
     574         442 :         if (!asn1_blob(data, &blob)) {
     575           0 :                 tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
     576           0 :                 return tevent_req_post(req, ev);
     577             :         }
     578             : 
     579         442 :         if (!tldap_msg_set_pending(req)) {
     580           0 :                 tevent_req_oom(req);
     581           0 :                 return tevent_req_post(req, ev);;
     582             :         }
     583             : 
     584         442 :         state->iov.iov_base = (void *)blob.data;
     585         442 :         state->iov.iov_len = blob.length;
     586             : 
     587         442 :         subreq = tstream_writev_queue_send(state, ev, ld->active, ld->outgoing,
     588         442 :                                            &state->iov, 1);
     589         442 :         if (tevent_req_nomem(subreq, req)) {
     590           0 :                 return tevent_req_post(req, ev);
     591             :         }
     592         442 :         tevent_req_set_callback(subreq, tldap_msg_sent, req);
     593         442 :         return req;
     594             : }
     595             : 
     596        2386 : static void tldap_msg_unset_pending(struct tevent_req *req)
     597             : {
     598        2386 :         struct tldap_msg_state *state = tevent_req_data(
     599             :                 req, struct tldap_msg_state);
     600        2386 :         struct tldap_context *ld = state->ld;
     601        2386 :         int num_pending = tldap_pending_reqs(ld);
     602           0 :         int i;
     603             : 
     604        2386 :         tevent_req_set_cleanup_fn(req, NULL);
     605             : 
     606        2386 :         for (i=0; i<num_pending; i++) {
     607        2386 :                 if (req == ld->pending[i]) {
     608        2386 :                         break;
     609             :                 }
     610             :         }
     611        2386 :         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           0 :                 return;
     618             :         }
     619             : 
     620        2386 :         if (num_pending == 1) {
     621        2386 :                 TALLOC_FREE(ld->pending);
     622        2386 :                 return;
     623             :         }
     624             : 
     625             :         /*
     626             :          * Remove ourselves from the cli->pending array
     627             :          */
     628           0 :         if (num_pending > 1) {
     629           0 :                 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           0 :         ld->pending = talloc_realloc(NULL, ld->pending, struct tevent_req *,
     637             :                                      num_pending - 1);
     638             : }
     639             : 
     640           0 : static void tldap_msg_cleanup(struct tevent_req *req,
     641             :                               enum tevent_req_state req_state)
     642             : {
     643           0 :         tldap_msg_unset_pending(req);
     644           0 : }
     645             : 
     646        2386 : static bool tldap_msg_set_pending(struct tevent_req *req)
     647             : {
     648        2386 :         struct tldap_msg_state *state = tevent_req_data(
     649             :                 req, struct tldap_msg_state);
     650           0 :         struct tldap_context *ld;
     651           0 :         struct tevent_req **pending;
     652           0 :         int num_pending;
     653             : 
     654        2386 :         ld = state->ld;
     655        2386 :         num_pending = tldap_pending_reqs(ld);
     656             : 
     657        2386 :         pending = talloc_realloc(ld, ld->pending, struct tevent_req *,
     658             :                                  num_pending+1);
     659        2386 :         if (pending == NULL) {
     660           0 :                 return false;
     661             :         }
     662        2386 :         pending[num_pending] = req;
     663        2386 :         ld->pending = pending;
     664        2386 :         tevent_req_set_cleanup_fn(req, tldap_msg_cleanup);
     665             : 
     666        2386 :         if (ld->read_req != NULL) {
     667           0 :                 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        2386 :         ld->read_req = read_ldap_send(ld->pending, state->ev, ld->active);
     675        2386 :         if (ld->read_req == NULL) {
     676           0 :                 tldap_msg_unset_pending(req);
     677           0 :                 return false;
     678             :         }
     679        2386 :         tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
     680        2386 :         return true;
     681             : }
     682             : 
     683         442 : static void tldap_msg_sent(struct tevent_req *subreq)
     684             : {
     685         442 :         struct tevent_req *req = tevent_req_callback_data(
     686             :                 subreq, struct tevent_req);
     687         442 :         struct tldap_msg_state *state = tevent_req_data(
     688             :                 req, struct tldap_msg_state);
     689           0 :         ssize_t nwritten;
     690           0 :         int err;
     691             : 
     692         442 :         nwritten = tstream_writev_queue_recv(subreq, &err);
     693         442 :         TALLOC_FREE(subreq);
     694         442 :         if (nwritten == -1) {
     695           0 :                 tldap_context_disconnect(state->ld, TLDAP_SERVER_DOWN);
     696           0 :                 return;
     697             :         }
     698             : }
     699             : 
     700        2386 : static int tldap_msg_msgid(struct tevent_req *req)
     701             : {
     702        2386 :         struct tldap_msg_state *state = tevent_req_data(
     703             :                 req, struct tldap_msg_state);
     704             : 
     705        2386 :         return state->id;
     706             : }
     707             : 
     708        2386 : static void tldap_msg_received(struct tevent_req *subreq)
     709             : {
     710        2386 :         struct tldap_context *ld = tevent_req_callback_data(
     711             :                 subreq, struct tldap_context);
     712           0 :         struct tevent_req *req;
     713           0 :         struct tldap_msg_state *state;
     714           0 :         struct asn1_data *data;
     715           0 :         uint8_t *inbuf;
     716           0 :         ssize_t received;
     717           0 :         size_t num_pending;
     718           0 :         size_t i;
     719           0 :         int err;
     720        2386 :         TLDAPRC status = TLDAP_PROTOCOL_ERROR;
     721           0 :         int id;
     722           0 :         uint8_t type;
     723           0 :         bool ok;
     724             : 
     725        2386 :         received = read_ldap_recv(subreq, talloc_tos(), &inbuf, &err);
     726        2386 :         TALLOC_FREE(subreq);
     727        2386 :         ld->read_req = NULL;
     728        2386 :         if (received == -1) {
     729           0 :                 status = TLDAP_SERVER_DOWN;
     730           0 :                 goto fail;
     731             :         }
     732             : 
     733        2386 :         data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
     734        2386 :         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           0 :                 status = TLDAP_NO_MEMORY;
     740           0 :                 goto fail;
     741             :         }
     742        2386 :         asn1_load_nocopy(data, inbuf, received);
     743             : 
     744        2386 :         ok = true;
     745        2386 :         ok &= asn1_start_tag(data, ASN1_SEQUENCE(0));
     746        2386 :         ok &= asn1_read_Integer(data, &id);
     747        2386 :         ok &= asn1_peek_uint8(data, &type);
     748             : 
     749        2386 :         if (!ok) {
     750           0 :                 status = TLDAP_PROTOCOL_ERROR;
     751           0 :                 goto fail;
     752             :         }
     753             : 
     754        2386 :         tldap_debug(ld, TLDAP_DEBUG_TRACE, "tldap_msg_received: got msg %d "
     755             :                     "type %d\n", id, (int)type);
     756             : 
     757        2386 :         if (id == 0) {
     758           0 :                 tldap_debug(
     759             :                         ld,
     760             :                         TLDAP_DEBUG_WARNING,
     761             :                         "tldap_msg_received: got msgid 0 of "
     762             :                         "type %"PRIu8", disconnecting\n",
     763             :                         type);
     764           0 :                 tldap_context_disconnect(ld, TLDAP_SERVER_DOWN);
     765           0 :                 return;
     766             :         }
     767             : 
     768        2386 :         num_pending = talloc_array_length(ld->pending);
     769             : 
     770        2386 :         for (i=0; i<num_pending; i++) {
     771        2386 :                 if (id == tldap_msg_msgid(ld->pending[i])) {
     772        2386 :                         break;
     773             :                 }
     774             :         }
     775        2386 :         if (i == num_pending) {
     776             :                 /* Dump unexpected reply */
     777           0 :                 tldap_debug(ld, TLDAP_DEBUG_WARNING, "tldap_msg_received: "
     778             :                             "No request pending for msg %d\n", id);
     779           0 :                 TALLOC_FREE(data);
     780           0 :                 TALLOC_FREE(inbuf);
     781           0 :                 goto done;
     782             :         }
     783             : 
     784        2386 :         req = ld->pending[i];
     785        2386 :         state = tevent_req_data(req, struct tldap_msg_state);
     786             : 
     787        2386 :         state->inbuf = talloc_move(state, &inbuf);
     788        2386 :         state->data = talloc_move(state, &data);
     789             : 
     790        2386 :         tldap_msg_unset_pending(req);
     791        2386 :         num_pending = talloc_array_length(ld->pending);
     792             : 
     793        2386 :         tevent_req_defer_callback(req, state->ev);
     794        2386 :         tevent_req_done(req);
     795             : 
     796        2386 :  done:
     797        2386 :         if (num_pending == 0) {
     798        2386 :                 return;
     799             :         }
     800             : 
     801           0 :         state = tevent_req_data(ld->pending[0],      struct tldap_msg_state);
     802           0 :         ld->read_req = read_ldap_send(ld->pending, state->ev, ld->active);
     803           0 :         if (ld->read_req == NULL) {
     804           0 :                 status = TLDAP_NO_MEMORY;
     805           0 :                 goto fail;
     806             :         }
     807           0 :         tevent_req_set_callback(ld->read_req, tldap_msg_received, ld);
     808           0 :         return;
     809             : 
     810           0 :  fail:
     811           0 :         tldap_context_disconnect(ld, status);
     812             : }
     813             : 
     814        2386 : static TLDAPRC tldap_msg_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     815             :                               struct tldap_message **pmsg)
     816             : {
     817        2386 :         struct tldap_msg_state *state = tevent_req_data(
     818             :                 req, struct tldap_msg_state);
     819           0 :         struct tldap_message *msg;
     820           0 :         TLDAPRC err;
     821           0 :         uint8_t msgtype;
     822             : 
     823        2386 :         if (tevent_req_is_ldap_error(req, &err)) {
     824           0 :                 return err;
     825             :         }
     826             : 
     827        2386 :         if (!asn1_peek_uint8(state->data, &msgtype)) {
     828           0 :                 return TLDAP_PROTOCOL_ERROR;
     829             :         }
     830             : 
     831        2386 :         if (pmsg == NULL) {
     832           0 :                 return TLDAP_SUCCESS;
     833             :         }
     834             : 
     835        2386 :         msg = talloc_zero(mem_ctx, struct tldap_message);
     836        2386 :         if (msg == NULL) {
     837           0 :                 return TLDAP_NO_MEMORY;
     838             :         }
     839        2386 :         msg->id = state->id;
     840             : 
     841        2386 :         msg->inbuf = talloc_move(msg, &state->inbuf);
     842        2386 :         msg->data = talloc_move(msg, &state->data);
     843        2386 :         msg->type = msgtype;
     844             : 
     845        2386 :         *pmsg = msg;
     846        2386 :         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         442 : static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
     856             :                                            struct tldap_context *ld,
     857             :                                            struct tldap_req_state **pstate)
     858             : {
     859           0 :         struct tevent_req *req;
     860           0 :         struct tldap_req_state *state;
     861             : 
     862         442 :         req = tevent_req_create(mem_ctx, &state, struct tldap_req_state);
     863         442 :         if (req == NULL) {
     864           0 :                 return NULL;
     865             :         }
     866         442 :         state->out = asn1_init(state, ASN1_MAX_TREE_DEPTH);
     867         442 :         if (state->out == NULL) {
     868           0 :                 goto err;
     869             :         }
     870         442 :         state->id = tldap_next_msgid(ld);
     871             : 
     872         442 :         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
     873         442 :         if (!asn1_write_Integer(state->out, state->id)) goto err;
     874             : 
     875         442 :         *pstate = state;
     876         442 :         return req;
     877             : 
     878           0 :   err:
     879             : 
     880           0 :         TALLOC_FREE(req);
     881           0 :         return NULL;
     882             : }
     883             : 
     884           0 : static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
     885             : {
     886           0 :         struct tldap_req_state *state = tevent_req_data(
     887             :                 req, struct tldap_req_state);
     888             : 
     889           0 :         TALLOC_FREE(ld->last_msg);
     890           0 :         ld->last_msg = talloc_move(ld, &state->result);
     891           0 : }
     892             : 
     893       33212 : static char *blob2string_talloc(TALLOC_CTX *mem_ctx, DATA_BLOB blob)
     894             : {
     895       33212 :         char *result = talloc_array(mem_ctx, char, blob.length+1);
     896             : 
     897       33212 :         if (result == NULL) {
     898           0 :                 return NULL;
     899             :         }
     900             : 
     901       33212 :         memcpy(result, blob.data, blob.length);
     902       33212 :         result[blob.length] = '\0';
     903       33212 :         return result;
     904             : }
     905             : 
     906       33212 : static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
     907             :                                          struct asn1_data *data,
     908             :                                          char **presult)
     909             : {
     910           0 :         DATA_BLOB string;
     911           0 :         char *result;
     912       33212 :         if (!asn1_read_OctetString(data, mem_ctx, &string))
     913           0 :                 return false;
     914             : 
     915       33212 :         result = blob2string_talloc(mem_ctx, string);
     916             : 
     917       33212 :         data_blob_free(&string);
     918             : 
     919       33212 :         if (result == NULL) {
     920           0 :                 return false;
     921             :         }
     922       33212 :         *presult = result;
     923       33212 :         return true;
     924             : }
     925             : 
     926             : static bool tldap_decode_controls(struct tldap_req_state *state);
     927             : 
     928         442 : static bool tldap_decode_response(struct tldap_req_state *state)
     929             : {
     930         442 :         struct asn1_data *data = state->result->data;
     931         442 :         struct tldap_message *msg = state->result;
     932           0 :         int rc;
     933         442 :         bool ok = true;
     934             : 
     935         442 :         ok &= asn1_read_enumerated(data, &rc);
     936         442 :         if (ok) {
     937         442 :                 msg->lderr = TLDAP_RC(rc);
     938             :         }
     939             : 
     940         442 :         ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
     941         442 :         ok &= asn1_read_OctetString_talloc(msg, data,
     942             :                                            &msg->res_diagnosticmessage);
     943         442 :         if (!ok) return ok;
     944         442 :         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
     945           0 :                 ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
     946           0 :                 ok &= asn1_read_OctetString_talloc(msg, data,
     947             :                                                    &msg->res_referral);
     948           0 :                 ok &= asn1_end_tag(data);
     949             :         } else {
     950         442 :                 msg->res_referral = NULL;
     951             :         }
     952             : 
     953         442 :         return ok;
     954             : }
     955             : 
     956             : static void tldap_sasl_bind_done(struct tevent_req *subreq);
     957             : 
     958          16 : 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           0 :         struct tevent_req *req, *subreq;
     970           0 :         struct tldap_req_state *state;
     971             : 
     972          16 :         req = tldap_req_create(mem_ctx, ld, &state);
     973          16 :         if (req == NULL) {
     974           0 :                 return NULL;
     975             :         }
     976             : 
     977          16 :         if (dn == NULL) {
     978           0 :                 dn = "";
     979             :         }
     980             : 
     981          16 :         if (!asn1_push_tag(state->out, TLDAP_REQ_BIND)) goto err;
     982          16 :         if (!asn1_write_Integer(state->out, ld->ld_version)) goto err;
     983          16 :         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
     984             : 
     985          16 :         if (mechanism == NULL) {
     986           0 :                 if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0))) goto err;
     987           0 :                 if (!asn1_write(state->out, creds->data, creds->length)) goto err;
     988           0 :                 if (!asn1_pop_tag(state->out)) goto err;
     989             :         } else {
     990          16 :                 if (!asn1_push_tag(state->out, ASN1_CONTEXT(3))) goto err;
     991          16 :                 if (!asn1_write_OctetString(state->out, mechanism,
     992           0 :                                        strlen(mechanism))) goto err;
     993          16 :                 if ((creds != NULL) && (creds->data != NULL)) {
     994          16 :                         if (!asn1_write_OctetString(state->out, creds->data,
     995           0 :                                                creds->length)) goto err;
     996             :                 }
     997          16 :                 if (!asn1_pop_tag(state->out)) goto err;
     998             :         }
     999             : 
    1000          16 :         if (!asn1_pop_tag(state->out)) goto err;
    1001             : 
    1002          16 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    1003             :                                 sctrls, num_sctrls);
    1004          16 :         if (tevent_req_nomem(subreq, req)) {
    1005           0 :                 return tevent_req_post(req, ev);
    1006             :         }
    1007          16 :         tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
    1008          16 :         return req;
    1009             : 
    1010           0 :   err:
    1011             : 
    1012           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    1013           0 :         return tevent_req_post(req, ev);
    1014             : }
    1015             : 
    1016          16 : static void tldap_sasl_bind_done(struct tevent_req *subreq)
    1017             : {
    1018          16 :         struct tevent_req *req = tevent_req_callback_data(
    1019             :                 subreq, struct tevent_req);
    1020          16 :         struct tldap_req_state *state = tevent_req_data(
    1021             :                 req, struct tldap_req_state);
    1022           0 :         TLDAPRC rc;
    1023           0 :         bool ok;
    1024             : 
    1025          16 :         rc = tldap_msg_recv(subreq, state, &state->result);
    1026          16 :         TALLOC_FREE(subreq);
    1027          16 :         if (tevent_req_ldap_error(req, rc)) {
    1028           0 :                 return;
    1029             :         }
    1030          16 :         if (state->result->type != TLDAP_RES_BIND) {
    1031           0 :                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
    1032           0 :                 return;
    1033             :         }
    1034             : 
    1035          16 :         ok = asn1_start_tag(state->result->data, TLDAP_RES_BIND);
    1036          16 :         ok &= tldap_decode_response(state);
    1037             : 
    1038          16 :         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(7))) {
    1039           0 :                 int len;
    1040             : 
    1041          16 :                 ok &= asn1_start_tag(state->result->data,
    1042             :                                      ASN1_CONTEXT_SIMPLE(7));
    1043          16 :                 if (!ok) {
    1044           0 :                         goto decode_error;
    1045             :                 }
    1046             : 
    1047          16 :                 len = asn1_tag_remaining(state->result->data);
    1048          16 :                 if (len == -1) {
    1049           0 :                         goto decode_error;
    1050             :                 }
    1051             : 
    1052          16 :                 state->result->res_serverSaslCreds =
    1053          16 :                         data_blob_talloc(state->result, NULL, len);
    1054          16 :                 if (state->result->res_serverSaslCreds.data == NULL) {
    1055           0 :                         goto decode_error;
    1056             :                 }
    1057             : 
    1058          16 :                 ok = asn1_read(state->result->data,
    1059          16 :                                state->result->res_serverSaslCreds.data,
    1060          16 :                                state->result->res_serverSaslCreds.length);
    1061             : 
    1062          16 :                 ok &= asn1_end_tag(state->result->data);
    1063             :         }
    1064             : 
    1065          16 :         ok &= asn1_end_tag(state->result->data);
    1066             : 
    1067          16 :         if (!ok) {
    1068           0 :                 goto decode_error;
    1069             :         }
    1070             : 
    1071          16 :         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr) &&
    1072           8 :             !TLDAP_RC_EQUAL(state->result->lderr,
    1073             :                             TLDAP_SASL_BIND_IN_PROGRESS)) {
    1074           0 :                 tevent_req_ldap_error(req, state->result->lderr);
    1075           0 :                 return;
    1076             :         }
    1077          16 :         tevent_req_done(req);
    1078          16 :         return;
    1079             : 
    1080           0 : decode_error:
    1081           0 :         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
    1082           0 :         return;
    1083             : }
    1084             : 
    1085          16 : TLDAPRC tldap_sasl_bind_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1086             :                              DATA_BLOB *serverSaslCreds)
    1087             : {
    1088          16 :         struct tldap_req_state *state = tevent_req_data(
    1089             :                 req, struct tldap_req_state);
    1090           0 :         TLDAPRC rc;
    1091             : 
    1092          16 :         if (tevent_req_is_ldap_error(req, &rc)) {
    1093           0 :                 return rc;
    1094             :         }
    1095             : 
    1096          16 :         if (serverSaslCreds != NULL) {
    1097          16 :                 serverSaslCreds->data = talloc_move(
    1098             :                         mem_ctx, &state->result->res_serverSaslCreds.data);
    1099          16 :                 serverSaslCreds->length =
    1100          16 :                         state->result->res_serverSaslCreds.length;
    1101             :         }
    1102             : 
    1103          16 :         return state->result->lderr;
    1104             : }
    1105             : 
    1106           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1118           0 :         struct tevent_context *ev;
    1119           0 :         struct tevent_req *req;
    1120           0 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    1121             : 
    1122           0 :         ev = samba_tevent_context_init(frame);
    1123           0 :         if (ev == NULL) {
    1124           0 :                 goto fail;
    1125             :         }
    1126           0 :         req = tldap_sasl_bind_send(frame, ev, ld, dn, mechanism, creds,
    1127             :                                    sctrls, num_sctrls, cctrls, num_cctrls);
    1128           0 :         if (req == NULL) {
    1129           0 :                 goto fail;
    1130             :         }
    1131           0 :         if (!tevent_req_poll(req, ev)) {
    1132           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    1133           0 :                 goto fail;
    1134             :         }
    1135           0 :         rc = tldap_sasl_bind_recv(req, mem_ctx, serverSaslCreds);
    1136           0 :         tldap_save_msg(ld, req);
    1137           0 :  fail:
    1138           0 :         TALLOC_FREE(frame);
    1139           0 :         return rc;
    1140             : }
    1141             : 
    1142           0 : 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           0 :         DATA_BLOB cred;
    1149             : 
    1150           0 :         if (passwd != NULL) {
    1151           0 :                 cred.data = discard_const_p(uint8_t, passwd);
    1152           0 :                 cred.length = strlen(passwd);
    1153             :         } else {
    1154           0 :                 cred.data = discard_const_p(uint8_t, "");
    1155           0 :                 cred.length = 0;
    1156             :         }
    1157           0 :         return tldap_sasl_bind_send(mem_ctx, ev, ld, dn, NULL, &cred, NULL, 0,
    1158             :                                     NULL, 0);
    1159             : }
    1160             : 
    1161           0 : TLDAPRC tldap_simple_bind_recv(struct tevent_req *req)
    1162             : {
    1163           0 :         return tldap_sasl_bind_recv(req, NULL, NULL);
    1164             : }
    1165             : 
    1166           0 : TLDAPRC tldap_simple_bind(struct tldap_context *ld, const char *dn,
    1167             :                           const char *passwd)
    1168             : {
    1169           0 :         DATA_BLOB cred;
    1170             : 
    1171           0 :         if (passwd != NULL) {
    1172           0 :                 cred.data = discard_const_p(uint8_t, passwd);
    1173           0 :                 cred.length = strlen(passwd);
    1174             :         } else {
    1175           0 :                 cred.data = discard_const_p(uint8_t, "");
    1176           0 :                 cred.length = 0;
    1177             :         }
    1178           0 :         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        4736 : static bool tldap_is_alpha(char c)
    1187             : {
    1188        4760 :         return (((c >= 'a') && (c <= 'z')) || \
    1189          24 :                 ((c >= 'A') && (c <= 'Z')));
    1190             : }
    1191             : 
    1192        4280 : static bool tldap_is_adh(char c)
    1193             : {
    1194        4280 :         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         472 : static bool tldap_is_attrdesc(const char *s, int len, bool no_tagopts)
    1219             : {
    1220         472 :         bool is_oid = false;
    1221         472 :         bool dot = false;
    1222           0 :         int i;
    1223             : 
    1224             :         /* first char has stricter rules */
    1225         472 :         if (isdigit(*s)) {
    1226          16 :                 is_oid = true;
    1227         456 :         } else if (!tldap_is_alpha(*s)) {
    1228             :                 /* bad first char */
    1229           0 :                 return false;
    1230             :         }
    1231             : 
    1232        4864 :         for (i = 1; i < len; i++) {
    1233             : 
    1234        4392 :                 if (is_oid) {
    1235         112 :                         if (isdigit(s[i])) {
    1236          64 :                                 dot = false;
    1237          64 :                                 continue;
    1238             :                         }
    1239          48 :                         if (s[i] == '.') {
    1240          48 :                                 if (dot) {
    1241             :                                         /* malformed */
    1242           0 :                                         return false;
    1243             :                                 }
    1244          48 :                                 dot = true;
    1245          48 :                                 continue;
    1246             :                         }
    1247             :                 } else {
    1248        4280 :                         if (tldap_is_adh(s[i])) {
    1249        4280 :                                 continue;
    1250             :                         }
    1251             :                 }
    1252             : 
    1253           0 :                 if (s[i] == ';') {
    1254           0 :                         if (no_tagopts) {
    1255             :                                 /* no tagging options */
    1256           0 :                                 return false;
    1257             :                         }
    1258           0 :                         if (dot) {
    1259             :                                 /* malformed */
    1260           0 :                                 return false;
    1261             :                         }
    1262           0 :                         if ((i + 1) == len) {
    1263             :                                 /* malformed */
    1264           0 :                                 return false;
    1265             :                         }
    1266             : 
    1267           0 :                         is_oid = false;
    1268           0 :                         continue;
    1269             :                 }
    1270             :         }
    1271             : 
    1272         472 :         if (dot) {
    1273             :                 /* malformed */
    1274           0 :                 return false;
    1275             :         }
    1276             : 
    1277         472 :         return true;
    1278             : }
    1279             : 
    1280             : /* this function copies the value until the closing parenthesis is found. */
    1281          56 : static char *tldap_get_val(TALLOC_CTX *memctx,
    1282             :                            const char *value, const char **_s)
    1283             : {
    1284          56 :         const char *s = value;
    1285             : 
    1286             :         /* find terminator */
    1287          56 :         while (*s) {
    1288          56 :                 s = strchr(s, ')');
    1289          56 :                 if (s && (*(s - 1) == '\\')) {
    1290           0 :                         s++;
    1291           0 :                         continue;
    1292             :                 }
    1293          56 :                 break;
    1294             :         }
    1295          56 :         if (!s || !(*s == ')')) {
    1296             :                 /* malformed filter */
    1297           0 :                 return NULL;
    1298             :         }
    1299             : 
    1300          56 :         *_s = s;
    1301             : 
    1302          56 :         return talloc_strndup(memctx, value, s - value);
    1303             : }
    1304             : 
    1305          14 : static int tldap_hex2char(const char *x)
    1306             : {
    1307          14 :         if (isxdigit(x[0]) && isxdigit(x[1])) {
    1308           7 :                 const char h1 = x[0], h2 = x[1];
    1309           7 :                 int c = 0;
    1310             : 
    1311           7 :                 if (h1 >= 'a') c = h1 - (int)'a' + 10;
    1312           7 :                 else if (h1 >= 'A') c = h1 - (int)'A' + 10;
    1313           7 :                 else if (h1 >= '0') c = h1 - (int)'0';
    1314           7 :                 c = c << 4;
    1315           7 :                 if (h2 >= 'a') c += h2 - (int)'a' + 10;
    1316           6 :                 else if (h2 >= 'A') c += h2 - (int)'A' + 10;
    1317           6 :                 else if (h2 >= '0') c += h2 - (int)'0';
    1318             : 
    1319           7 :                 return c;
    1320             :         }
    1321             : 
    1322           0 :         return -1;
    1323             : }
    1324             : 
    1325          64 : static bool tldap_find_first_star(const char *val, const char **star)
    1326             : {
    1327           0 :         const char *s;
    1328             : 
    1329         176 :         for (s = val; *s; s++) {
    1330         176 :                 switch (*s) {
    1331           0 :                 case '\\':
    1332           0 :                         if (isxdigit(s[1]) && isxdigit(s[2])) {
    1333           0 :                                 s += 2;
    1334           0 :                                 break;
    1335             :                         }
    1336             :                         /* not hex based escape, check older syntax */
    1337           0 :                         switch (s[1]) {
    1338           0 :                         case '(':
    1339             :                         case ')':
    1340             :                         case '*':
    1341             :                         case '\\':
    1342           0 :                                 s++;
    1343           0 :                                 break;
    1344           0 :                         default:
    1345             :                                 /* invalid escape sequence */
    1346           0 :                                 return false;
    1347             :                         }
    1348           0 :                         break;
    1349          24 :                 case ')':
    1350             :                         /* end of val, nothing found */
    1351          24 :                         *star = s;
    1352          24 :                         return true;
    1353             : 
    1354          40 :                 case '*':
    1355          40 :                         *star = s;
    1356          40 :                         return true;
    1357             :                 }
    1358             :         }
    1359             : 
    1360             :         /* string ended without closing parenthesis, filter is malformed */
    1361           0 :         return false;
    1362             : }
    1363             : 
    1364          90 : static bool tldap_unescape_inplace(char *value, size_t *val_len)
    1365             : {
    1366           2 :         int c;
    1367           2 :         size_t i, p;
    1368             : 
    1369         502 :         for (i = 0,p = 0; i < *val_len; i++) {
    1370             : 
    1371         412 :                 switch (value[i]) {
    1372           0 :                 case '(':
    1373             :                 case ')':
    1374             :                 case '*':
    1375             :                         /* these must be escaped */
    1376           0 :                         return false;
    1377             : 
    1378          14 :                 case '\\':
    1379          14 :                         if (!value[i + 1]) {
    1380             :                                 /* invalid EOL */
    1381           0 :                                 return false;
    1382             :                         }
    1383          14 :                         i++;
    1384             : 
    1385             :                         /* LDAPv3 escaped */
    1386          14 :                         c = tldap_hex2char(&value[i]);
    1387          14 :                         if (c >= 0 && c < 256) {
    1388           7 :                                 value[p] = c;
    1389           7 :                                 i++;
    1390           7 :                                 p++;
    1391           7 :                                 break;
    1392             :                         }
    1393             : 
    1394             :                         /* LDAPv2 escaped */
    1395           7 :                         switch (value[i]) {
    1396           7 :                         case '(':
    1397             :                         case ')':
    1398             :                         case '*':
    1399             :                         case '\\':
    1400           7 :                                 value[p] = value[i];
    1401           7 :                                 p++;
    1402             : 
    1403           7 :                                 break;
    1404           0 :                         default:
    1405             :                                 /* invalid */
    1406           0 :                                 return false;
    1407             :                         }
    1408           7 :                         break;
    1409             : 
    1410         398 :                 default:
    1411         398 :                         value[p] = value[i];
    1412         398 :                         p++;
    1413             :                 }
    1414             :         }
    1415          90 :         value[p] = '\0';
    1416          90 :         *val_len = p;
    1417          90 :         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         528 : static bool tldap_push_filter_int(struct tldap_context *ld,
    1428             :                                   struct asn1_data *data,
    1429             :                                   const char **_s)
    1430             : {
    1431         528 :         const char *s = *_s;
    1432           0 :         bool ret;
    1433             : 
    1434         528 :         if (*s != '(') {
    1435           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1436             :                             "Incomplete or malformed filter\n");
    1437           0 :                 return false;
    1438             :         }
    1439         528 :         s++;
    1440             : 
    1441             :         /* we are right after a parenthesis,
    1442             :          * find out what op we have at hand */
    1443         528 :         switch (*s) {
    1444           8 :         case '&':
    1445           8 :                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: AND\n");
    1446           8 :                 if (!asn1_push_tag(data, TLDAP_FILTER_AND)) return false;
    1447           8 :                 s++;
    1448           8 :                 break;
    1449             : 
    1450          16 :         case '|':
    1451          16 :                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: OR\n");
    1452          16 :                 if (!asn1_push_tag(data, TLDAP_FILTER_OR)) return false;
    1453          16 :                 s++;
    1454          16 :                 break;
    1455             : 
    1456          16 :         case '!':
    1457          16 :                 tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: NOT\n");
    1458          16 :                 if (!asn1_push_tag(data, TLDAP_FILTER_NOT)) return false;
    1459          16 :                 s++;
    1460          16 :                 ret = tldap_push_filter_int(ld, data, &s);
    1461          16 :                 if (!ret) {
    1462           0 :                         return false;
    1463             :                 }
    1464          16 :                 if (!asn1_pop_tag(data)) return false;
    1465          16 :                 goto done;
    1466             : 
    1467           0 :         case '(':
    1468             :         case ')':
    1469           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1470           0 :                             "Invalid parenthesis '%c'\n", *s);
    1471           0 :                 return false;
    1472             : 
    1473           0 :         case '\0':
    1474           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1475             :                             "Invalid filter termination\n");
    1476           0 :                 return false;
    1477             : 
    1478         488 :         default:
    1479         488 :                 ret = tldap_push_filter_basic(ld, data, &s);
    1480         488 :                 if (!ret) {
    1481           0 :                         return false;
    1482             :                 }
    1483         488 :                 goto done;
    1484             :         }
    1485             : 
    1486             :         /* only and/or filters get here.
    1487             :          * go through the list of filters */
    1488             : 
    1489          24 :         if (*s == ')') {
    1490             :                 /* RFC 4526: empty and/or */
    1491           0 :                 if (!asn1_pop_tag(data)) return false;
    1492           0 :                 goto done;
    1493             :         }
    1494             : 
    1495          88 :         while (*s) {
    1496          88 :                 ret = tldap_push_filter_int(ld, data, &s);
    1497          88 :                 if (!ret) {
    1498           0 :                         return false;
    1499             :                 }
    1500             : 
    1501          88 :                 if (*s == ')') {
    1502             :                         /* end of list, return */
    1503          24 :                         if (!asn1_pop_tag(data)) return false;
    1504          24 :                         break;
    1505             :                 }
    1506             :         }
    1507             : 
    1508           0 : done:
    1509         528 :         if (*s != ')') {
    1510           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1511             :                             "Incomplete or malformed filter\n");
    1512           0 :                 return false;
    1513             :         }
    1514         528 :         s++;
    1515             : 
    1516         528 :         if (asn1_has_error(data)) {
    1517           0 :                 return false;
    1518             :         }
    1519             : 
    1520         528 :         *_s = s;
    1521         528 :         return true;
    1522             : }
    1523             : 
    1524             : 
    1525         488 : static bool tldap_push_filter_basic(struct tldap_context *ld,
    1526             :                                     struct asn1_data *data,
    1527             :                                     const char **_s)
    1528             : {
    1529         488 :         TALLOC_CTX *tmpctx = talloc_tos();
    1530         488 :         const char *s = *_s;
    1531           0 :         const char *e;
    1532           0 :         const char *eq;
    1533           0 :         const char *val;
    1534           0 :         const char *type;
    1535           0 :         const char *dn;
    1536           0 :         const char *rule;
    1537           0 :         const char *star;
    1538         488 :         size_t type_len = 0;
    1539           0 :         char *uval;
    1540           0 :         size_t uval_len;
    1541         488 :         bool write_octect = true;
    1542           0 :         bool ret;
    1543             : 
    1544         488 :         eq = strchr(s, '=');
    1545         488 :         if (!eq) {
    1546           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1547             :                             "Invalid filter, missing equal sign\n");
    1548           0 :                 return false;
    1549             :         }
    1550             : 
    1551         488 :         val = eq + 1;
    1552         488 :         e = eq - 1;
    1553             : 
    1554         488 :         switch (*e) {
    1555           8 :         case '<':
    1556           8 :                 if (!asn1_push_tag(data, TLDAP_FILTER_LE)) return false;
    1557           8 :                 break;
    1558             : 
    1559           8 :         case '>':
    1560           8 :                 if (!asn1_push_tag(data, TLDAP_FILTER_GE)) return false;
    1561           8 :                 break;
    1562             : 
    1563           8 :         case '~':
    1564           8 :                 if (!asn1_push_tag(data, TLDAP_FILTER_APX)) return false;
    1565           8 :                 break;
    1566             : 
    1567          24 :         case ':':
    1568          24 :                 if (!asn1_push_tag(data, TLDAP_FILTER_EXT)) return false;
    1569          24 :                 write_octect = false;
    1570             : 
    1571          24 :                 type = NULL;
    1572          24 :                 dn = NULL;
    1573          24 :                 rule = NULL;
    1574             : 
    1575          24 :                 if (*s == ':') { /* [:dn]:rule:= value */
    1576           8 :                         if (s == e) {
    1577             :                                 /* malformed filter */
    1578           0 :                                 return false;
    1579             :                         }
    1580           8 :                         dn = s;
    1581             :                 } else { /* type[:dn][:rule]:= value */
    1582          16 :                         type = s;
    1583          16 :                         dn = strchr(s, ':');
    1584          16 :                         type_len = dn - type;
    1585          16 :                         if (dn == e) { /* type:= value */
    1586           8 :                                 dn = NULL;
    1587             :                         }
    1588             :                 }
    1589          24 :                 if (dn) {
    1590          16 :                         dn++;
    1591             : 
    1592          16 :                         rule = strchr(dn, ':');
    1593          16 :                         if (rule == NULL) {
    1594           0 :                                 return false;
    1595             :                         }
    1596          16 :                         if ((rule == dn + 1) || rule + 1 == e) {
    1597             :                                 /* malformed filter, contains "::" */
    1598           0 :                                 return false;
    1599             :                         }
    1600             : 
    1601          16 :                         if (strncasecmp_m(dn, "dn:", 3) != 0) {
    1602           0 :                                 if (rule == e) {
    1603           0 :                                         rule = dn;
    1604           0 :                                         dn = NULL;
    1605             :                                 } else {
    1606             :                                         /* malformed filter. With two
    1607             :                                          * optionals, the first must be "dn"
    1608             :                                          */
    1609           0 :                                         return false;
    1610             :                                 }
    1611             :                         } else {
    1612          16 :                                 if (rule == e) {
    1613           0 :                                         rule = NULL;
    1614             :                                 } else {
    1615          16 :                                         rule++;
    1616             :                                 }
    1617             :                         }
    1618             :                 }
    1619             : 
    1620          24 :                 if (!type && !dn && !rule) {
    1621             :                         /* malformed filter, there must be at least one */
    1622           0 :                         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          24 :                 if (rule) {
    1636          16 :                         ret = tldap_is_attrdesc(rule, e - rule, true);
    1637          16 :                         if (!ret) {
    1638           0 :                                 return false;
    1639             :                         }
    1640          16 :                         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
    1641          16 :                         if (!asn1_write(data, rule, e - rule)) return false;
    1642          16 :                         if (!asn1_pop_tag(data)) return false;
    1643             :                 }
    1644             : 
    1645             :                 /* check and add type */
    1646          24 :                 if (type) {
    1647          16 :                         ret = tldap_is_attrdesc(type, type_len, false);
    1648          16 :                         if (!ret) {
    1649           0 :                                 return false;
    1650             :                         }
    1651          16 :                         if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
    1652          16 :                         if (!asn1_write(data, type, type_len)) return false;
    1653          16 :                         if (!asn1_pop_tag(data)) return false;
    1654             :                 }
    1655             : 
    1656          24 :                 uval = tldap_get_val(tmpctx, val, _s);
    1657          24 :                 if (!uval) {
    1658           0 :                         return false;
    1659             :                 }
    1660          24 :                 uval_len = *_s - val;
    1661          24 :                 ret = tldap_unescape_inplace(uval, &uval_len);
    1662          24 :                 if (!ret) {
    1663           0 :                         return false;
    1664             :                 }
    1665             : 
    1666          24 :                 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
    1667          24 :                 if (!asn1_write(data, uval, uval_len)) return false;
    1668          24 :                 if (!asn1_pop_tag(data)) return false;
    1669             : 
    1670          24 :                 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
    1671          24 :                 if (!asn1_write_uint8(data, dn?1:0)) return false;
    1672          24 :                 if (!asn1_pop_tag(data)) return false;
    1673          24 :                 break;
    1674             : 
    1675         440 :         default:
    1676         440 :                 e = eq;
    1677             : 
    1678         440 :                 ret = tldap_is_attrdesc(s, e - s, false);
    1679         440 :                 if (!ret) {
    1680           0 :                         return false;
    1681             :                 }
    1682             : 
    1683         440 :                 if (strncmp(val, "*)", 2) == 0) {
    1684             :                         /* presence */
    1685         416 :                         if (!asn1_push_tag(data, TLDAP_FILTER_PRES)) return false;
    1686         416 :                         if (!asn1_write(data, s, e - s)) return false;
    1687         416 :                         *_s = val + 1;
    1688         416 :                         write_octect = false;
    1689         416 :                         break;
    1690             :                 }
    1691             : 
    1692          24 :                 ret = tldap_find_first_star(val, &star);
    1693          24 :                 if (!ret) {
    1694           0 :                         return false;
    1695             :                 }
    1696          24 :                 if (*star == '*') {
    1697             :                         /* substring */
    1698          16 :                         if (!asn1_push_tag(data, TLDAP_FILTER_SUB)) return false;
    1699          16 :                         if (!asn1_write_OctetString(data, s, e - s)) return false;
    1700          16 :                         ret = tldap_push_filter_substring(ld, data, val, &s);
    1701          16 :                         if (!ret) {
    1702           0 :                                 return false;
    1703             :                         }
    1704          16 :                         *_s = s;
    1705          16 :                         write_octect = false;
    1706          16 :                         break;
    1707             :                 }
    1708             : 
    1709             :                 /* if nothing else, then it is just equality */
    1710           8 :                 if (!asn1_push_tag(data, TLDAP_FILTER_EQ)) return false;
    1711           8 :                 write_octect = true;
    1712           8 :                 break;
    1713             :         }
    1714             : 
    1715         488 :         if (write_octect) {
    1716          32 :                 uval = tldap_get_val(tmpctx, val, _s);
    1717          32 :                 if (!uval) {
    1718           0 :                         return false;
    1719             :                 }
    1720          32 :                 uval_len = *_s - val;
    1721          32 :                 ret = tldap_unescape_inplace(uval, &uval_len);
    1722          32 :                 if (!ret) {
    1723           0 :                         return false;
    1724             :                 }
    1725             : 
    1726          32 :                 if (!asn1_write_OctetString(data, s, e - s)) return false;
    1727          32 :                 if (!asn1_write_OctetString(data, uval, uval_len)) return false;
    1728             :         }
    1729             : 
    1730         488 :         if (asn1_has_error(data)) {
    1731           0 :                 return false;
    1732             :         }
    1733         488 :         return asn1_pop_tag(data);
    1734             : }
    1735             : 
    1736          16 : 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          16 :         TALLOC_CTX *tmpctx = talloc_tos();
    1742          16 :         bool initial = true;
    1743           0 :         const char *star;
    1744           0 :         char *chunk;
    1745           0 :         size_t chunk_len;
    1746           0 :         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          16 :         if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
    1758             : 
    1759           0 :         do {
    1760          40 :                 ret = tldap_find_first_star(val, &star);
    1761          40 :                 if (!ret) {
    1762           0 :                         return false;
    1763             :                 }
    1764          40 :                 chunk_len = star - val;
    1765             : 
    1766          40 :                 switch (*star) {
    1767          24 :                 case '*':
    1768          24 :                         if (!initial && chunk_len == 0) {
    1769             :                                 /* found '**', which is illegal */
    1770           0 :                                 return false;
    1771             :                         }
    1772          24 :                         break;
    1773          16 :                 case ')':
    1774          16 :                         if (initial) {
    1775             :                                 /* no stars ?? */
    1776           0 :                                 return false;
    1777             :                         }
    1778             :                         /* we are done */
    1779          16 :                         break;
    1780           0 :                 default:
    1781             :                         /* ?? */
    1782           0 :                         return false;
    1783             :                 }
    1784             : 
    1785          40 :                 if (initial && chunk_len == 0) {
    1786           8 :                         val = star + 1;
    1787           8 :                         initial = false;
    1788           8 :                         continue;
    1789             :                 }
    1790             : 
    1791          32 :                 chunk = talloc_strndup(tmpctx, val, chunk_len);
    1792          32 :                 if (!chunk) {
    1793           0 :                         return false;
    1794             :                 }
    1795          32 :                 ret = tldap_unescape_inplace(chunk, &chunk_len);
    1796          32 :                 if (!ret) {
    1797           0 :                         return false;
    1798             :                 }
    1799          32 :                 switch (*star) {
    1800          16 :                 case '*':
    1801          16 :                         if (initial) {
    1802           8 :                                 if (!asn1_push_tag(data, TLDAP_SUB_INI)) return false;
    1803           8 :                                 initial = false;
    1804             :                         } else {
    1805           8 :                                 if (!asn1_push_tag(data, TLDAP_SUB_ANY)) return false;
    1806             :                         }
    1807          16 :                         break;
    1808          16 :                 case ')':
    1809          16 :                         if (!asn1_push_tag(data, TLDAP_SUB_FIN)) return false;
    1810          16 :                         break;
    1811           0 :                 default:
    1812             :                         /* ?? */
    1813           0 :                         return false;
    1814             :                 }
    1815          32 :                 if (!asn1_write(data, chunk, chunk_len)) return false;
    1816          32 :                 if (!asn1_pop_tag(data)) return false;
    1817             : 
    1818          32 :                 val = star + 1;
    1819             : 
    1820          40 :         } while (*star == '*');
    1821             : 
    1822          16 :         *_s = star;
    1823             : 
    1824             :         /* end of sequence */
    1825          16 :         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         424 : static bool tldap_push_filter(struct tldap_context *ld,
    1834             :                               struct asn1_data *data,
    1835             :                               const char *filter)
    1836             : {
    1837         424 :         const char *s = filter;
    1838           0 :         bool ret;
    1839             : 
    1840         424 :         ret = tldap_push_filter_int(ld, data, &s);
    1841         424 :         if (ret && *s) {
    1842           0 :                 tldap_debug(ld, TLDAP_DEBUG_ERROR,
    1843             :                             "Incomplete or malformed filter\n");
    1844           0 :                 return false;
    1845             :         }
    1846         424 :         return ret;
    1847             : }
    1848             : 
    1849             : /*****************************************************************************/
    1850             : 
    1851             : static void tldap_search_done(struct tevent_req *subreq);
    1852             : 
    1853         424 : 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           0 :         struct tevent_req *req, *subreq;
    1870           0 :         struct tldap_req_state *state;
    1871           0 :         int i;
    1872             : 
    1873         424 :         req = tldap_req_create(mem_ctx, ld, &state);
    1874         424 :         if (req == NULL) {
    1875           0 :                 return NULL;
    1876             :         }
    1877             : 
    1878         424 :         if (!asn1_push_tag(state->out, TLDAP_REQ_SEARCH)) goto encoding_error;
    1879         424 :         if (!asn1_write_OctetString(state->out, base, strlen(base))) goto encoding_error;
    1880         424 :         if (!asn1_write_enumerated(state->out, scope)) goto encoding_error;
    1881         424 :         if (!asn1_write_enumerated(state->out, deref)) goto encoding_error;
    1882         424 :         if (!asn1_write_Integer(state->out, sizelimit)) goto encoding_error;
    1883         424 :         if (!asn1_write_Integer(state->out, timelimit)) goto encoding_error;
    1884         424 :         if (!asn1_write_BOOLEAN(state->out, attrsonly)) goto encoding_error;
    1885             : 
    1886         424 :         if (!tldap_push_filter(ld, state->out, filter)) {
    1887           0 :                 goto encoding_error;
    1888             :         }
    1889             : 
    1890         424 :         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto encoding_error;
    1891         440 :         for (i=0; i<num_attrs; i++) {
    1892          16 :                 if (!asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]))) goto encoding_error;
    1893             :         }
    1894         424 :         if (!asn1_pop_tag(state->out)) goto encoding_error;
    1895         424 :         if (!asn1_pop_tag(state->out)) goto encoding_error;
    1896             : 
    1897         424 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    1898             :                                 sctrls, num_sctrls);
    1899         424 :         if (tevent_req_nomem(subreq, req)) {
    1900           0 :                 return tevent_req_post(req, ev);
    1901             :         }
    1902         424 :         tevent_req_set_callback(subreq, tldap_search_done, req);
    1903         424 :         return req;
    1904             : 
    1905           0 :  encoding_error:
    1906           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    1907           0 :         return tevent_req_post(req, ev);
    1908             : }
    1909             : 
    1910        2368 : static void tldap_search_done(struct tevent_req *subreq)
    1911             : {
    1912        2368 :         struct tevent_req *req = tevent_req_callback_data(
    1913             :                 subreq, struct tevent_req);
    1914        2368 :         struct tldap_req_state *state = tevent_req_data(
    1915             :                 req, struct tldap_req_state);
    1916           0 :         TLDAPRC rc;
    1917             : 
    1918        2368 :         rc = tldap_msg_recv(subreq, state, &state->result);
    1919        2368 :         if (tevent_req_ldap_error(req, rc)) {
    1920           0 :                 return;
    1921             :         }
    1922        2368 :         switch (state->result->type) {
    1923        1944 :         case TLDAP_RES_SEARCH_ENTRY:
    1924             :         case TLDAP_RES_SEARCH_REFERENCE:
    1925        1944 :                 if (!tldap_msg_set_pending(subreq)) {
    1926           0 :                         tevent_req_oom(req);
    1927           0 :                         return;
    1928             :                 }
    1929        1944 :                 tevent_req_notify_callback(req);
    1930        2368 :                 break;
    1931         424 :         case TLDAP_RES_SEARCH_RESULT:
    1932         424 :                 TALLOC_FREE(subreq);
    1933         424 :                 if (!asn1_start_tag(state->result->data,
    1934         424 :                                     state->result->type) ||
    1935         424 :                     !tldap_decode_response(state) ||
    1936         424 :                     !asn1_end_tag(state->result->data) ||
    1937         424 :                     !tldap_decode_controls(state)) {
    1938           0 :                         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
    1939           0 :                         return;
    1940             :                 }
    1941         424 :                 tevent_req_done(req);
    1942         424 :                 break;
    1943           0 :         default:
    1944           0 :                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
    1945           0 :                 return;
    1946             :         }
    1947             : }
    1948             : 
    1949        2368 : TLDAPRC tldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1950             :                           struct tldap_message **pmsg)
    1951             : {
    1952        2368 :         struct tldap_req_state *state = tevent_req_data(
    1953             :                 req, struct tldap_req_state);
    1954           0 :         TLDAPRC rc;
    1955             : 
    1956        2368 :         if (!tevent_req_is_in_progress(req)
    1957         424 :             && tevent_req_is_ldap_error(req, &rc)) {
    1958           0 :                 return rc;
    1959             :         }
    1960             : 
    1961        2368 :         if (tevent_req_is_in_progress(req)) {
    1962        1944 :                 switch (state->result->type) {
    1963        1944 :                 case TLDAP_RES_SEARCH_ENTRY:
    1964             :                 case TLDAP_RES_SEARCH_REFERENCE:
    1965        1944 :                         break;
    1966           0 :                 default:
    1967           0 :                         return TLDAP_OPERATIONS_ERROR;
    1968             :                 }
    1969             :         }
    1970             : 
    1971        2368 :         *pmsg = talloc_move(mem_ctx, &state->result);
    1972        2368 :         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          32 : 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           0 :         struct tevent_req *req, *subreq;
    1991           0 :         struct tldap_search_all_state *state;
    1992             : 
    1993          32 :         req = tevent_req_create(mem_ctx, &state,
    1994             :                                 struct tldap_search_all_state);
    1995          32 :         if (req == NULL) {
    1996           0 :                 return NULL;
    1997             :         }
    1998             : 
    1999          32 :         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          32 :         if (tevent_req_nomem(subreq, req)) {
    2004           0 :                 return tevent_req_post(req, ev);
    2005             :         }
    2006          32 :         tevent_req_set_callback(subreq, tldap_search_all_done, req);
    2007          32 :         return req;
    2008             : }
    2009             : 
    2010          64 : static void tldap_search_all_done(struct tevent_req *subreq)
    2011             : {
    2012          64 :         struct tevent_req *req = tevent_req_callback_data(
    2013             :                 subreq, struct tevent_req);
    2014          64 :         struct tldap_search_all_state *state = tevent_req_data(
    2015             :                 req, struct tldap_search_all_state);
    2016           0 :         struct tldap_message *msg, **tmp;
    2017           0 :         size_t num_msgs;
    2018           0 :         TLDAPRC rc;
    2019           0 :         int msgtype;
    2020             : 
    2021          64 :         rc = tldap_search_recv(subreq, state, &msg);
    2022             :         /* No TALLOC_FREE(subreq), this is multi-step */
    2023          64 :         if (tevent_req_ldap_error(req, rc)) {
    2024          32 :                 return;
    2025             :         }
    2026             : 
    2027          64 :         msgtype = tldap_msg_type(msg);
    2028          64 :         if (msgtype == TLDAP_RES_SEARCH_RESULT) {
    2029          32 :                 state->result = msg;
    2030          32 :                 tevent_req_done(req);
    2031          32 :                 return;
    2032             :         }
    2033             : 
    2034          32 :         num_msgs = talloc_array_length(state->msgs);
    2035             : 
    2036          32 :         tmp = talloc_realloc(state, state->msgs, struct tldap_message *,
    2037             :                              num_msgs + 1);
    2038          32 :         if (tevent_req_nomem(tmp, req)) {
    2039           0 :                 return;
    2040             :         }
    2041          32 :         state->msgs = tmp;
    2042          32 :         state->msgs[num_msgs] = talloc_move(state->msgs, &msg);
    2043             : }
    2044             : 
    2045          32 : 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          32 :         struct tldap_search_all_state *state = tevent_req_data(
    2050             :                 req, struct tldap_search_all_state);
    2051           0 :         TLDAPRC rc;
    2052             : 
    2053          32 :         if (tevent_req_is_ldap_error(req, &rc)) {
    2054           0 :                 return rc;
    2055             :         }
    2056             : 
    2057          32 :         if (msgs != NULL) {
    2058          32 :                 *msgs = talloc_move(mem_ctx, &state->msgs);
    2059             :         }
    2060          32 :         if (result != NULL) {
    2061          32 :                 *result = talloc_move(mem_ctx, &state->result);
    2062             :         }
    2063             : 
    2064          32 :         return TLDAP_SUCCESS;
    2065             : }
    2066             : 
    2067          32 : 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           0 :         TALLOC_CTX *frame;
    2076           0 :         struct tevent_context *ev;
    2077           0 :         struct tevent_req *req;
    2078          32 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    2079           0 :         struct tldap_message **msgs;
    2080           0 :         struct tldap_message *result;
    2081             : 
    2082          32 :         if (tldap_pending_reqs(ld)) {
    2083           0 :                 return TLDAP_BUSY;
    2084             :         }
    2085             : 
    2086          32 :         frame = talloc_stackframe();
    2087             : 
    2088          32 :         ev = samba_tevent_context_init(frame);
    2089          32 :         if (ev == NULL) {
    2090           0 :                 goto fail;
    2091             :         }
    2092          32 :         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          32 :         if (req == NULL) {
    2097           0 :                 goto fail;
    2098             :         }
    2099          32 :         if (!tevent_req_poll(req, ev)) {
    2100           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    2101           0 :                 goto fail;
    2102             :         }
    2103          32 :         rc = tldap_search_all_recv(req, frame, &msgs, &result);
    2104          32 :         TALLOC_FREE(req);
    2105          32 :         if (!TLDAP_RC_IS_SUCCESS(rc)) {
    2106           0 :                 goto fail;
    2107             :         }
    2108             : 
    2109          32 :         TALLOC_FREE(ld->last_msg);
    2110          32 :         ld->last_msg = talloc_move(ld, &result);
    2111             : 
    2112          32 :         if (pmsgs != NULL) {
    2113          24 :                 *pmsgs = talloc_move(mem_ctx, &msgs);
    2114             :         }
    2115           8 : fail:
    2116          32 :         TALLOC_FREE(frame);
    2117          32 :         return rc;
    2118             : }
    2119             : 
    2120        1912 : static bool tldap_parse_search_entry(struct tldap_message *msg)
    2121             : {
    2122        1912 :         int num_attribs = 0;
    2123             : 
    2124        1912 :         if (msg->type != TLDAP_RES_SEARCH_ENTRY) {
    2125           0 :                 return false;
    2126             :         }
    2127        1912 :         if (!asn1_start_tag(msg->data, TLDAP_RES_SEARCH_ENTRY)) {
    2128           0 :                 return false;
    2129             :         }
    2130             : 
    2131             :         /* dn */
    2132             : 
    2133        1912 :         if (!asn1_read_OctetString_talloc(msg, msg->data, &msg->dn)) return false;
    2134             : 
    2135        1912 :         if (msg->dn == NULL) {
    2136           0 :                 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        1912 :         msg->attribs = talloc_array(msg, struct tldap_attribute, 1);
    2146        1912 :         if (msg->attribs == NULL) {
    2147           0 :                 return false;
    2148             :         }
    2149             : 
    2150        1912 :         if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
    2151       31944 :         while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
    2152           0 :                 struct tldap_attribute *attrib;
    2153       30032 :                 int num_values = 0;
    2154             : 
    2155       30032 :                 attrib = &msg->attribs[num_attribs];
    2156       30032 :                 attrib->values = talloc_array(msg->attribs, DATA_BLOB, 1);
    2157       30032 :                 if (attrib->values == NULL) {
    2158           0 :                         return false;
    2159             :                 }
    2160       30032 :                 if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
    2161       30032 :                 if (!asn1_read_OctetString_talloc(msg->attribs, msg->data,
    2162           0 :                                              &attrib->name)) return false;
    2163       30032 :                 if (!asn1_start_tag(msg->data, ASN1_SET)) return false;
    2164             : 
    2165       63536 :                 while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
    2166       33504 :                         if (!asn1_read_OctetString(msg->data, msg,
    2167       33504 :                                               &attrib->values[num_values])) return false;
    2168             : 
    2169       33504 :                         attrib->values = talloc_realloc(
    2170             :                                 msg->attribs, attrib->values, DATA_BLOB,
    2171             :                                 num_values + 2);
    2172       33504 :                         if (attrib->values == NULL) {
    2173           0 :                                 return false;
    2174             :                         }
    2175       33504 :                         num_values += 1;
    2176             :                 }
    2177       30032 :                 attrib->values = talloc_realloc(msg->attribs, attrib->values,
    2178             :                                                 DATA_BLOB, num_values);
    2179       30032 :                 attrib->num_values = num_values;
    2180             : 
    2181       30032 :                 if (!asn1_end_tag(msg->data)) return false; /* ASN1_SET */
    2182       30032 :                 if (!asn1_end_tag(msg->data)) return false; /* ASN1_SEQUENCE(0) */
    2183       30032 :                 msg->attribs = talloc_realloc(
    2184             :                         msg, msg->attribs, struct tldap_attribute,
    2185             :                         num_attribs + 2);
    2186       30032 :                 if (msg->attribs == NULL) {
    2187           0 :                         return false;
    2188             :                 }
    2189       30032 :                 num_attribs += 1;
    2190             :         }
    2191        1912 :         msg->attribs = talloc_realloc(
    2192             :                 msg, msg->attribs, struct tldap_attribute, num_attribs);
    2193        1912 :         return asn1_end_tag(msg->data);
    2194             : }
    2195             : 
    2196        1912 : bool tldap_entry_dn(struct tldap_message *msg, char **dn)
    2197             : {
    2198        1912 :         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
    2199           0 :                 return false;
    2200             :         }
    2201        1912 :         *dn = msg->dn;
    2202        1912 :         return true;
    2203             : }
    2204             : 
    2205           8 : bool tldap_entry_attributes(struct tldap_message *msg,
    2206             :                             struct tldap_attribute **attributes,
    2207             :                             int *num_attributes)
    2208             : {
    2209           8 :         if ((msg->dn == NULL) && (!tldap_parse_search_entry(msg))) {
    2210           0 :                 return false;
    2211             :         }
    2212           8 :         *attributes = msg->attribs;
    2213           8 :         *num_attributes = talloc_array_length(msg->attribs);
    2214           8 :         return true;
    2215             : }
    2216             : 
    2217         424 : static bool tldap_decode_controls(struct tldap_req_state *state)
    2218             : {
    2219         424 :         struct tldap_message *msg = state->result;
    2220         424 :         struct asn1_data *data = msg->data;
    2221         424 :         struct tldap_control *sctrls = NULL;
    2222         424 :         int num_controls = 0;
    2223         424 :         bool ret = false;
    2224             : 
    2225         424 :         msg->res_sctrls = NULL;
    2226             : 
    2227         424 :         if (!asn1_peek_tag(data, ASN1_CONTEXT(0))) {
    2228          40 :                 return true;
    2229             :         }
    2230             : 
    2231         384 :         if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto out;
    2232             : 
    2233         768 :         while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
    2234           0 :                 struct tldap_control *c;
    2235         384 :                 char *oid = NULL;
    2236             : 
    2237         384 :                 sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
    2238             :                                         num_controls + 1);
    2239         384 :                 if (sctrls == NULL) {
    2240           0 :                         goto out;
    2241             :                 }
    2242         384 :                 c = &sctrls[num_controls];
    2243             : 
    2244         384 :                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto out;
    2245         384 :                 if (!asn1_read_OctetString_talloc(msg, data, &oid)) goto out;
    2246         384 :                 if (asn1_has_error(data) || (oid == NULL)) {
    2247           0 :                         goto out;
    2248             :                 }
    2249         384 :                 c->oid = oid;
    2250         384 :                 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
    2251           0 :                         if (!asn1_read_BOOLEAN(data, &c->critical)) goto out;
    2252             :                 } else {
    2253         384 :                         c->critical = false;
    2254             :                 }
    2255         384 :                 c->value = data_blob_null;
    2256         384 :                 if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
    2257         384 :                     !asn1_read_OctetString(data, msg, &c->value)) {
    2258           0 :                         goto out;
    2259             :                 }
    2260         384 :                 if (!asn1_end_tag(data)) goto out; /* ASN1_SEQUENCE(0) */
    2261             : 
    2262         384 :                 num_controls += 1;
    2263             :         }
    2264             : 
    2265         384 :         if (!asn1_end_tag(data)) goto out;      /* ASN1_CONTEXT(0) */
    2266             : 
    2267         384 :         ret = true;
    2268             : 
    2269         384 :  out:
    2270             : 
    2271         384 :         if (ret) {
    2272         384 :                 msg->res_sctrls = sctrls;
    2273             :         } else {
    2274           0 :                 TALLOC_FREE(sctrls);
    2275             :         }
    2276         384 :         return ret;
    2277             : }
    2278             : 
    2279           0 : static void tldap_simple_done(struct tevent_req *subreq, int type)
    2280             : {
    2281           0 :         struct tevent_req *req = tevent_req_callback_data(
    2282             :                 subreq, struct tevent_req);
    2283           0 :         struct tldap_req_state *state = tevent_req_data(
    2284             :                 req, struct tldap_req_state);
    2285           0 :         TLDAPRC rc;
    2286             : 
    2287           0 :         rc = tldap_msg_recv(subreq, state, &state->result);
    2288           0 :         TALLOC_FREE(subreq);
    2289           0 :         if (tevent_req_ldap_error(req, rc)) {
    2290           0 :                 return;
    2291             :         }
    2292           0 :         if (state->result->type != type) {
    2293           0 :                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
    2294           0 :                 return;
    2295             :         }
    2296           0 :         if (!asn1_start_tag(state->result->data, state->result->type) ||
    2297           0 :             !tldap_decode_response(state) ||
    2298           0 :             !asn1_end_tag(state->result->data) ||
    2299           0 :             !tldap_decode_controls(state)) {
    2300           0 :                 tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
    2301           0 :                 return;
    2302             :         }
    2303           0 :         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr)) {
    2304           0 :                 tevent_req_ldap_error(req, state->result->lderr);
    2305           0 :                 return;
    2306             :         }
    2307           0 :         tevent_req_done(req);
    2308             : }
    2309             : 
    2310           0 : static TLDAPRC tldap_simple_recv(struct tevent_req *req)
    2311             : {
    2312           0 :         TLDAPRC rc;
    2313           0 :         if (tevent_req_is_ldap_error(req, &rc)) {
    2314           0 :                 return rc;
    2315             :         }
    2316           0 :         return TLDAP_SUCCESS;
    2317             : }
    2318             : 
    2319             : static void tldap_add_done(struct tevent_req *subreq);
    2320             : 
    2321           0 : 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           0 :         struct tevent_req *req, *subreq;
    2333           0 :         struct tldap_req_state *state;
    2334           0 :         int i, j;
    2335             : 
    2336           0 :         req = tldap_req_create(mem_ctx, ld, &state);
    2337           0 :         if (req == NULL) {
    2338           0 :                 return NULL;
    2339             :         }
    2340             : 
    2341           0 :         if (!asn1_push_tag(state->out, TLDAP_REQ_ADD)) goto err;
    2342           0 :         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
    2343           0 :         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
    2344             : 
    2345           0 :         for (i=0; i<num_attributes; i++) {
    2346           0 :                 struct tldap_mod *attrib = &attributes[i];
    2347           0 :                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
    2348           0 :                 if (!asn1_write_OctetString(state->out, attrib->attribute,
    2349           0 :                                        strlen(attrib->attribute))) goto err;
    2350           0 :                 if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
    2351           0 :                 for (j=0; j<attrib->num_values; j++) {
    2352           0 :                         if (!asn1_write_OctetString(state->out,
    2353           0 :                                                attrib->values[j].data,
    2354           0 :                                                attrib->values[j].length)) goto err;
    2355             :                 }
    2356           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2357           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2358             :         }
    2359             : 
    2360           0 :         if (!asn1_pop_tag(state->out)) goto err;
    2361           0 :         if (!asn1_pop_tag(state->out)) goto err;
    2362             : 
    2363           0 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    2364             :                                 sctrls, num_sctrls);
    2365           0 :         if (tevent_req_nomem(subreq, req)) {
    2366           0 :                 return tevent_req_post(req, ev);
    2367             :         }
    2368           0 :         tevent_req_set_callback(subreq, tldap_add_done, req);
    2369           0 :         return req;
    2370             : 
    2371           0 :   err:
    2372             : 
    2373           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    2374           0 :         return tevent_req_post(req, ev);
    2375             : }
    2376             : 
    2377           0 : static void tldap_add_done(struct tevent_req *subreq)
    2378             : {
    2379           0 :         tldap_simple_done(subreq, TLDAP_RES_ADD);
    2380           0 : }
    2381             : 
    2382           0 : TLDAPRC tldap_add_recv(struct tevent_req *req)
    2383             : {
    2384           0 :         return tldap_simple_recv(req);
    2385             : }
    2386             : 
    2387           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2393           0 :         struct tevent_context *ev;
    2394           0 :         struct tevent_req *req;
    2395           0 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    2396             : 
    2397           0 :         ev = samba_tevent_context_init(frame);
    2398           0 :         if (ev == NULL) {
    2399           0 :                 goto fail;
    2400             :         }
    2401           0 :         req = tldap_add_send(frame, ev, ld, dn, attributes, num_attributes,
    2402             :                              sctrls, num_sctrls, cctrls, num_cctrls);
    2403           0 :         if (req == NULL) {
    2404           0 :                 goto fail;
    2405             :         }
    2406           0 :         if (!tevent_req_poll(req, ev)) {
    2407           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    2408           0 :                 goto fail;
    2409             :         }
    2410           0 :         rc = tldap_add_recv(req);
    2411           0 :         tldap_save_msg(ld, req);
    2412           0 :  fail:
    2413           0 :         TALLOC_FREE(frame);
    2414           0 :         return rc;
    2415             : }
    2416             : 
    2417             : static void tldap_modify_done(struct tevent_req *subreq);
    2418             : 
    2419           0 : 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           0 :         struct tevent_req *req, *subreq;
    2430           0 :         struct tldap_req_state *state;
    2431           0 :         int i, j;
    2432             : 
    2433           0 :         req = tldap_req_create(mem_ctx, ld, &state);
    2434           0 :         if (req == NULL) {
    2435           0 :                 return NULL;
    2436             :         }
    2437             : 
    2438           0 :         if (!asn1_push_tag(state->out, TLDAP_REQ_MODIFY)) goto err;
    2439           0 :         if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
    2440           0 :         if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
    2441             : 
    2442           0 :         for (i=0; i<num_mods; i++) {
    2443           0 :                 struct tldap_mod *mod = &mods[i];
    2444           0 :                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
    2445           0 :                 if (!asn1_write_enumerated(state->out, mod->mod_op)) goto err;
    2446           0 :                 if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
    2447           0 :                 if (!asn1_write_OctetString(state->out, mod->attribute,
    2448           0 :                                        strlen(mod->attribute))) goto err;
    2449           0 :                 if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
    2450           0 :                 for (j=0; j<mod->num_values; j++) {
    2451           0 :                         if (!asn1_write_OctetString(state->out,
    2452           0 :                                                mod->values[j].data,
    2453           0 :                                                mod->values[j].length)) goto err;
    2454             :                 }
    2455           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2456           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2457           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2458             :         }
    2459             : 
    2460           0 :         if (!asn1_pop_tag(state->out)) goto err;
    2461           0 :         if (!asn1_pop_tag(state->out)) goto err;
    2462             : 
    2463           0 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    2464             :                                 sctrls, num_sctrls);
    2465           0 :         if (tevent_req_nomem(subreq, req)) {
    2466           0 :                 return tevent_req_post(req, ev);
    2467             :         }
    2468           0 :         tevent_req_set_callback(subreq, tldap_modify_done, req);
    2469           0 :         return req;
    2470             : 
    2471           0 :   err:
    2472             : 
    2473           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    2474           0 :         return tevent_req_post(req, ev);
    2475             : }
    2476             : 
    2477           0 : static void tldap_modify_done(struct tevent_req *subreq)
    2478             : {
    2479           0 :         tldap_simple_done(subreq, TLDAP_RES_MODIFY);
    2480           0 : }
    2481             : 
    2482           0 : TLDAPRC tldap_modify_recv(struct tevent_req *req)
    2483             : {
    2484           0 :         return tldap_simple_recv(req);
    2485             : }
    2486             : 
    2487           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2493           0 :         struct tevent_context *ev;
    2494           0 :         struct tevent_req *req;
    2495           0 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    2496             : 
    2497           0 :         ev = samba_tevent_context_init(frame);
    2498           0 :         if (ev == NULL) {
    2499           0 :                 goto fail;
    2500             :         }
    2501           0 :         req = tldap_modify_send(frame, ev, ld, dn, mods, num_mods,
    2502             :                                 sctrls, num_sctrls, cctrls, num_cctrls);
    2503           0 :         if (req == NULL) {
    2504           0 :                 goto fail;
    2505             :         }
    2506           0 :         if (!tevent_req_poll(req, ev)) {
    2507           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    2508           0 :                 goto fail;
    2509             :         }
    2510           0 :         rc = tldap_modify_recv(req);
    2511           0 :         tldap_save_msg(ld, req);
    2512           0 :  fail:
    2513           0 :         TALLOC_FREE(frame);
    2514           0 :         return rc;
    2515             : }
    2516             : 
    2517             : static void tldap_delete_done(struct tevent_req *subreq);
    2518             : 
    2519           0 : 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           0 :         struct tevent_req *req, *subreq;
    2529           0 :         struct tldap_req_state *state;
    2530             : 
    2531           0 :         req = tldap_req_create(mem_ctx, ld, &state);
    2532           0 :         if (req == NULL) {
    2533           0 :                 return NULL;
    2534             :         }
    2535             : 
    2536           0 :         if (!asn1_push_tag(state->out, TLDAP_REQ_DELETE)) goto err;
    2537           0 :         if (!asn1_write(state->out, dn, strlen(dn))) goto err;
    2538           0 :         if (!asn1_pop_tag(state->out)) goto err;
    2539             : 
    2540           0 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    2541             :                                 sctrls, num_sctrls);
    2542           0 :         if (tevent_req_nomem(subreq, req)) {
    2543           0 :                 return tevent_req_post(req, ev);
    2544             :         }
    2545           0 :         tevent_req_set_callback(subreq, tldap_delete_done, req);
    2546           0 :         return req;
    2547             : 
    2548           0 :   err:
    2549             : 
    2550           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    2551           0 :         return tevent_req_post(req, ev);
    2552             : }
    2553             : 
    2554           0 : static void tldap_delete_done(struct tevent_req *subreq)
    2555             : {
    2556           0 :         tldap_simple_done(subreq, TLDAP_RES_DELETE);
    2557           0 : }
    2558             : 
    2559           0 : TLDAPRC tldap_delete_recv(struct tevent_req *req)
    2560             : {
    2561           0 :         return tldap_simple_recv(req);
    2562             : }
    2563             : 
    2564           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2569           0 :         struct tevent_context *ev;
    2570           0 :         struct tevent_req *req;
    2571           0 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    2572             : 
    2573           0 :         ev = samba_tevent_context_init(frame);
    2574           0 :         if (ev == NULL) {
    2575           0 :                 goto fail;
    2576             :         }
    2577           0 :         req = tldap_delete_send(frame, ev, ld, dn, sctrls, num_sctrls,
    2578             :                                 cctrls, num_cctrls);
    2579           0 :         if (req == NULL) {
    2580           0 :                 goto fail;
    2581             :         }
    2582           0 :         if (!tevent_req_poll(req, ev)) {
    2583           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    2584           0 :                 goto fail;
    2585             :         }
    2586           0 :         rc = tldap_delete_recv(req);
    2587           0 :         tldap_save_msg(ld, req);
    2588           0 :  fail:
    2589           0 :         TALLOC_FREE(frame);
    2590           0 :         return rc;
    2591             : }
    2592             : 
    2593             : static void tldap_extended_done(struct tevent_req *subreq);
    2594             : 
    2595           2 : 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           0 :         struct tevent_req *req, *subreq;
    2606           0 :         struct tldap_req_state *state;
    2607             : 
    2608           2 :         req = tldap_req_create(mem_ctx, ld, &state);
    2609           2 :         if (req == NULL) {
    2610           0 :                 return NULL;
    2611             :         }
    2612             : 
    2613           2 :         if (!asn1_push_tag(state->out, TLDAP_REQ_EXTENDED)) goto err;
    2614             : 
    2615           2 :         if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0))) goto err;
    2616           2 :         if (!asn1_write(state->out, in_oid, strlen(in_oid))) goto err;
    2617           2 :         if (!asn1_pop_tag(state->out)) goto err;
    2618             : 
    2619           2 :         if (in_blob != NULL) {
    2620           0 :                 if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(1))) goto err;
    2621           0 :                 if (!asn1_write_OctetString(state->out, in_blob->data, in_blob->length)) goto err;
    2622           0 :                 if (!asn1_pop_tag(state->out)) goto err;
    2623             :         }
    2624             : 
    2625           2 :         if (!asn1_pop_tag(state->out)) goto err;
    2626             : 
    2627           2 :         subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
    2628             :                                 sctrls, num_sctrls);
    2629           2 :         if (tevent_req_nomem(subreq, req)) {
    2630           0 :                 return tevent_req_post(req, ev);
    2631             :         }
    2632           2 :         tevent_req_set_callback(subreq, tldap_extended_done, req);
    2633           2 :         return req;
    2634             : 
    2635           0 :   err:
    2636             : 
    2637           0 :         tevent_req_ldap_error(req, TLDAP_ENCODING_ERROR);
    2638           0 :         return tevent_req_post(req, ev);
    2639             : }
    2640             : 
    2641           2 : static void tldap_extended_done(struct tevent_req *subreq)
    2642             : {
    2643           2 :         struct tevent_req *req = tevent_req_callback_data(
    2644             :                 subreq, struct tevent_req);
    2645           2 :         struct tldap_req_state *state = tevent_req_data(
    2646             :                 req, struct tldap_req_state);
    2647           0 :         TLDAPRC rc;
    2648           0 :         bool ok;
    2649             : 
    2650           2 :         rc = tldap_msg_recv(subreq, state, &state->result);
    2651           2 :         TALLOC_FREE(subreq);
    2652           2 :         if (tevent_req_ldap_error(req, rc)) {
    2653           0 :                 return;
    2654             :         }
    2655           2 :         if (state->result->type != TLDAP_RES_EXTENDED) {
    2656           0 :                 tevent_req_ldap_error(req, TLDAP_PROTOCOL_ERROR);
    2657           0 :                 return;
    2658             :         }
    2659             : 
    2660           2 :         ok = asn1_start_tag(state->result->data, TLDAP_RES_EXTENDED);
    2661           2 :         ok &= tldap_decode_response(state);
    2662             : 
    2663           2 :         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(10))) {
    2664           2 :                 ok &= asn1_start_tag(state->result->data,
    2665             :                                      ASN1_CONTEXT_SIMPLE(10));
    2666           2 :                 if (!ok) {
    2667           0 :                         goto decode_error;
    2668             :                 }
    2669             : 
    2670           4 :                 ok &= asn1_read_LDAPString(state->result->data,
    2671           2 :                                            state->result,
    2672           2 :                                            &state->result->res_extended.oid);
    2673             : 
    2674           2 :                 ok &= asn1_end_tag(state->result->data);
    2675             :         }
    2676             : 
    2677           2 :         if (asn1_peek_tag(state->result->data, ASN1_CONTEXT_SIMPLE(11))) {
    2678           0 :                 int len;
    2679             : 
    2680           0 :                 ok &= asn1_start_tag(state->result->data,
    2681             :                                      ASN1_CONTEXT_SIMPLE(11));
    2682           0 :                 if (!ok) {
    2683           0 :                         goto decode_error;
    2684             :                 }
    2685             : 
    2686           0 :                 len = asn1_tag_remaining(state->result->data);
    2687           0 :                 if (len == -1) {
    2688           0 :                         goto decode_error;
    2689             :                 }
    2690             : 
    2691           0 :                 state->result->res_extended.blob =
    2692           0 :                         data_blob_talloc(state->result, NULL, len);
    2693           0 :                 if (state->result->res_extended.blob.data == NULL) {
    2694           0 :                         goto decode_error;
    2695             :                 }
    2696             : 
    2697           0 :                 ok = asn1_read(state->result->data,
    2698           0 :                                state->result->res_extended.blob.data,
    2699           0 :                                state->result->res_extended.blob.length);
    2700             : 
    2701           0 :                 ok &= asn1_end_tag(state->result->data);
    2702             :         }
    2703             : 
    2704           2 :         ok &= asn1_end_tag(state->result->data);
    2705             : 
    2706           2 :         if (!ok) {
    2707           0 :                 goto decode_error;
    2708             :         }
    2709             : 
    2710           2 :         if (!TLDAP_RC_IS_SUCCESS(state->result->lderr)) {
    2711           0 :                 tevent_req_ldap_error(req, state->result->lderr);
    2712           0 :                 return;
    2713             :         }
    2714           2 :         tevent_req_done(req);
    2715           2 :         return;
    2716             : 
    2717           0 : decode_error:
    2718           0 :         tevent_req_ldap_error(req, TLDAP_DECODING_ERROR);
    2719           0 :         return;
    2720             : }
    2721             : 
    2722           2 : TLDAPRC tldap_extended_recv(struct tevent_req *req,
    2723             :                             TALLOC_CTX *mem_ctx,
    2724             :                             char **out_oid,
    2725             :                             DATA_BLOB *out_blob)
    2726             : {
    2727           2 :         struct tldap_req_state *state = tevent_req_data(
    2728             :                 req, struct tldap_req_state);
    2729           0 :         TLDAPRC rc;
    2730             : 
    2731           2 :         if (tevent_req_is_ldap_error(req, &rc)) {
    2732           0 :                 return rc;
    2733             :         }
    2734             : 
    2735           2 :         if (out_oid != NULL) {
    2736           0 :                 *out_oid = talloc_move(mem_ctx,
    2737             :                                 &state->result->res_extended.oid);
    2738             :         }
    2739             : 
    2740           2 :         if (out_blob != NULL) {
    2741           0 :                 out_blob->data = talloc_move(mem_ctx,
    2742             :                                 &state->result->res_extended.blob.data);
    2743           0 :                 out_blob->length =
    2744           0 :                                 state->result->res_extended.blob.length;
    2745             :         }
    2746             : 
    2747           2 :         return state->result->lderr;
    2748             : }
    2749             : 
    2750           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2762           0 :         struct tevent_context *ev;
    2763           0 :         struct tevent_req *req;
    2764           0 :         TLDAPRC rc = TLDAP_NO_MEMORY;
    2765             : 
    2766           0 :         ev = samba_tevent_context_init(frame);
    2767           0 :         if (ev == NULL) {
    2768           0 :                 goto fail;
    2769             :         }
    2770           0 :         req = tldap_extended_send(frame, ev, ld,
    2771             :                                   in_oid, in_blob,
    2772             :                                   sctrls, num_sctrls,
    2773             :                                   cctrls, num_cctrls);
    2774           0 :         if (req == NULL) {
    2775           0 :                 goto fail;
    2776             :         }
    2777           0 :         if (!tevent_req_poll(req, ev)) {
    2778           0 :                 rc = TLDAP_OPERATIONS_ERROR;
    2779           0 :                 goto fail;
    2780             :         }
    2781           0 :         rc = tldap_extended_recv(req, mem_ctx, out_oid, out_blob);
    2782           0 :         tldap_save_msg(ld, req);
    2783           0 :  fail:
    2784           0 :         TALLOC_FREE(frame);
    2785           0 :         return rc;
    2786             : }
    2787             : 
    2788           0 : int tldap_msg_id(const struct tldap_message *msg)
    2789             : {
    2790           0 :         return msg->id;
    2791             : }
    2792             : 
    2793        6184 : int tldap_msg_type(const struct tldap_message *msg)
    2794             : {
    2795        6184 :         return msg->type;
    2796             : }
    2797             : 
    2798           0 : const char *tldap_msg_matcheddn(struct tldap_message *msg)
    2799             : {
    2800           0 :         if (msg == NULL) {
    2801           0 :                 return NULL;
    2802             :         }
    2803           0 :         return msg->res_matcheddn;
    2804             : }
    2805             : 
    2806           0 : const char *tldap_msg_diagnosticmessage(struct tldap_message *msg)
    2807             : {
    2808           0 :         if (msg == NULL) {
    2809           0 :                 return NULL;
    2810             :         }
    2811           0 :         return msg->res_diagnosticmessage;
    2812             : }
    2813             : 
    2814           0 : const char *tldap_msg_referral(struct tldap_message *msg)
    2815             : {
    2816           0 :         if (msg == NULL) {
    2817           0 :                 return NULL;
    2818             :         }
    2819           0 :         return msg->res_referral;
    2820             : }
    2821             : 
    2822         384 : void tldap_msg_sctrls(struct tldap_message *msg, int *num_sctrls,
    2823             :                       struct tldap_control **sctrls)
    2824             : {
    2825         384 :         if (msg == NULL) {
    2826           0 :                 *sctrls = NULL;
    2827           0 :                 *num_sctrls = 0;
    2828           0 :                 return;
    2829             :         }
    2830         384 :         *sctrls = msg->res_sctrls;
    2831         384 :         *num_sctrls = talloc_array_length(msg->res_sctrls);
    2832             : }
    2833             : 
    2834           0 : struct tldap_message *tldap_ctx_lastmsg(struct tldap_context *ld)
    2835             : {
    2836           0 :         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           0 : const char *tldap_rc2string(TLDAPRC rc)
    2960             : {
    2961           0 :         size_t i;
    2962             : 
    2963           0 :         for (i=0; i<ARRAY_SIZE(tldaprc_errmap); i++) {
    2964           0 :                 if (TLDAP_RC_EQUAL(rc, tldaprc_errmap[i].rc)) {
    2965           0 :                         return tldaprc_errmap[i].string;
    2966             :                 }
    2967             :         }
    2968             : 
    2969           0 :         return "Unknown LDAP Error";
    2970             : }

Generated by: LCOV version 1.14