Coverage Report

Created: 2025-07-23 07:04

/src/samba/libcli/ldap/ldap_message.c
Line
Count
Source (jump to first uncovered line)
1
/* 
2
   Unix SMB/CIFS implementation.
3
   LDAP protocol helper functions for SAMBA
4
   
5
   Copyright (C) Andrew Tridgell  2004
6
   Copyright (C) Volker Lendecke 2004
7
   Copyright (C) Stefan Metzmacher 2004
8
   Copyright (C) Simo Sorce 2004
9
    
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
   
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
   
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
   
23
*/
24
25
#include "includes.h"
26
#include "../lib/util/asn1.h"
27
#include "../libcli/ldap/ldap_message.h"
28
29
_PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
30
0
{
31
0
  return talloc_zero(mem_ctx, struct ldap_message);
32
0
}
33
34
35
static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36
        struct ldb_message_element *attrib)
37
30.4k
{
38
30.4k
  attrib->values = talloc_realloc(mem_ctx,
39
30.4k
          attrib->values,
40
30.4k
          DATA_BLOB,
41
30.4k
          attrib->num_values+1);
42
30.4k
  if (attrib->values == NULL)
43
0
    return false;
44
45
30.4k
  attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
46
30.4k
                     value->data);
47
30.4k
  attrib->values[attrib->num_values].length = value->length;
48
30.4k
  attrib->num_values += 1;
49
30.4k
  return true;
50
30.4k
}
51
52
static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
53
               const struct ldb_message_element *attrib,
54
               struct ldb_message_element **attribs,
55
               int *num_attribs)
56
102
{
57
102
  *attribs = talloc_realloc(mem_ctx,
58
102
          *attribs,
59
102
          struct ldb_message_element,
60
102
          *num_attribs+1);
61
62
102
  if (*attribs == NULL)
63
0
    return false;
64
65
102
  (*attribs)[*num_attribs] = *attrib;
66
102
  talloc_steal(*attribs, attrib->values);
67
102
  talloc_steal(*attribs, attrib->name);
68
102
  *num_attribs += 1;
69
102
  return true;
70
102
}
71
72
static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
73
            struct ldap_mod *mod,
74
            struct ldap_mod **mods,
75
            int *num_mods)
76
47
{
77
47
  *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
78
79
47
  if (*mods == NULL)
80
0
    return false;
81
82
47
  (*mods)[*num_mods] = *mod;
83
47
  *num_mods += 1;
84
47
  return true;
85
47
}
86
87
static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
88
              const struct ldap_control_handler *handlers,
89
              struct ldb_control *ctrl)
90
1.73k
{
91
1.73k
  int i;
92
93
1.73k
  if (!handlers) {
94
0
    return true;
95
0
  }
96
97
54.2k
  for (i = 0; handlers[i].oid != NULL; i++) {
98
53.6k
    if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
99
1.17k
      if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
100
969
        return false;
101
969
      }
102
208
      break;
103
1.17k
    }
104
53.6k
  }
105
764
  if (handlers[i].oid == NULL) {
106
556
    return false;
107
556
  }
108
109
208
  return true;
110
764
}
111
112
static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113
          struct ldb_control *ctrl, DATA_BLOB *value)
114
1.80k
{
115
1.80k
  DATA_BLOB oid;
116
117
1.80k
  if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
118
36
    return false;
119
36
  }
120
121
1.76k
  if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
122
14
    return false;
123
14
  }
124
1.75k
  ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
125
1.75k
  if (!ctrl->oid) {
126
0
    return false;
127
0
  }
128
129
1.75k
  if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
130
135
    bool critical;
131
135
    if (!asn1_read_BOOLEAN(data, &critical)) {
132
10
      return false;
133
10
    }
134
125
    ctrl->critical = critical;
135
1.61k
  } else {
136
1.61k
    ctrl->critical = false;
137
1.61k
  }
138
139
1.74k
  ctrl->data = NULL;
140
141
1.74k
  if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142
686
    *value = data_blob(NULL, 0);
143
686
    goto end_tag;
144
686
  }
145
146
1.05k
  if (!asn1_read_OctetString(data, mem_ctx, value)) {
147
3
    return false;
148
3
  }
149
150
1.73k
end_tag:
151
1.73k
  if (!asn1_end_tag(data)) {
152
6
    return false;
153
6
  }
154
155
1.73k
  return true;
156
1.73k
}
157
158
static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
159
        const struct ldap_control_handler *handlers,
160
        struct ldb_control *ctrl)
161
0
{
162
0
  DATA_BLOB value;
163
0
  int i;
164
165
0
  if (!handlers) {
166
0
    return false;
167
0
  }
168
169
0
  for (i = 0; handlers[i].oid != NULL; i++) {
170
0
    if (!ctrl->oid) {
171
      /* not encoding this control, the OID has been
172
       * set to NULL indicating it isn't really
173
       * here */
174
0
      return true;
175
0
    }
176
0
    if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
177
0
      if (!handlers[i].encode) {
178
0
        if (ctrl->critical) {
179
0
          return false;
180
0
        } else {
181
          /* not encoding this control */
182
0
          return true;
183
0
        }
184
0
      }
185
0
      if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
186
0
        return false;
187
0
      }
188
0
      break;
189
0
    }
190
0
  }
191
0
  if (handlers[i].oid == NULL) {
192
0
    return false;
193
0
  }
194
195
0
  if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
196
0
    return false;
197
0
  }
198
199
0
  if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
200
0
    return false;
201
0
  }
202
203
0
  if (ctrl->critical) {
204
0
    if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
205
0
      return false;
206
0
    }
207
0
  }
208
209
0
  if (!ctrl->data) {
210
0
    goto pop_tag;
211
0
  }
212
213
0
  if (!asn1_write_OctetString(data, value.data, value.length)) {
214
0
    return false;
215
0
  }
216
217
0
pop_tag:
218
0
  if (!asn1_pop_tag(data)) {
219
0
    return false;
220
0
  }
221
222
0
  return true;
223
0
}
224
225
static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
226
0
{
227
0
  int i;
228
229
0
  switch (tree->operation) {
230
0
  case LDB_OP_AND:
231
0
  case LDB_OP_OR:
232
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1))) return false;
233
0
    for (i=0; i<tree->u.list.num_elements; i++) {
234
0
      if (!ldap_push_filter(data, tree->u.list.elements[i])) {
235
0
        return false;
236
0
      }
237
0
    }
238
0
    if (!asn1_pop_tag(data)) return false;
239
0
    break;
240
241
0
  case LDB_OP_NOT:
242
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(2))) return false;
243
0
    if (!ldap_push_filter(data, tree->u.isnot.child)) {
244
0
      return false;
245
0
    }
246
0
    if (!asn1_pop_tag(data)) return false;
247
0
    break;
248
249
0
  case LDB_OP_EQUALITY:
250
    /* equality test */
251
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
252
0
    if (!asn1_write_OctetString(data, tree->u.equality.attr,
253
0
              strlen(tree->u.equality.attr))) return false;
254
0
    if (!asn1_write_OctetString(data, tree->u.equality.value.data,
255
0
              tree->u.equality.value.length)) return false;
256
0
    if (!asn1_pop_tag(data)) return false;
257
0
    break;
258
259
0
  case LDB_OP_SUBSTRING:
260
    /*
261
      SubstringFilter ::= SEQUENCE {
262
        type            AttributeDescription,
263
        -- at least one must be present
264
        substrings      SEQUENCE OF CHOICE {
265
          initial [0] LDAPString,
266
          any     [1] LDAPString,
267
          final   [2] LDAPString } }
268
    */
269
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(4))) return false;
270
0
    if (!asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr))) return false;
