Coverage Report

Created: 2026-02-14 07:07

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