271
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
272
273
0
    if (tree->u.substring.chunks && tree->u.substring.chunks[0]) {
274
0
      i = 0;
275
0
      if (!tree->u.substring.start_with_wildcard) {
276
0
        if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) return false;
277
0
        if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
278
0
        if (!asn1_pop_tag(data)) return false;
279
0
        i++;
280
0
      }
281
0
      while (tree->u.substring.chunks[i]) {
282
0
        int ctx;
283
284
0
        if (( ! tree->u.substring.chunks[i + 1]) &&
285
0
            (tree->u.substring.end_with_wildcard == 0)) {
286
0
          ctx = 2;
287
0
        } else {
288
0
          ctx = 1;
289
0
        }
290
0
        if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx))) return false;
291
0
        if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
292
0
        if (!asn1_pop_tag(data)) return false;
293
0
        i++;
294
0
      }
295
0
    }
296
0
    if (!asn1_pop_tag(data)) return false;
297
0
    if (!asn1_pop_tag(data)) return false;
298
0
    break;
299
300
0
  case LDB_OP_GREATER:
301
    /* greaterOrEqual test */
302
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(5))) return false;
303
0
    if (!asn1_write_OctetString(data, tree->u.comparison.attr,
304
0
              strlen(tree->u.comparison.attr))) return false;
305
0
    if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
306
0
              tree->u.comparison.value.length)) return false;
307
0
    if (!asn1_pop_tag(data)) return false;
308
0
    break;
309
310
0
  case LDB_OP_LESS:
311
    /* lessOrEqual test */
312
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(6))) return false;
313
0
    if (!asn1_write_OctetString(data, tree->u.comparison.attr,
314
0
              strlen(tree->u.comparison.attr))) return false;
315
0
    if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
316
0
              tree->u.comparison.value.length)) return false;
317
0
    if (!asn1_pop_tag(data)) return false;
318
0
    break;
319
320
0
  case LDB_OP_PRESENT:
321
    /* present test */
322
0
    if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false;
323
0
    if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false;
324
0
    if (!asn1_pop_tag(data)) return false;
325
0
    return !asn1_has_error(data);
326
327
0
  case LDB_OP_APPROX:
328
    /* approx test */
329
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(8))) return false;
330
0
    if (!asn1_write_OctetString(data, tree->u.comparison.attr,
331
0
              strlen(tree->u.comparison.attr))) return false;
332
0
    if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
333
0
              tree->u.comparison.value.length)) return false;
334
0
    if (!asn1_pop_tag(data)) return false;
335
0
    break;
336
337
0
  case LDB_OP_EXTENDED:
338
    /*
339
      MatchingRuleAssertion ::= SEQUENCE {
340
      matchingRule    [1] MatchingRuleID OPTIONAL,
341
      type            [2] AttributeDescription OPTIONAL,
342
      matchValue      [3] AssertionValue,
343
      dnAttributes    [4] BOOLEAN DEFAULT FALSE
344
      }
345
    */
346
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(9))) return false;
347
0
    if (tree->u.extended.rule_id) {
348
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
349
0
      if (!asn1_write_LDAPString(data, tree->u.extended.rule_id)) return false;
350
0
      if (!asn1_pop_tag(data)) return false;
351
0
    }
352
0
    if (tree->u.extended.attr) {
353
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
354
0
      if (!asn1_write_LDAPString(data, tree->u.extended.attr)) return false;
355
0
      if (!asn1_pop_tag(data)) return false;
356
0
    }
357
0
    if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
358
0
    if (!asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value)) return false;
359
0
    if (!asn1_pop_tag(data)) return false;
360
0
    if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
361
0
    if (!asn1_write_uint8(data, tree->u.extended.dnAttributes)) return false;
362
0
    if (!asn1_pop_tag(data)) return false;
363
0
    if (!asn1_pop_tag(data)) return false;
364
0
    break;
365
366
0
  default:
367
0
    return false;
368
0
  }
369
0
  return !asn1_has_error(data);
370
0
}
371
372
static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
373
0
{
374
0
  if (!asn1_write_enumerated(data, result->resultcode)) return false;
375
0
  if (!asn1_write_OctetString(data, result->dn,
376
0
             (result->dn) ? strlen(result->dn) : 0)) return false;
377
0
  if (!asn1_write_OctetString(data, result->errormessage,
378
0
             (result->errormessage) ?
379
0
             strlen(result->errormessage) : 0)) return false;
380
0
  if (result->referral) {
381
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
382
0
    if (!asn1_write_OctetString(data, result->referral,
383
0
               strlen(result->referral))) return false;
384
0
    if (!asn1_pop_tag(data)) return false;
385
0
  }
386
0
  return true;
387
0
}
388
389
_PUBLIC_ bool ldap_encode(struct ldap_message *msg,
390
        const struct ldap_control_handler *control_handlers,
391
        DATA_BLOB *result, TALLOC_CTX *mem_ctx)
392
0
{
393
0
  struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
394
0
  int i, j;
395
396
0
  if (!data) return false;
397
398
0
  if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
399
0
  if (!asn1_write_Integer(data, msg->messageid)) goto err;
400
401
0
  switch (msg->type) {
402
0
  case LDAP_TAG_BindRequest: {
403
0
    struct ldap_BindRequest *r = &msg->r.BindRequest;
404
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
405
0
    if (!asn1_write_Integer(data, r->version)) goto err;
406
0
    if (!asn1_write_OctetString(data, r->dn,
407
0
               (r->dn != NULL) ? strlen(r->dn) : 0)) goto err;
408
409
0
    switch (r->mechanism) {
410
0
    case LDAP_AUTH_MECH_SIMPLE:
411
      /* context, primitive */
412
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
413
0
      if (!asn1_write(data, r->creds.password,
414
0
           strlen(r->creds.password))) goto err;
415
0
      if (!asn1_pop_tag(data)) goto err;
416
0
      break;
417
0
    case LDAP_AUTH_MECH_SASL:
418
      /* context, constructed */
419
0
      if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
420
0
      if (!asn1_write_OctetString(data, r->creds.SASL.mechanism,
421
0
                 strlen(r->creds.SASL.mechanism))) goto err;
422
0
      if (r->creds.SASL.secblob) {
423
0
        if (!asn1_write_OctetString(data, r->creds.SASL.secblob->data,
424
0
                   r->creds.SASL.secblob->length)) goto err;
425
0
      }
426
0
      if (!asn1_pop_tag(data)) goto err;
427
0
      break;
428
0
    default:
429
0
      goto err;
430
0
    }
431
432
0
    if (!asn1_pop_tag(data)) goto err;
433
0
    break;
434
0
  }
435
0
  case LDAP_TAG_BindResponse: {
436
0
    struct ldap_BindResponse *r = &msg->r.BindResponse;
437
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
438
0
    if (!ldap_encode_response(data, &r->response)) goto err;
439
0
    if (r->SASL.secblob) {
440
0
      if (!asn1_write_ContextSimple(data, 7, r->SASL.secblob)) goto err;
441
0
    }
442
0
    if (!asn1_pop_tag(data)) goto err;
443
0
    break;
444
0
  }
445
0
  case LDAP_TAG_UnbindRequest: {
446
/*    struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
447
0
    if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
448
0
    if (!asn1_pop_tag(data)) goto err;
449
0
    break;
450
0
  }
451
0
  case LDAP_TAG_SearchRequest: {
452
0
    struct ldap_SearchRequest *r = &msg->r.SearchRequest;
453
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
454
0
    if (!asn1_write_OctetString(data, r->basedn, strlen(r->basedn))) goto err;
455
0
    if (!asn1_write_enumerated(data, r->scope)) goto err;
456
0
    if (!asn1_write_enumerated(data, r->deref)) goto err;
457
0
    if (!asn1_write_Integer(data, r->sizelimit)) goto err;
458
0
    if (!asn1_write_Integer(data, r->timelimit)) goto err;
459
0
    if (!asn1_write_BOOLEAN(data, r->attributesonly)) goto err;
460
461
0
    if (!ldap_push_filter(data, r->tree)) {
462
0
      goto err;
463
0
    }
464
465
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
466
0
    for (i=0; i<r->num_attributes; i++) {
467
0
      if (!asn1_write_OctetString(data, r->attributes[i],
468
0
                 strlen(r->attributes[i]))) goto err;
469
0
    }
470
0
    if (!asn1_pop_tag(data)) goto err;
471
0
    if (!asn1_pop_tag(data)) goto err;
472
0
    break;
473
0
  }
474
0
  case LDAP_TAG_SearchResultEntry: {
475
0
    struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
476
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
477
0
    if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
478
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
479
0
    for (i=0; i<r->num_attributes; i++) {
480
0
      struct ldb_message_element *attr = &r->attributes[i];
481
0
      if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
482
0
      if (!asn1_write_OctetString(data, attr->name,
483
0
                 strlen(attr->name))) goto err;
484
0
      if (!asn1_push_tag(data, ASN1_SEQUENCE(1))) goto err;
485
0
      for (j=0; j<attr->num_values; j++) {
486
0
        if (!asn1_write_OctetString(data,
487
0
                   attr->values[j].data,
488
0
                   attr->values[j].length)) goto err;
489
0
      }
490
0
      if (!asn1_pop_tag(data)) goto err;
491
0
      if (!asn1_pop_tag(data)) goto err;
492
0
    }
493
0
    if (!asn1_pop_tag(data)) goto err;
494
0
    if (!asn1_pop_tag(data)) goto err;
495
0
    break;
496
0
  }
497
0
  case LDAP_TAG_SearchResultDone: {
498
0
    struct ldap_Result *r = &msg->r.SearchResultDone;
499
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
500
0
    if (!ldap_encode_response(data, r)) goto err;
501
0
    if (!asn1_pop_tag(data)) goto err;
502
0
    break;
503
0
  }
504
0
  case LDAP_TAG_ModifyRequest: {
505
0
    struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
506
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
507
0
    if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
508
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
509
510
0
    for (i=0; i<r->num_mods; i++) {
511
0
      struct ldb_message_element *attrib = &r->mods[i].attrib;
512
0
      if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
513
0
      if (!asn1_write_enumerated(data, r->mods[i].type)) goto err;
514
0
      if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
515
0
      if (!asn1_write_OctetString(data, attrib->name,
516
0
                 strlen(attrib->name))) goto err;
517
0
      if (!asn1_push_tag(data, ASN1_SET)) goto err;
518
0
      for (j=0; j<attrib->num_values; j++) {
519
0
        if (!asn1_write_OctetString(data,
520
0
                   attrib->values[j].data,
521
0
                   attrib->values[j].length)) goto err;
522
  
523
0
      }
524
0
      if (!asn1_pop_tag(data)) goto err;
525
0
      if (!asn1_pop_tag(data)) goto err;
526
0
      if (!asn1_pop_tag(data)) goto err;
527
0
    }
528
    
529
0
    if (!asn1_pop_tag(data)) goto err;
530
0
    if (!asn1_pop_tag(data)) goto err;
531
0
    break;
532
0
  }
533
0
  case LDAP_TAG_ModifyResponse: {
534
0
    struct ldap_Result *r = &msg->r.ModifyResponse;
535
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
536
0
    if (!ldap_encode_response(data, r)) goto err;
537
0
    if (!asn1_pop_tag(data)) goto err;
538
0
    break;
539
0
  }
540
0
  case LDAP_TAG_AddRequest: {
541
0
    struct ldap_AddRequest *r = &msg->r.AddRequest;
542
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
543
0
    if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
544
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
545
546
0
    for (i=0; i<r->num_attributes; i++) {
547
0
      struct ldb_message_element *attrib = &r->attributes[i];
548
0
      if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
549
0
      if (attrib->name == NULL) {
550
0
        goto err;
551
0
      }
552
0
      if (!asn1_write_OctetString(data, attrib->name,
553
0
                 strlen(attrib->name))) goto err;
554
0
      if (!asn1_push_tag(data, ASN1_SET)) goto err;
555
0
      for (j=0; j<r->attributes[i].num_values; j++) {
556
0
        if (!asn1_write_OctetString(data,
557
0
                   attrib->values[j].data,
558
0
                   attrib->values[j].length)) goto err;
559
0
      }
560
0
      if (!asn1_pop_tag(data)) goto err;
561
0
      if (!asn1_pop_tag(data)) goto err;
562
0
    }
563
0
    if (!asn1_pop_tag(data)) goto err;
564
0
    if (!asn1_pop_tag(data)) goto err;
565
0
    break;
566
0
  }
567
0
  case LDAP_TAG_AddResponse: {
568
0
    struct ldap_Result *r = &msg->r.AddResponse;
569
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
570
0
    if (!ldap_encode_response(data, r)) goto err;
571
0
    if (!asn1_pop_tag(data)) goto err;
572
0
    break;
573
0
  }
574
0
  case LDAP_TAG_DelRequest: {
575
0
    struct ldap_DelRequest *r = &msg->r.DelRequest;
576
0
    if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
577
0
    if (!asn1_write(data, r->dn, strlen(r->dn))) goto err;
578
0
    if (!asn1_pop_tag(data)) goto err;
579
0
    break;
580
0
  }
581
0
  case LDAP_TAG_DelResponse: {
582
0
    struct ldap_Result *r = &msg->r.DelResponse;
583
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
584
0
    if (!ldap_encode_response(data, r)) goto err;
585
0
    if (!asn1_pop_tag(data)) goto err;
586
0
    break;
587
0
  }
588
0
  case LDAP_TAG_ModifyDNRequest: {
589
0
    struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
590
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
591
0
    if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
592
0
    if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err;
593
0
    if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err;
594
0
    if (r->newsuperior) {
595
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
596
0
      if (!asn1_write(data, r->newsuperior,
597
0
           strlen(r->newsuperior))) goto err;
598
0
      if (!asn1_pop_tag(data)) goto err;
599
0
    }
600
0
    if (!asn1_pop_tag(data)) goto err;
601
0
    break;
602
0
  }
603
0
  case LDAP_TAG_ModifyDNResponse: {
604
0
    struct ldap_Result *r = &msg->r.ModifyDNResponse;
605
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
606
0
    if (!ldap_encode_response(data, r)) goto err;
607
0
    if (!asn1_pop_tag(data)) goto err;
608
0
    break;
609
0
  }
610
0
  case LDAP_TAG_CompareRequest: {
611
0
    struct ldap_CompareRequest *r = &msg->r.CompareRequest;
612
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
613
0
    if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
614
0
    if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
615
0
    if (!asn1_write_OctetString(data, r->attribute,
616
0
               strlen(r->attribute))) goto err;
617
0
    if (!asn1_write_OctetString(data, r->value.data,
618
0
               r->value.length)) goto err;
619
0
    if (!asn1_pop_tag(data)) goto err;
620
0
    if (!asn1_pop_tag(data)) goto err;
621
0
    break;
622
0
  }
623
0
  case LDAP_TAG_CompareResponse: {
624
0
    struct ldap_Result *r = &msg->r.ModifyDNResponse;
625
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
626
0
    if (!ldap_encode_response(data, r)) goto err;
627
0
    if (!asn1_pop_tag(data)) goto err;
628
0
    break;
629
0
  }
630
0
  case LDAP_TAG_AbandonRequest: {
631
0
    struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
632
0
    if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
633
0
    if (!asn1_write_implicit_Integer(data, r->messageid)) goto err;
634
0
    if (!asn1_pop_tag(data)) goto err;
635
0
    break;
636
0
  }
637
0
  case LDAP_TAG_SearchResultReference: {
638
0
    struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
639
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
640
0
    if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err;
641
0
    if (!asn1_pop_tag(data)) goto err;
642
0
    break;
643
0
  }
644
0
  case LDAP_TAG_ExtendedRequest: {
645
0
    struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
646
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
647
0
    if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
648
0
    if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
649
0
    if (!asn1_pop_tag(data)) goto err;
650
0
    if (r->value) {
651
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err;
652
0
      if (!asn1_write(data, r->value->data, r->value->length)) goto err;
653
0
      if (!asn1_pop_tag(data)) goto err;
654
0
    }
655
0
    if (!asn1_pop_tag(data)) goto err;
656
0
    break;
657
0
  }
658
0
  case LDAP_TAG_ExtendedResponse: {
659
0
    struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
660
0
    if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
661
0
    if (!ldap_encode_response(data, &r->response)) goto err;
662
0
    if (r->oid) {
663
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err;
664
0
      if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
665
0
      if (!asn1_pop_tag(data)) goto err;
666
0
    }
667
0
    if (r->value) {
668
0
      if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err;
669
0
      if (!asn1_write(data, r->value->data, r->value->length)) goto err;
670
0
      if (!asn1_pop_tag(data)) goto err;
671
0
    }
672
0
    if (!asn1_pop_tag(data)) goto err;
673
0
    break;
674
0
  }
675
0
  default:
676
0
    goto err;
677
0
  }
678
679
0
  if (msg->controls != NULL) {
680
0
    if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
681
    
682
0
    for (i = 0; msg->controls[i] != NULL; i++) {
683
0
      if (!ldap_encode_control(mem_ctx, data,
684
0
             control_handlers,
685
0
             msg->controls[i])) {
686
0
        DEBUG(0,("Unable to encode control %s\n",
687
0
           msg->controls[i]->oid));
688
0
        goto err;
689
0
      }
690
0
    }
691
692
0
    if (!asn1_pop_tag(data)) goto err;
693
0
  }
694
695
0
  if (!asn1_pop_tag(data)) goto err;
696
697
0
  if (!asn1_extract_blob(data, mem_ctx, result)) {
698
0
    goto err;
699
0
  }
700
701
0
  asn1_free(data);
702
703
0
  return true;
704
705
0
  err:
706
707
0
  asn1_free(data);
708
0
  return false;
709
0
}
710
711
static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
712
              DATA_BLOB blob)
713
6.64k
{
714
6.64k
  char *result = talloc_array(mem_ctx, char, blob.length+1);
715
6.64k
  if (result == NULL) {
716
0
    return NULL;
717
0
  }
718
6.64k
  memcpy(result, blob.data, blob.length);
719
6.64k
  result[blob.length] = '\0';
720
6.64k
  return result;
721
6.64k
}
722
723
bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
724
          struct asn1_data *data,
725
          const char **result)
726
6.67k
{
727
6.67k
  DATA_BLOB string;
728
6.67k
  if (!asn1_read_OctetString(data, mem_ctx, &string))
729
161
    return false;
730
6.51k
  *result = blob2string_talloc(mem_ctx, string);
731
6.51k
  data_blob_free(&string);
732
6.51k
  return *result ? true : false;
733
6.67k
}
734
735
static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
736
         struct asn1_data *data,
737
         struct ldap_Result *result)
738
190
{
739
190
  if (!asn1_read_enumerated(data, &result->resultcode)) return false;
740
112
  if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
741
66
  if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
742
42
  if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
743
5
    if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
744
4
    if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
745
3
    if (!asn1_end_tag(data)) return false;
746
37
  } else {
747
37
    result->referral = NULL;
748
37
  }
749
39
  return true;
750
42
}
751
752
static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
753
1.99k
{
754
755
1.99k
  chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
756
1.99k
  if (chunks == NULL) {
757
0
    return NULL;
758
0
  }
759
760
1.99k
  chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
761
1.99k
  if (chunks[chunk_num] == NULL) {
762
0
    return NULL;
763
0
  }
764
765
1.99k
  chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
766
1.99k
  if (chunks[chunk_num]->data == NULL) {
767
0
    return NULL;
768
0
  }
769
1.99k
  chunks[chunk_num]->length = strlen(value);
770
771
1.99k
  chunks[chunk_num + 1] = NULL;
772
773
1.99k
  return chunks;
774
1.99k
}
775
776
777
/*
778
  parse the ASN.1 formatted search string into a ldb_parse_tree
779
*/
780
static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, 
781
                  struct asn1_data *data)
782
24.7k
{
783
24.7k
  uint8_t filter_tag;
784
24.7k
  struct ldb_parse_tree *ret;
785
786
24.7k
  if (!asn1_peek_uint8(data, &filter_tag)) {
787
20
    return NULL;
788
20
  }
789
790
24.7k
  filter_tag &= 0x1f; /* strip off the asn1 stuff */
791
792
24.7k
  ret = talloc(mem_ctx, struct ldb_parse_tree);
793
24.7k
  if (ret == NULL) return NULL;
794
795
24.7k
  switch(filter_tag) {
796
5.85k
  case 0:
797
7.39k
  case 1:
798
    /* AND or OR of one or more filters */
799
7.39k
    ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
800
7.39k
    ret->u.list.num_elements = 0;
801
7.39k
    ret->u.list.elements = NULL;
802
803
7.39k
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
804
60
      goto failed;
805
60
    }
806
807
20.9k
    while (asn1_tag_remaining(data) > 0) {
808
19.3k
      struct ldb_parse_tree *subtree;
809
19.3k
      subtree = ldap_decode_filter_tree(ret, data);
810
19.3k
      if (subtree == NULL) {
811
5.74k
        goto failed;
812
5.74k
      }
813
13.5k
      ret->u.list.elements = 
814
13.5k
        talloc_realloc(ret, ret->u.list.elements, 
815
13.5k
                 struct ldb_parse_tree *, 
816
13.5k
                 ret->u.list.num_elements+1);
817
13.5k
      if (ret->u.list.elements == NULL) {
818
0
        goto failed;
819
0
      }
820
13.5k
      talloc_steal(ret->u.list.elements, subtree);
821
13.5k
      ret->u.list.elements[ret->u.list.num_elements] = subtree;
822
13.5k
      ret->u.list.num_elements++;
823
13.5k
    }
824
1.59k
    if (!asn1_end_tag(data)) {
825
102
      goto failed;
826
102
    }
827
1.49k
    break;
828
829
4.97k
  case 2:
830
    /* 'not' operation */
831
4.97k
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
832
35
      goto failed;
833
35
    }
834
835
4.93k
    ret->operation = LDB_OP_NOT;
836
4.93k
    ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
837
4.93k
    if (ret->u.isnot.child == NULL) {
838
4.74k
      goto failed;
839
4.74k
    }
840
198
    if (!asn1_end_tag(data)) {
841
3
      goto failed;
842
3
    }
843
195
    break;
844
845
372
  case 3: {
846
    /* equalityMatch */
847
372
    const char *attrib;
848
372
    DATA_BLOB value;
849
850
372
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
851
369
    if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
852
368
    if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
853
364
    if (!asn1_end_tag(data)) goto failed;
854
363
    if (asn1_has_error(data) || (attrib == NULL) ||
855
363
        (value.data == NULL)) {
856
0
      goto failed;
857
0
    }
858
859
363
    ret->operation = LDB_OP_EQUALITY;
860
363
    ret->u.equality.attr = talloc_steal(ret, attrib);
861
363
    ret->u.equality.value.data = talloc_steal(ret, value.data);
862
363
    ret->u.equality.value.length = value.length;
863
363
    break;
864
363
  }
865
2.26k
  case 4: {
866
    /* substrings */
867
2.26k
    DATA_BLOB attr;
868
2.26k
    uint8_t subs_tag;
869
2.26k
    char *value;
870
2.26k
    int chunk_num = 0;
871
872
2.26k
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
873
7
      goto failed;
874
7
    }
875
2.25k
    if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
876
2
      goto failed;
877
2
    }
878
879
2.25k
    ret->operation = LDB_OP_SUBSTRING;
880
2.25k
    ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
881
2.25k
    if (ret->u.substring.attr == NULL) {
882
0
      goto failed;
883
0
    }
884
2.25k
    ret->u.substring.chunks = NULL;
885
2.25k
    ret->u.substring.start_with_wildcard = 1;
886
2.25k
    ret->u.substring.end_with_wildcard = 1;
887
888
2.25k
    if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
889
3
      goto failed;
890
3
    }
891
892
4.25k
    while (asn1_tag_remaining(data) > 0) {
893
2.02k
      if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
894
2.02k
      subs_tag &= 0x1f; /* strip off the asn1 stuff */
895
2.02k
      if (subs_tag > 2) goto failed;
896
897
2.00k
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
898
1.99k
      if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
899
1.99k
      if (!asn1_end_tag(data)) goto failed;
900
901
1.99k
      switch (subs_tag) {
902
239
      case 0:
903
239
        if (ret->u.substring.chunks != NULL) {
904
          /* initial value found in the middle */
905
1
          goto failed;
906
1
        }
907
908
238
        ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
909
238
        if (ret->u.substring.chunks == NULL) {
910
0
          goto failed;
911
0
        }
912
913
238
        ret->u.substring.start_with_wildcard = 0;
914
238
        chunk_num = 1;
915
238
        break;
916
917
968
      case 1:
918
968
        if (ret->u.substring.end_with_wildcard == 0) {
919
          /* "any" value found after a "final" value */
920
1
          goto failed;
921
1
        }
922
923
967
        ret->u.substring.chunks = ldap_decode_substring(ret,
924
967
                    ret->u.substring.chunks,
925
967
                    chunk_num,
926
967
                    value);
927
967
        if (ret->u.substring.chunks == NULL) {
928
0
          goto failed;
929
0
        }
930
931
967
        chunk_num++;
932
967
        break;
933
934
792
      case 2:
935
792
        ret->u.substring.chunks = ldap_decode_substring(ret,
936
792
                    ret->u.substring.chunks,
937
792
                    chunk_num,
938
792
                    value);
939
792
        if (ret->u.substring.chunks == NULL) {
940
0
          goto failed;
941
0
        }
942
943
792
        ret->u.substring.end_with_wildcard = 0;
944
792
        break;
945
946
0
      default:
947
0
        goto failed;
948
1.99k
      }
949
950
1.99k
    }
951
952
2.22k
    if (!asn1_end_tag(data)) { /* SEQUENCE */
953
10
      goto failed;
954
10
    }
955
956
2.21k
    if (!asn1_end_tag(data)) {
957
5
      goto failed;
958
5
    }
959
2.20k
    break;
960
2.21k
  }
961
2.20k
  case 5: {
962
    /* greaterOrEqual */
963
211
    const char *attrib;
964
211
    DATA_BLOB value;
965
966
211
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
967
208
    if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
968
204
    if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
969
202
    if (!asn1_end_tag(data)) goto failed;
970
201
    if (asn1_has_error(data) || (attrib == NULL) ||
971
201
        (value.data == NULL)) {
972
0
      goto failed;
973
0
    }
974
975
201
    ret->operation = LDB_OP_GREATER;
976
201
    ret->u.comparison.attr = talloc_steal(ret, attrib);
977
201
    ret->u.comparison.value.data = talloc_steal(ret, value.data);
978
201
    ret->u.comparison.value.length = value.length;
979
201
    break;
980
201
  }
981
274
  case 6: {
982
    /* lessOrEqual */
983
274
    const char *attrib;
984
274
    DATA_BLOB value;
985
986
274
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
987
271
    if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
988
256
    if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
989
255
    if (!asn1_end_tag(data)) goto failed;
990
253
    if (asn1_has_error(data) || (attrib == NULL) ||
991
253
        (value.data == NULL)) {
992
0
      goto failed;
993
0
    }
994
995
253
    ret->operation = LDB_OP_LESS;
996
253
    ret->u.comparison.attr = talloc_steal(ret, attrib);
997
253
    ret->u.comparison.value.data = talloc_steal(ret, value.data);
998
253
    ret->u.comparison.value.length = value.length;
999
253
    break;
1000
253
  }
1001
1.60k
  case 7: {
1002
    /* Normal presence, "attribute=*" */
1003
1.60k
    char *attr;
1004
1005
1.60k
    if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
1006
1
      goto failed;
1007
1
    }
1008
1.60k
    if (!asn1_read_LDAPString(data, ret, &attr)) {
1009
0
      goto failed;
1010
0
    }
1011
1012
1.60k
    ret->operation = LDB_OP_PRESENT;
1013
1.60k
    ret->u.present.attr = talloc_steal(ret, attr);
1014
1015
1.60k
    if (!asn1_end_tag(data)) {
1016
0
      goto failed;
1017
0
    }
1018
1.60k
    break;
1019
1.60k
  }
1020
1.60k
  case 8: {
1021
    /* approx */
1022
340
    const char *attrib;
1023
340
    DATA_BLOB value;
1024
1025
340
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
1026
339
    if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
1027
337
    if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
1028
333
    if (!asn1_end_tag(data)) goto failed;
1029
330
    if (asn1_has_error(data) || (attrib == NULL) ||
1030
330
        (value.data == NULL)) {
1031
0
      goto failed;
1032
0
    }
1033
1034
330
    ret->operation = LDB_OP_APPROX;
1035
330
    ret->u.comparison.attr = talloc_steal(ret, attrib);
1036
330
    ret->u.comparison.value.data = talloc_steal(ret, value.data);
1037
330
    ret->u.comparison.value.length = value.length;
1038
330
    break;
1039
330
  }
1040
7.30k
  case 9: {
1041
7.30k
    char *oid = NULL, *attr = NULL, *value;
1042
7.30k
    uint8_t dnAttributes;
1043
    /* an extended search */
1044
7.30k
    if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1045
5
      goto failed;
1046
5
    }
1047
1048
    /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1049
       we need to check we properly implement --SSS */ 
1050
    /* either oid or type must be defined */
1051
7.29k
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1052
6.74k
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
1053
6.74k
      if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
1054
6.74k
      if (!asn1_end_tag(data)) goto failed;
1055
6.74k
    }
1056
7.29k
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional  */
1057
924
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
1058
920
      if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
1059
920
      if (!asn1_end_tag(data)) goto failed;
1060
920
    }
1061
7.29k
    if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
1062
7.26k
    if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
1063
7.26k
    if (!asn1_end_tag(data)) goto failed;
1064
    /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1065
       it is not marked as OPTIONAL but openldap tools
1066
       do not set this unless it is to be set as TRUE
1067
       NOTE: openldap tools do not work with AD as it
1068
       seems that AD always requires the dnAttributes
1069
       boolean value to be set */
1070
7.26k
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1071
197
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
1072
196
      if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
1073
195
      if (!asn1_end_tag(data)) goto failed;
1074
7.06k
    } else {
1075
7.06k
      dnAttributes = 0;
1076
7.06k
    }
1077
7.25k
    if ((oid == NULL && attr == NULL) || (value == NULL)) {
1078
9
      goto failed;
1079
9
    }
1080
1081
7.24k
    if (oid) {
1082
6.72k
      ret->operation               = LDB_OP_EXTENDED;
1083
1084
      /* From the RFC2251: If the type field is
1085
         absent and matchingRule is present, the matchValue is compared
1086
         against all attributes in an entry which support that matchingRule
1087
      */
1088
6.72k
      if (attr) {
1089
387
        ret->u.extended.attr = talloc_steal(ret, attr);
1090
6.33k
      } else {
1091
6.33k
        ret->u.extended.attr = talloc_strdup(ret, "*");
1092
6.33k
        if (ret->u.extended.attr == NULL) {
1093
0
          goto failed;
1094
0
        }
1095
6.33k
      }
1096
6.72k
      ret->u.extended.rule_id      = talloc_steal(ret, oid);
1097
6.72k
      ret->u.extended.value.data   = (uint8_t *)talloc_steal(ret, value);
1098
6.72k
      ret->u.extended.value.length = strlen(value);
1099
6.72k
      ret->u.extended.dnAttributes = dnAttributes;
1100
6.72k
    } else {
1101
524
      ret->operation               = LDB_OP_EQUALITY;
1102
524
      ret->u.equality.attr         = talloc_steal(ret, attr);
1103
524
      ret->u.equality.value.data   = (uint8_t *)talloc_steal(ret, value);
1104
524
      ret->u.equality.value.length = strlen(value);
1105
524
    }
1106
7.24k
    if (!asn1_end_tag(data)) {
1107
6
      goto failed;
1108
6
    }
1109
7.24k
    break;
1110
7.24k
  }
1111
1112
7.24k
  default:
1113
16
    goto failed;
1114
24.7k
  }
1115
  
1116
13.8k
  return ret;
1117
1118
10.8k
failed:
1119
10.8k
  talloc_free(ret);
1120
10.8k
  return NULL; 
1121
24.7k
}
1122
1123
/* Decode a single LDAP attribute, possibly containing multiple values */
1124
static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1125
             struct ldb_message_element *attrib)
1126
235
{
1127
235
  if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1128
213
  if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
1129
201
  if (!asn1_start_tag(data, ASN1_SET)) return false;
1130
30.5k
  while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1131
30.4k
    DATA_BLOB blob;
1132
30.4k
    if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
1133
30.4k
    add_value_to_attrib(mem_ctx, &blob, attrib);
1134
30.4k
  }
1135
179
  if (!asn1_end_tag(data)) return false;
1136
155
  return asn1_end_tag(data);
1137
179
}
1138
1139
/* Decode a set of LDAP attributes, as found in the dereference control */
1140
bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1141
            struct ldb_message_element **attributes,
1142
            int *num_attributes)
1143
143
{
1144
245
  while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1145
172
    struct ldb_message_element attrib;
1146
172
    ZERO_STRUCT(attrib);
1147
172
    if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
1148
102
    add_attrib_to_array_talloc(mem_ctx, &attrib,
1149
102
             attributes, num_attributes);
1150
102
  }
1151
73
  return true;
1152
143
}
1153
1154
/* Decode a set of LDAP attributes, as found in a search entry */
1155
static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1156
        struct ldb_message_element **attributes,
1157
        int *num_attributes)
1158
88
{
1159
88
  if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1160
79
  if (!ldap_decode_attribs_bare(mem_ctx, data,
1161
79
         attributes, num_attributes)) return false;
1162
37
  return asn1_end_tag(data);
1163
79
}
1164
1165
/* This routine returns LDAP status codes */
1166
1167
_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1168
            const struct ldap_request_limits *limits,
1169
            const struct ldap_control_handler *control_handlers,
1170
            struct ldap_message *msg)
1171
2.48k
{
1172
2.48k
  uint8_t tag;
1173
1174
2.48k
  if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1175
2.27k
  if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
1176
1177
2.26k
  if (!asn1_peek_uint8(data, &tag)) goto prot_err;
1178
1179
2.21k
  switch(tag) {
1180
1181
39
  case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1182
39
    struct ldap_BindRequest *r = &msg->r.BindRequest;
1183
39
    msg->type = LDAP_TAG_BindRequest;
1184
39
    if (!asn1_start_tag(data, tag)) goto prot_err;
1185
37
    if (!asn1_read_Integer(data, &r->version)) goto prot_err;
1186
35
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1187
33
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1188
25
      int pwlen;
1189
25
      r->creds.password = "";
1190
25
      r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1191
25
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1192
23
      pwlen = asn1_tag_remaining(data);
1193
23
      if (pwlen == -1) {
1194
0
        goto prot_err;
1195
0
      }
1196
23
      if (pwlen != 0) {
1197
21
        char *pw = talloc_array(msg, char, pwlen+1);
1198
21
        if (!pw) {
1199
0
          return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1200
0
        }
1201
21
        if (!asn1_read(data, pw, pwlen)) goto prot_err;
1202
21
        pw[pwlen] = '\0';
1203
21
        r->creds.password = pw;
1204
21
      }
1205
23
      if (!asn1_end_tag(data)) goto prot_err;
1206
23
    } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1207
7
      if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
1208
6
      r->mechanism = LDAP_AUTH_MECH_SASL;
1209
6
      if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
1210
5
      if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1211
2
        DATA_BLOB tmp_blob = data_blob(NULL, 0);
1212
2
        if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
1213
1
        r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1214
1
        if (!r->creds.SASL.secblob) {
1215
0
          return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1216
0
        }
1217
1
        *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1218
1
                    tmp_blob.data, tmp_blob.length);
1219
1
        data_blob_free(&tmp_blob);
1220
3
      } else {
1221
3
        r->creds.SASL.secblob = NULL;
1222
3
      }
1223
4
      if (!asn1_end_tag(data)) goto prot_err;
1224
4
    } else {
1225
      /* Neither Simple nor SASL bind */
1226
1
      goto prot_err;
1227
1
    }
1228
25
    if (!asn1_end_tag(data)) goto prot_err;
1229
2
    break;
1230
25
  }
1231
1232
43
  case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1233
43
    struct ldap_BindResponse *r = &msg->r.BindResponse;
1234
43
    msg->type = LDAP_TAG_BindResponse;
1235
43
    if (!asn1_start_tag(data, tag)) goto prot_err;
1236
41
    if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1237
6
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1238
4
      DATA_BLOB tmp_blob = data_blob(NULL, 0);
1239
4
      if (!asn1_read_ContextSimple(data, msg, 7, &tmp_blob)) goto prot_err;
1240
3
      r->SASL.secblob = talloc(msg, DATA_BLOB);
1241
3
      if (!r->SASL.secblob) {
1242
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1243
0
      }
1244
3
      *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1245
3
                  tmp_blob.data, tmp_blob.length);
1246
3
      data_blob_free(&tmp_blob);
1247
3
    } else {
1248
2
      r->SASL.secblob = NULL;
1249
2
    }
1250
5
    if (!asn1_end_tag(data)) goto prot_err;
1251
1
    break;
1252
5
  }
1253
1254
111
  case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1255
111
    msg->type = LDAP_TAG_UnbindRequest;
1256
111
    if (!asn1_start_tag(data, tag)) goto prot_err;
1257
110
    if (!asn1_end_tag(data)) goto prot_err;
1258
96
    break;
1259
110
  }
1260
1261
623
  case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1262
623
    struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1263
623
    int sizelimit, timelimit;
1264
623
    const char **attrs = NULL;
1265
623
    size_t request_size = asn1_get_length(data);
1266
623
    msg->type = LDAP_TAG_SearchRequest;
1267
623
    if (request_size > limits->max_search_size) {
1268
21
      goto prot_err;
1269
21
    }
1270
602
    if (!asn1_start_tag(data, tag)) goto prot_err;
1271
598
    if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
1272
597
    if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
1273
559
    if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
1274
549
    if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
1275
543
    r->sizelimit = sizelimit;
1276
543
    if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
1277
537
    r->timelimit = timelimit;
1278
537
    if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
1279
1280
514
    r->tree = ldap_decode_filter_tree(msg, data);
1281
514
    if (r->tree == NULL) {
1282
406
      goto prot_err;
1283
406
    }
1284
1285
108
    if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1286
1287
38
    r->num_attributes = 0;
1288
38
    r->attributes = NULL;
1289
1290
3.72k
    while (asn1_tag_remaining(data) > 0) {
1291
1292
3.70k
      const char *attr;
1293
3.70k
      if (!asn1_read_OctetString_talloc(msg, data,
1294
3.70k
                &attr))
1295
19
        goto prot_err;
1296
3.68k
      if (!add_string_to_array(msg, attr,
1297
3.68k
             &attrs,
1298
3.68k
             &r->num_attributes))
1299
0
        goto prot_err;
1300
3.68k
    }
1301
19
    r->attributes = attrs;
1302
1303
19
    if (!asn1_end_tag(data)) goto prot_err;
1304
14
    if (!asn1_end_tag(data)) goto prot_err;
1305
7
    break;
1306
14
  }
1307
1308
55
  case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1309
55
    struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1310
55
    msg->type = LDAP_TAG_SearchResultEntry;
1311
55
    r->attributes = NULL;
1312
55
    r->num_attributes = 0;
1313
55
    if (!asn1_start_tag(data, tag)) goto prot_err;
1314
53
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1315
52
    if (!ldap_decode_attribs(msg, data, &r->attributes,
1316
52
            &r->num_attributes)) goto prot_err;
1317
12
    if (!asn1_end_tag(data)) goto prot_err;
1318
1
    break;
1319
12
  }
1320
1321
55
  case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1322
55
    struct ldap_Result *r = &msg->r.SearchResultDone;
1323
55
    msg->type = LDAP_TAG_SearchResultDone;
1324
55
    if (!asn1_start_tag(data, tag)) goto prot_err;
1325
53
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1326
10
    if (!asn1_end_tag(data)) goto prot_err;
1327
1
    break;
1328
10
  }
1329
1330
12
  case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1331
12
    struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1332
12
    msg->type = LDAP_TAG_SearchResultReference;
1333
12
    if (!asn1_start_tag(data, tag)) goto prot_err;
1334
11
    if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
1335
10
    if (!asn1_end_tag(data)) goto prot_err;
1336
5
    break;
1337
10
  }
1338
1339
54
  case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1340
54
    struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1341
54
    msg->type = LDAP_TAG_ModifyRequest;
1342
54
    if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
1343
53
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1344
52
    if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1345
1346
49
    r->num_mods = 0;
1347
49
    r->mods = NULL;
1348
1349
96
    while (asn1_tag_remaining(data) > 0) {
1350
85
      struct ldap_mod mod;
1351
85
      int v;
1352
85
      ZERO_STRUCT(mod);
1353
85
      if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1354
67
      if (!asn1_read_enumerated(data, &v)) goto prot_err;
1355
63
      mod.type = v;
1356
63
      if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
1357
48
      if (!asn1_end_tag(data)) goto prot_err;
1358
47
      if (!add_mod_to_array_talloc(msg, &mod,
1359
47
                 &r->mods, &r->num_mods)) {
1360
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1361
0
      }
1362
47
    }
1363
1364
11
    if (!asn1_end_tag(data)) goto prot_err;
1365
6
    if (!asn1_end_tag(data)) goto prot_err;
1366
1
    break;
1367
6
  }
1368
1369
23
  case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1370
23
    struct ldap_Result *r = &msg->r.ModifyResponse;
1371
23
    msg->type = LDAP_TAG_ModifyResponse;
1372
23
    if (!asn1_start_tag(data, tag)) goto prot_err;
1373
22
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1374
2
    if (!asn1_end_tag(data)) goto prot_err;
1375
1
    break;
1376
2
  }
1377
1378
39
  case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1379
39
    struct ldap_AddRequest *r = &msg->r.AddRequest;
1380
39
    msg->type = LDAP_TAG_AddRequest;
1381
39
    if (!asn1_start_tag(data, tag)) goto prot_err;
1382
38
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1383
1384
36
    r->attributes = NULL;
1385
36
    r->num_attributes = 0;
1386
36
    if (!ldap_decode_attribs(msg, data, &r->attributes,
1387
36
            &r->num_attributes)) goto prot_err;
1388
1389
3
    if (!asn1_end_tag(data)) goto prot_err;
1390
2
    break;
1391
3
  }
1392
1393
29
  case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1394
29
    struct ldap_Result *r = &msg->r.AddResponse;
1395
29
    msg->type = LDAP_TAG_AddResponse;
1396
29
    if (!asn1_start_tag(data, tag)) goto prot_err;
1397
28
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1398
4
    if (!asn1_end_tag(data)) goto prot_err;
1399
1
    break;
1400
4
  }
1401
1402
502
  case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1403
502
    struct ldap_DelRequest *r = &msg->r.DelRequest;
1404
502
    int len;
1405
502
    char *dn;
1406
502
    msg->type = LDAP_TAG_DelRequest;
1407
502
    if (!asn1_start_tag(data,
1408
502
             ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
1409
499
    len = asn1_tag_remaining(data);
1410
499
    if (len == -1) {
1411
0
      goto prot_err;
1412
0
    }
1413
499
    dn = talloc_array(msg, char, len+1);
1414
499
    if (dn == NULL)
1415
0
      break;
1416
499
    if (!asn1_read(data, dn, len)) goto prot_err;
1417
499
    dn[len] = '\0';
1418
499
    r->dn = dn;
1419
499
    if (!asn1_end_tag(data)) goto prot_err;
1420
499
    break;
1421
499
  }
1422
1423
499
  case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1424
5
    struct ldap_Result *r = &msg->r.DelResponse;
1425
5
    msg->type = LDAP_TAG_DelResponse;
1426
5
    if (!asn1_start_tag(data, tag)) goto prot_err;
1427
4
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1428
2
    if (!asn1_end_tag(data)) goto prot_err;
1429
1
    break;
1430
2
  }
1431
1432
131
  case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1433
131
    struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1434
131
    msg->type = LDAP_TAG_ModifyDNRequest;
1435
131
    if (!asn1_start_tag(data,
1436
131
             ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
1437
130
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1438
129
    if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
1439
126
    if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
1440
66
    r->newsuperior = NULL;
1441
66
    if (asn1_tag_remaining(data) > 0) {
1442
33
      int len;
1443
33
      char *newsup;
1444
33
      if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1445
29
      len = asn1_tag_remaining(data);
1446
29
      if (len == -1) {
1447
0
        goto prot_err;
1448
0
      }
1449
29
      newsup = talloc_array(msg, char, len+1);
1450
29
      if (newsup == NULL) {
1451
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1452
0
      }
1453
29
      if (!asn1_read(data, newsup, len)) goto prot_err;
1454
29
      newsup[len] = '\0';
1455
29
      r->newsuperior = newsup;
1456
29
      if (!asn1_end_tag(data)) goto prot_err;
1457
29
    }
1458
62
    if (!asn1_end_tag(data)) goto prot_err;
1459
9
    break;
1460
62
  }
1461
1462
9
  case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1463
9
    struct ldap_Result *r = &msg->r.ModifyDNResponse;
1464
9
    msg->type = LDAP_TAG_ModifyDNResponse;
1465
9
    if (!asn1_start_tag(data, tag)) goto prot_err;
1466
8
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1467
2
    if (!asn1_end_tag(data)) goto prot_err;
1468
1
    break;
1469
2
  }
1470
1471
21
  case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1472
21
    struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1473
21
    msg->type = LDAP_TAG_CompareRequest;
1474
21
    if (!asn1_start_tag(data,
1475
21
             ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
1476
20
    if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1477
19
    if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1478
7
    if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
1479
6
    if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
1480
5
    if (r->value.data) {
1481
5
      talloc_steal(msg, r->value.data);
1482
5
    }
1483
5
    if (!asn1_end_tag(data)) goto prot_err;
1484
3
    if (!asn1_end_tag(data)) goto prot_err;
1485
2
    break;
1486
3
  }
1487
1488
13
  case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1489
13
    struct ldap_Result *r = &msg->r.CompareResponse;
1490
13
    msg->type = LDAP_TAG_CompareResponse;
1491
13
    if (!asn1_start_tag(data, tag)) goto prot_err;
1492
12
    if (!ldap_decode_response(msg, data, r)) goto prot_err;
1493
2
    if (!asn1_end_tag(data)) goto prot_err;
1494
1
    break;
1495
2
  }
1496
1497
278
  case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1498
278
    struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1499
278
    msg->type = LDAP_TAG_AbandonRequest;
1500
278
    if (!asn1_start_tag(data, tag)) goto prot_err;
1501
274
    if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
1502
274
    if (!asn1_end_tag(data)) goto prot_err;
1503
274
    break;
1504
274
  }
1505
1506
274
  case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1507
126
    struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1508
126
    DATA_BLOB tmp_blob = data_blob(NULL, 0);
1509
1510
126
    msg->type = LDAP_TAG_ExtendedRequest;
1511
126
    if (!asn1_start_tag(data,tag)) goto prot_err;
1512
125
    if (!asn1_read_ContextSimple(data, msg, 0, &tmp_blob)) {
1513
3
      goto prot_err;
1514
3
    }
1515
122
    r->oid = blob2string_talloc(msg, tmp_blob);
1516
122
    data_blob_free(&tmp_blob);
1517
122
    if (!r->oid) {
1518
0
      return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1519
0
    }
1520
1521
122
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1522
58
      if (!asn1_read_ContextSimple(data, msg, 1, &tmp_blob)) goto prot_err;
1523
46
      r->value = talloc(msg, DATA_BLOB);
1524
46
      if (!r->value) {
1525
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1526
0
      }
1527
46
      *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1528
46
      data_blob_free(&tmp_blob);
1529
64
    } else {
1530
64
      r->value = NULL;
1531
64
    }
1532
1533
110
    if (!asn1_end_tag(data)) goto prot_err;
1534
11
    break;
1535
110
  }
1536
1537
23
  case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1538
23
    struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1539
23
    DATA_BLOB tmp_blob = data_blob(NULL, 0);
1540
1541
23
    msg->type = LDAP_TAG_ExtendedResponse;
1542
23
    if (!asn1_start_tag(data, tag)) goto prot_err;
1543
22
    if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1544
1545
11
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1546
5
      if (!asn1_read_ContextSimple(data, msg, 10, &tmp_blob))
1547
1
        goto prot_err;
1548
4
      r->oid = blob2string_talloc(msg, tmp_blob);
1549
4
      data_blob_free(&tmp_blob);
1550
4
      if (!r->oid) {
1551
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1552
0
      }
1553
6
    } else {
1554
6
      r->oid = NULL;
1555
6
    }
1556
1557
10
    if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1558
3
      if (!asn1_read_ContextSimple(data, msg, 11, &tmp_blob))
1559
1
        goto prot_err;
1560
2
      r->value = talloc(msg, DATA_BLOB);
1561
2
      if (!r->value) {
1562
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1563
0
      }
1564
2
      *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1565
2
      data_blob_free(&tmp_blob);
1566
7
    } else {
1567
7
      r->value = NULL;
1568
7
    }
1569
1570
9
    if (!asn1_end_tag(data)) goto prot_err;
1571
4
    break;
1572
9
  }
1573
26
  default:
1574
26
    goto prot_err;
1575
2.21k
  }
1576
1577
920
  msg->controls = NULL;
1578
920
  msg->controls_decoded = NULL;
1579
1580
920
  if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1581
780
    int i = 0;
1582
780
    struct ldb_control **ctrl = NULL;
1583
780
    bool *decoded = NULL;
1584
1585
780
    if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
1586
1587
2.50k
    while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1588
1.80k
      DATA_BLOB value;
1589
      /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1590
1591
1.80k
      ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1592
1.80k
      if (!ctrl) {
1593
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1594
0
      }
1595
1596
1.80k
      decoded = talloc_realloc(msg, decoded, bool, i+1);
1597
1.80k
      if (!decoded) {
1598
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1599
0
      }
1600
1601
1.80k
      ctrl[i] = talloc(ctrl, struct ldb_control);
1602
1.80k
      if (!ctrl[i]) {
1603
0
        return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1604
0
      }
1605
1606
1.80k
      if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1607
69
        goto prot_err;
1608
69
      }
1609
1610
1.73k
      if (!ldap_decode_control_value(ctrl[i], value,
1611
1.73k
                   control_handlers,
1612
1.73k
                   ctrl[i])) {
1613
1.52k
        if (ctrl[i]->critical) {
1614
92
          ctrl[i]->data = NULL;
1615
92
          decoded[i] = false;
1616
92
          i++;
1617
1.43k
        } else {
1618
1.43k
          talloc_free(ctrl[i]);
1619
1.43k
          ctrl[i] = NULL;
1620
1.43k
        }
1621
1.52k
      } else {
1622
208
        decoded[i] = true;
1623
208
        i++;
1624
208
      }
1625
1.73k
    }
1626
1627
707
    if (ctrl != NULL) {
1628
685
      ctrl[i] = NULL;
1629
685
    }
1630
1631
707
    msg->controls = ctrl;
1632
707
    msg->controls_decoded = decoded;
1633
1634
707
    if (!asn1_end_tag(data)) goto prot_err;
1635
707
  }
1636
1637
200
  if (!asn1_end_tag(data)) goto prot_err;
1638
7
  if (asn1_has_error(data) || asn1_has_nesting(data)) {
1639
0
    return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1640
0
  }
1641
7
  return NT_STATUS_OK;
1642
1643
2.48k
  prot_err:
1644
1645
2.48k
  return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1646
7
}
1647
1648
1649
/*
1650
  return NT_STATUS_OK if a blob has enough bytes in it to be a full
1651
  ldap packet. Set packet_size if true.
1652
*/
1653
NTSTATUS ldap_full_packet(struct tstream_context *stream,
1654
        void *private_data,
1655
        DATA_BLOB blob,
1656
        size_t *packet_size)
1657
0
{
1658
0
  int ret;
1659
1660
0
  if (blob.length < 6) {
1661
    /*
1662
     * We need at least 6 bytes to workout the length
1663
     * of the pdu.
1664
     */
1665
0
    return STATUS_MORE_ENTRIES;
1666
0
  }
1667
1668
0
  ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1669
0
  if (ret != 0) {
1670
0
    return map_nt_error_from_unix_common(ret);
1671
0
  }
1672
0
  return NT_STATUS_OK;
1673
0
}