backupkey: Handle more clearly the case where we find the secret, but it has no value
[Samba.git] / libcli / ldap / ldap_message.c
blobba94f4ccfacbbcad21c17a09df7c706459214e47
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
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.
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.
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/>.
25 #include "includes.h"
26 #include "../lib/util/asn1.h"
27 #include "../libcli/ldap/ldap_message.h"
29 _PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
31 return talloc_zero(mem_ctx, struct ldap_message);
35 static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36 struct ldb_message_element *attrib)
38 attrib->values = talloc_realloc(mem_ctx,
39 attrib->values,
40 DATA_BLOB,
41 attrib->num_values+1);
42 if (attrib->values == NULL)
43 return false;
45 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
46 value->data);
47 attrib->values[attrib->num_values].length = value->length;
48 attrib->num_values += 1;
49 return true;
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)
57 *attribs = talloc_realloc(mem_ctx,
58 *attribs,
59 struct ldb_message_element,
60 *num_attribs+1);
62 if (*attribs == NULL)
63 return false;
65 (*attribs)[*num_attribs] = *attrib;
66 talloc_steal(*attribs, attrib->values);
67 talloc_steal(*attribs, attrib->name);
68 *num_attribs += 1;
69 return true;
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)
77 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
79 if (*mods == NULL)
80 return false;
82 (*mods)[*num_mods] = *mod;
83 *num_mods += 1;
84 return true;
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)
91 int i;
93 if (!handlers) {
94 return true;
97 for (i = 0; handlers[i].oid != NULL; i++) {
98 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
99 if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
100 return false;
102 break;
105 if (handlers[i].oid == NULL) {
106 return false;
109 return true;
112 static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113 struct ldb_control *ctrl, DATA_BLOB *value)
115 DATA_BLOB oid;
117 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
118 return false;
121 if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
122 return false;
124 ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
125 if (!ctrl->oid) {
126 return false;
129 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
130 bool critical;
131 if (!asn1_read_BOOLEAN(data, &critical)) {
132 return false;
134 ctrl->critical = critical;
135 } else {
136 ctrl->critical = false;
139 ctrl->data = NULL;
141 if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142 *value = data_blob(NULL, 0);
143 goto end_tag;
146 if (!asn1_read_OctetString(data, mem_ctx, value)) {
147 return false;
150 end_tag:
151 if (!asn1_end_tag(data)) {
152 return false;
155 return true;
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)
162 DATA_BLOB value;
163 int i;
165 if (!handlers) {
166 return false;
169 for (i = 0; handlers[i].oid != NULL; i++) {
170 if (!ctrl->oid) {
171 /* not encoding this control, the OID has been
172 * set to NULL indicating it isn't really
173 * here */
174 return true;
176 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
177 if (!handlers[i].encode) {
178 if (ctrl->critical) {
179 return false;
180 } else {
181 /* not encoding this control */
182 return true;
185 if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
186 return false;
188 break;
191 if (handlers[i].oid == NULL) {
192 return false;
195 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
196 return false;
199 if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
200 return false;
203 if (ctrl->critical) {
204 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
205 return false;
209 if (!ctrl->data) {
210 goto pop_tag;
213 if (!asn1_write_OctetString(data, value.data, value.length)) {
214 return false;
217 pop_tag:
218 if (!asn1_pop_tag(data)) {
219 return false;
222 return true;
225 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
227 int i;
229 switch (tree->operation) {
230 case LDB_OP_AND:
231 case LDB_OP_OR:
232 if (!asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1))) return false;
233 for (i=0; i<tree->u.list.num_elements; i++) {
234 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
235 return false;
238 if (!asn1_pop_tag(data)) return false;
239 break;
241 case LDB_OP_NOT:
242 if (!asn1_push_tag(data, ASN1_CONTEXT(2))) return false;
243 if (!ldap_push_filter(data, tree->u.isnot.child)) {
244 return false;
246 if (!asn1_pop_tag(data)) return false;
247 break;
249 case LDB_OP_EQUALITY:
250 /* equality test */
251 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
252 if (!asn1_write_OctetString(data, tree->u.equality.attr,
253 strlen(tree->u.equality.attr))) return false;
254 if (!asn1_write_OctetString(data, tree->u.equality.value.data,
255 tree->u.equality.value.length)) return false;
256 if (!asn1_pop_tag(data)) return false;
257 break;
259 case LDB_OP_SUBSTRING:
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 } }
269 if (!asn1_push_tag(data, ASN1_CONTEXT(4))) return false;
270 if (!asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr))) return false;
271 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
273 if (tree->u.substring.chunks && tree->u.substring.chunks[0]) {
274 i = 0;
275 if (!tree->u.substring.start_with_wildcard) {
276 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) return false;
277 if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
278 if (!asn1_pop_tag(data)) return false;
279 i++;
281 while (tree->u.substring.chunks[i]) {
282 int ctx;
284 if (( ! tree->u.substring.chunks[i + 1]) &&
285 (tree->u.substring.end_with_wildcard == 0)) {
286 ctx = 2;
287 } else {
288 ctx = 1;
290 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx))) return false;
291 if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
292 if (!asn1_pop_tag(data)) return false;
293 i++;
296 if (!asn1_pop_tag(data)) return false;
297 if (!asn1_pop_tag(data)) return false;
298 break;
300 case LDB_OP_GREATER:
301 /* greaterOrEqual test */
302 if (!asn1_push_tag(data, ASN1_CONTEXT(5))) return false;
303 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
304 strlen(tree->u.comparison.attr))) return false;
305 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
306 tree->u.comparison.value.length)) return false;
307 if (!asn1_pop_tag(data)) return false;
308 break;
310 case LDB_OP_LESS:
311 /* lessOrEqual test */
312 if (!asn1_push_tag(data, ASN1_CONTEXT(6))) return false;
313 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
314 strlen(tree->u.comparison.attr))) return false;
315 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
316 tree->u.comparison.value.length)) return false;
317 if (!asn1_pop_tag(data)) return false;
318 break;
320 case LDB_OP_PRESENT:
321 /* present test */
322 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false;
323 if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false;
324 if (!asn1_pop_tag(data)) return false;
325 return !data->has_error;
327 case LDB_OP_APPROX:
328 /* approx test */
329 if (!asn1_push_tag(data, ASN1_CONTEXT(8))) return false;
330 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
331 strlen(tree->u.comparison.attr))) return false;
332 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
333 tree->u.comparison.value.length)) return false;
334 if (!asn1_pop_tag(data)) return false;
335 break;
337 case LDB_OP_EXTENDED:
339 MatchingRuleAssertion ::= SEQUENCE {
340 matchingRule [1] MatchingRuleID OPTIONAL,
341 type [2] AttributeDescription OPTIONAL,
342 matchValue [3] AssertionValue,
343 dnAttributes [4] BOOLEAN DEFAULT FALSE
346 if (!asn1_push_tag(data, ASN1_CONTEXT(9))) return false;
347 if (tree->u.extended.rule_id) {
348 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
349 if (!asn1_write_LDAPString(data, tree->u.extended.rule_id)) return false;
350 if (!asn1_pop_tag(data)) return false;
352 if (tree->u.extended.attr) {
353 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
354 if (!asn1_write_LDAPString(data, tree->u.extended.attr)) return false;
355 if (!asn1_pop_tag(data)) return false;
357 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
358 if (!asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value)) return false;
359 if (!asn1_pop_tag(data)) return false;
360 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
361 if (!asn1_write_uint8(data, tree->u.extended.dnAttributes)) return false;
362 if (!asn1_pop_tag(data)) return false;
363 if (!asn1_pop_tag(data)) return false;
364 break;
366 default:
367 return false;
369 return !data->has_error;
372 static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
374 if (!asn1_write_enumerated(data, result->resultcode)) return false;
375 if (!asn1_write_OctetString(data, result->dn,
376 (result->dn) ? strlen(result->dn) : 0)) return false;
377 if (!asn1_write_OctetString(data, result->errormessage,
378 (result->errormessage) ?
379 strlen(result->errormessage) : 0)) return false;
380 if (result->referral) {
381 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
382 if (!asn1_write_OctetString(data, result->referral,
383 strlen(result->referral))) return false;
384 if (!asn1_pop_tag(data)) return false;
386 return true;
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)
393 struct asn1_data *data = asn1_init(mem_ctx);
394 int i, j;
396 if (!data) return false;
398 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
399 if (!asn1_write_Integer(data, msg->messageid)) goto err;
401 switch (msg->type) {
402 case LDAP_TAG_BindRequest: {
403 struct ldap_BindRequest *r = &msg->r.BindRequest;
404 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
405 if (!asn1_write_Integer(data, r->version)) goto err;
406 if (!asn1_write_OctetString(data, r->dn,
407 (r->dn != NULL) ? strlen(r->dn) : 0)) goto err;
409 switch (r->mechanism) {
410 case LDAP_AUTH_MECH_SIMPLE:
411 /* context, primitive */
412 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
413 if (!asn1_write(data, r->creds.password,
414 strlen(r->creds.password))) goto err;
415 if (!asn1_pop_tag(data)) goto err;
416 break;
417 case LDAP_AUTH_MECH_SASL:
418 /* context, constructed */
419 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
420 if (!asn1_write_OctetString(data, r->creds.SASL.mechanism,
421 strlen(r->creds.SASL.mechanism))) goto err;
422 if (r->creds.SASL.secblob) {
423 if (!asn1_write_OctetString(data, r->creds.SASL.secblob->data,
424 r->creds.SASL.secblob->length)) goto err;
426 if (!asn1_pop_tag(data)) goto err;
427 break;
428 default:
429 goto err;
432 if (!asn1_pop_tag(data)) goto err;
433 break;
435 case LDAP_TAG_BindResponse: {
436 struct ldap_BindResponse *r = &msg->r.BindResponse;
437 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
438 if (!ldap_encode_response(data, &r->response)) goto err;
439 if (r->SASL.secblob) {
440 if (!asn1_write_ContextSimple(data, 7, r->SASL.secblob)) goto err;
442 if (!asn1_pop_tag(data)) goto err;
443 break;
445 case LDAP_TAG_UnbindRequest: {
446 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
447 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
448 if (!asn1_pop_tag(data)) goto err;
449 break;
451 case LDAP_TAG_SearchRequest: {
452 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
453 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
454 if (!asn1_write_OctetString(data, r->basedn, strlen(r->basedn))) goto err;
455 if (!asn1_write_enumerated(data, r->scope)) goto err;
456 if (!asn1_write_enumerated(data, r->deref)) goto err;
457 if (!asn1_write_Integer(data, r->sizelimit)) goto err;
458 if (!asn1_write_Integer(data, r->timelimit)) goto err;
459 if (!asn1_write_BOOLEAN(data, r->attributesonly)) goto err;
461 if (!ldap_push_filter(data, r->tree)) {
462 goto err;
465 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
466 for (i=0; i<r->num_attributes; i++) {
467 if (!asn1_write_OctetString(data, r->attributes[i],
468 strlen(r->attributes[i]))) goto err;
470 if (!asn1_pop_tag(data)) goto err;
471 if (!asn1_pop_tag(data)) goto err;
472 break;
474 case LDAP_TAG_SearchResultEntry: {
475 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
476 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
477 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
478 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
479 for (i=0; i<r->num_attributes; i++) {
480 struct ldb_message_element *attr = &r->attributes[i];
481 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
482 if (!asn1_write_OctetString(data, attr->name,
483 strlen(attr->name))) goto err;
484 if (!asn1_push_tag(data, ASN1_SEQUENCE(1))) goto err;
485 for (j=0; j<attr->num_values; j++) {
486 if (!asn1_write_OctetString(data,
487 attr->values[j].data,
488 attr->values[j].length)) goto err;
490 if (!asn1_pop_tag(data)) goto err;
491 if (!asn1_pop_tag(data)) goto err;
493 if (!asn1_pop_tag(data)) goto err;
494 if (!asn1_pop_tag(data)) goto err;
495 break;
497 case LDAP_TAG_SearchResultDone: {
498 struct ldap_Result *r = &msg->r.SearchResultDone;
499 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
500 if (!ldap_encode_response(data, r)) goto err;
501 if (!asn1_pop_tag(data)) goto err;
502 break;
504 case LDAP_TAG_ModifyRequest: {
505 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
506 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
507 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
508 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
510 for (i=0; i<r->num_mods; i++) {
511 struct ldb_message_element *attrib = &r->mods[i].attrib;
512 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
513 if (!asn1_write_enumerated(data, r->mods[i].type)) goto err;
514 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
515 if (!asn1_write_OctetString(data, attrib->name,
516 strlen(attrib->name))) goto err;
517 if (!asn1_push_tag(data, ASN1_SET)) goto err;
518 for (j=0; j<attrib->num_values; j++) {
519 if (!asn1_write_OctetString(data,
520 attrib->values[j].data,
521 attrib->values[j].length)) goto err;
524 if (!asn1_pop_tag(data)) goto err;
525 if (!asn1_pop_tag(data)) goto err;
526 if (!asn1_pop_tag(data)) goto err;
529 if (!asn1_pop_tag(data)) goto err;
530 if (!asn1_pop_tag(data)) goto err;
531 break;
533 case LDAP_TAG_ModifyResponse: {
534 struct ldap_Result *r = &msg->r.ModifyResponse;
535 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
536 if (!ldap_encode_response(data, r)) goto err;
537 if (!asn1_pop_tag(data)) goto err;
538 break;
540 case LDAP_TAG_AddRequest: {
541 struct ldap_AddRequest *r = &msg->r.AddRequest;
542 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
543 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
544 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
546 for (i=0; i<r->num_attributes; i++) {
547 struct ldb_message_element *attrib = &r->attributes[i];
548 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
549 if (!asn1_write_OctetString(data, attrib->name,
550 strlen(attrib->name))) goto err;
551 if (!asn1_push_tag(data, ASN1_SET)) goto err;
552 for (j=0; j<r->attributes[i].num_values; j++) {
553 if (!asn1_write_OctetString(data,
554 attrib->values[j].data,
555 attrib->values[j].length)) goto err;
557 if (!asn1_pop_tag(data)) goto err;
558 if (!asn1_pop_tag(data)) goto err;
560 if (!asn1_pop_tag(data)) goto err;
561 if (!asn1_pop_tag(data)) goto err;
562 break;
564 case LDAP_TAG_AddResponse: {
565 struct ldap_Result *r = &msg->r.AddResponse;
566 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
567 if (!ldap_encode_response(data, r)) goto err;
568 if (!asn1_pop_tag(data)) goto err;
569 break;
571 case LDAP_TAG_DelRequest: {
572 struct ldap_DelRequest *r = &msg->r.DelRequest;
573 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
574 if (!asn1_write(data, r->dn, strlen(r->dn))) goto err;
575 if (!asn1_pop_tag(data)) goto err;
576 break;
578 case LDAP_TAG_DelResponse: {
579 struct ldap_Result *r = &msg->r.DelResponse;
580 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
581 if (!ldap_encode_response(data, r)) goto err;
582 if (!asn1_pop_tag(data)) goto err;
583 break;
585 case LDAP_TAG_ModifyDNRequest: {
586 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
587 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
588 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
589 if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err;
590 if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err;
591 if (r->newsuperior) {
592 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
593 if (!asn1_write(data, r->newsuperior,
594 strlen(r->newsuperior))) goto err;
595 if (!asn1_pop_tag(data)) goto err;
597 if (!asn1_pop_tag(data)) goto err;
598 break;
600 case LDAP_TAG_ModifyDNResponse: {
601 struct ldap_Result *r = &msg->r.ModifyDNResponse;
602 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
603 if (!ldap_encode_response(data, r)) goto err;
604 if (!asn1_pop_tag(data)) goto err;
605 break;
607 case LDAP_TAG_CompareRequest: {
608 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
609 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
610 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
611 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
612 if (!asn1_write_OctetString(data, r->attribute,
613 strlen(r->attribute))) goto err;
614 if (!asn1_write_OctetString(data, r->value.data,
615 r->value.length)) goto err;
616 if (!asn1_pop_tag(data)) goto err;
617 if (!asn1_pop_tag(data)) goto err;
618 break;
620 case LDAP_TAG_CompareResponse: {
621 struct ldap_Result *r = &msg->r.ModifyDNResponse;
622 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
623 if (!ldap_encode_response(data, r)) goto err;
624 if (!asn1_pop_tag(data)) goto err;
625 break;
627 case LDAP_TAG_AbandonRequest: {
628 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
629 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
630 if (!asn1_write_implicit_Integer(data, r->messageid)) goto err;
631 if (!asn1_pop_tag(data)) goto err;
632 break;
634 case LDAP_TAG_SearchResultReference: {
635 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
636 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
637 if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err;
638 if (!asn1_pop_tag(data)) goto err;
639 break;
641 case LDAP_TAG_ExtendedRequest: {
642 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
643 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
644 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
645 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
646 if (!asn1_pop_tag(data)) goto err;
647 if (r->value) {
648 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err;
649 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
650 if (!asn1_pop_tag(data)) goto err;
652 if (!asn1_pop_tag(data)) goto err;
653 break;
655 case LDAP_TAG_ExtendedResponse: {
656 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
657 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
658 if (!ldap_encode_response(data, &r->response)) goto err;
659 if (r->oid) {
660 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err;
661 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
662 if (!asn1_pop_tag(data)) goto err;
664 if (r->value) {
665 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err;
666 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
667 if (!asn1_pop_tag(data)) goto err;
669 if (!asn1_pop_tag(data)) goto err;
670 break;
672 default:
673 goto err;
676 if (msg->controls != NULL) {
677 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
679 for (i = 0; msg->controls[i] != NULL; i++) {
680 if (!ldap_encode_control(mem_ctx, data,
681 control_handlers,
682 msg->controls[i])) {
683 DEBUG(0,("Unable to encode control %s\n",
684 msg->controls[i]->oid));
685 goto err;
689 if (!asn1_pop_tag(data)) goto err;
692 if (!asn1_pop_tag(data)) goto err;
694 *result = data_blob_talloc(mem_ctx, data->data, data->length);
695 asn1_free(data);
697 return true;
699 err:
701 asn1_free(data);
702 return false;
705 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
706 DATA_BLOB blob)
708 char *result = talloc_array(mem_ctx, char, blob.length+1);
709 memcpy(result, blob.data, blob.length);
710 result[blob.length] = '\0';
711 return result;
714 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
715 struct asn1_data *data,
716 const char **result)
718 DATA_BLOB string;
719 if (!asn1_read_OctetString(data, mem_ctx, &string))
720 return false;
721 *result = blob2string_talloc(mem_ctx, string);
722 data_blob_free(&string);
723 return true;
726 static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
727 struct asn1_data *data,
728 struct ldap_Result *result)
730 if (!asn1_read_enumerated(data, &result->resultcode)) return false;
731 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
732 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
733 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
734 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
735 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
736 if (!asn1_end_tag(data)) return false;
737 } else {
738 result->referral = NULL;
740 return true;
743 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
746 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
747 if (chunks == NULL) {
748 return NULL;
751 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
752 if (chunks[chunk_num] == NULL) {
753 return NULL;
756 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
757 if (chunks[chunk_num]->data == NULL) {
758 return NULL;
760 chunks[chunk_num]->length = strlen(value);
762 chunks[chunk_num + 1] = '\0';
764 return chunks;
769 parse the ASN.1 formatted search string into a ldb_parse_tree
771 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
772 struct asn1_data *data)
774 uint8_t filter_tag;
775 struct ldb_parse_tree *ret;
777 if (!asn1_peek_uint8(data, &filter_tag)) {
778 return NULL;
781 filter_tag &= 0x1f; /* strip off the asn1 stuff */
783 ret = talloc(mem_ctx, struct ldb_parse_tree);
784 if (ret == NULL) return NULL;
786 switch(filter_tag) {
787 case 0:
788 case 1:
789 /* AND or OR of one or more filters */
790 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
791 ret->u.list.num_elements = 0;
792 ret->u.list.elements = NULL;
794 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
795 goto failed;
798 while (asn1_tag_remaining(data) > 0) {
799 struct ldb_parse_tree *subtree;
800 subtree = ldap_decode_filter_tree(ret, data);
801 if (subtree == NULL) {
802 goto failed;
804 ret->u.list.elements =
805 talloc_realloc(ret, ret->u.list.elements,
806 struct ldb_parse_tree *,
807 ret->u.list.num_elements+1);
808 if (ret->u.list.elements == NULL) {
809 goto failed;
811 talloc_steal(ret->u.list.elements, subtree);
812 ret->u.list.elements[ret->u.list.num_elements] = subtree;
813 ret->u.list.num_elements++;
815 if (!asn1_end_tag(data)) {
816 goto failed;
818 break;
820 case 2:
821 /* 'not' operation */
822 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
823 goto failed;
826 ret->operation = LDB_OP_NOT;
827 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
828 if (ret->u.isnot.child == NULL) {
829 goto failed;
831 if (!asn1_end_tag(data)) {
832 goto failed;
834 break;
836 case 3: {
837 /* equalityMatch */
838 const char *attrib;
839 DATA_BLOB value;
841 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
842 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
843 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
844 if (!asn1_end_tag(data)) goto failed;
845 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
846 goto failed;
849 ret->operation = LDB_OP_EQUALITY;
850 ret->u.equality.attr = talloc_steal(ret, attrib);
851 ret->u.equality.value.data = talloc_steal(ret, value.data);
852 ret->u.equality.value.length = value.length;
853 break;
855 case 4: {
856 /* substrings */
857 DATA_BLOB attr;
858 uint8_t subs_tag;
859 char *value;
860 int chunk_num = 0;
862 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
863 goto failed;
865 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
866 goto failed;
869 ret->operation = LDB_OP_SUBSTRING;
870 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
871 ret->u.substring.chunks = NULL;
872 ret->u.substring.start_with_wildcard = 1;
873 ret->u.substring.end_with_wildcard = 1;
875 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
876 goto failed;
879 while (asn1_tag_remaining(data)) {
880 if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
881 subs_tag &= 0x1f; /* strip off the asn1 stuff */
882 if (subs_tag > 2) goto failed;
884 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
885 if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
886 if (!asn1_end_tag(data)) goto failed;
888 switch (subs_tag) {
889 case 0:
890 if (ret->u.substring.chunks != NULL) {
891 /* initial value found in the middle */
892 goto failed;
895 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
896 if (ret->u.substring.chunks == NULL) {
897 goto failed;
900 ret->u.substring.start_with_wildcard = 0;
901 chunk_num = 1;
902 break;
904 case 1:
905 if (ret->u.substring.end_with_wildcard == 0) {
906 /* "any" value found after a "final" value */
907 goto failed;
910 ret->u.substring.chunks = ldap_decode_substring(ret,
911 ret->u.substring.chunks,
912 chunk_num,
913 value);
914 if (ret->u.substring.chunks == NULL) {
915 goto failed;
918 chunk_num++;
919 break;
921 case 2:
922 ret->u.substring.chunks = ldap_decode_substring(ret,
923 ret->u.substring.chunks,
924 chunk_num,
925 value);
926 if (ret->u.substring.chunks == NULL) {
927 goto failed;
930 ret->u.substring.end_with_wildcard = 0;
931 break;
933 default:
934 goto failed;
939 if (!asn1_end_tag(data)) { /* SEQUENCE */
940 goto failed;
943 if (!asn1_end_tag(data)) {
944 goto failed;
946 break;
948 case 5: {
949 /* greaterOrEqual */
950 const char *attrib;
951 DATA_BLOB value;
953 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
954 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
955 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
956 if (!asn1_end_tag(data)) goto failed;
957 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
958 goto failed;
961 ret->operation = LDB_OP_GREATER;
962 ret->u.comparison.attr = talloc_steal(ret, attrib);
963 ret->u.comparison.value.data = talloc_steal(ret, value.data);
964 ret->u.comparison.value.length = value.length;
965 break;
967 case 6: {
968 /* lessOrEqual */
969 const char *attrib;
970 DATA_BLOB value;
972 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
973 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
974 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
975 if (!asn1_end_tag(data)) goto failed;
976 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
977 goto failed;
980 ret->operation = LDB_OP_LESS;
981 ret->u.comparison.attr = talloc_steal(ret, attrib);
982 ret->u.comparison.value.data = talloc_steal(ret, value.data);
983 ret->u.comparison.value.length = value.length;
984 break;
986 case 7: {
987 /* Normal presence, "attribute=*" */
988 char *attr;
990 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
991 goto failed;
993 if (!asn1_read_LDAPString(data, ret, &attr)) {
994 goto failed;
997 ret->operation = LDB_OP_PRESENT;
998 ret->u.present.attr = talloc_steal(ret, attr);
1000 if (!asn1_end_tag(data)) {
1001 goto failed;
1003 break;
1005 case 8: {
1006 /* approx */
1007 const char *attrib;
1008 DATA_BLOB value;
1010 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
1011 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
1012 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
1013 if (!asn1_end_tag(data)) goto failed;
1014 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1015 goto failed;
1018 ret->operation = LDB_OP_APPROX;
1019 ret->u.comparison.attr = talloc_steal(ret, attrib);
1020 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1021 ret->u.comparison.value.length = value.length;
1022 break;
1024 case 9: {
1025 char *oid = NULL, *attr = NULL, *value;
1026 uint8_t dnAttributes;
1027 /* an extended search */
1028 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1029 goto failed;
1032 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1033 we need to check we properly implement --SSS */
1034 /* either oid or type must be defined */
1035 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1036 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
1037 if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
1038 if (!asn1_end_tag(data)) goto failed;
1040 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1041 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
1042 if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
1043 if (!asn1_end_tag(data)) goto failed;
1045 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
1046 if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
1047 if (!asn1_end_tag(data)) goto failed;
1048 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1049 it is not marked as OPTIONAL but openldap tools
1050 do not set this unless it is to be set as TRUE
1051 NOTE: openldap tools do not work with AD as it
1052 seems that AD always requires the dnAttributes
1053 boolean value to be set */
1054 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1055 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
1056 if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
1057 if (!asn1_end_tag(data)) goto failed;
1058 } else {
1059 dnAttributes = 0;
1061 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1062 goto failed;
1065 if (oid) {
1066 ret->operation = LDB_OP_EXTENDED;
1068 /* From the RFC2251: If the type field is
1069 absent and matchingRule is present, the matchValue is compared
1070 against all attributes in an entry which support that matchingRule
1072 if (attr) {
1073 ret->u.extended.attr = talloc_steal(ret, attr);
1074 } else {
1075 ret->u.extended.attr = talloc_strdup(ret, "*");
1077 ret->u.extended.rule_id = talloc_steal(ret, oid);
1078 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1079 ret->u.extended.value.length = strlen(value);
1080 ret->u.extended.dnAttributes = dnAttributes;
1081 } else {
1082 ret->operation = LDB_OP_EQUALITY;
1083 ret->u.equality.attr = talloc_steal(ret, attr);
1084 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1085 ret->u.equality.value.length = strlen(value);
1087 if (!asn1_end_tag(data)) {
1088 goto failed;
1090 break;
1093 default:
1094 goto failed;
1097 return ret;
1099 failed:
1100 talloc_free(ret);
1101 return NULL;
1104 /* Decode a single LDAP attribute, possibly containing multiple values */
1105 static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1106 struct ldb_message_element *attrib)
1108 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1109 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
1110 if (!asn1_start_tag(data, ASN1_SET)) return false;
1111 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1112 DATA_BLOB blob;
1113 if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
1114 add_value_to_attrib(mem_ctx, &blob, attrib);
1116 if (!asn1_end_tag(data)) return false;
1117 return asn1_end_tag(data);
1120 /* Decode a set of LDAP attributes, as found in the dereference control */
1121 bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1122 struct ldb_message_element **attributes,
1123 int *num_attributes)
1125 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1126 struct ldb_message_element attrib;
1127 ZERO_STRUCT(attrib);
1128 if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
1129 add_attrib_to_array_talloc(mem_ctx, &attrib,
1130 attributes, num_attributes);
1132 return true;
1135 /* Decode a set of LDAP attributes, as found in a search entry */
1136 static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1137 struct ldb_message_element **attributes,
1138 int *num_attributes)
1140 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1141 if (!ldap_decode_attribs_bare(mem_ctx, data,
1142 attributes, num_attributes)) return false;
1143 return asn1_end_tag(data);
1146 /* This routine returns LDAP status codes */
1148 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1149 const struct ldap_control_handler *control_handlers,
1150 struct ldap_message *msg)
1152 uint8_t tag;
1154 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1155 if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
1157 if (!asn1_peek_uint8(data, &tag)) goto prot_err;
1159 switch(tag) {
1161 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1162 struct ldap_BindRequest *r = &msg->r.BindRequest;
1163 msg->type = LDAP_TAG_BindRequest;
1164 if (!asn1_start_tag(data, tag)) goto prot_err;
1165 if (!asn1_read_Integer(data, &r->version)) goto prot_err;
1166 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1167 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1168 int pwlen;
1169 r->creds.password = "";
1170 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1171 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1172 pwlen = asn1_tag_remaining(data);
1173 if (pwlen == -1) {
1174 goto prot_err;
1176 if (pwlen != 0) {
1177 char *pw = talloc_array(msg, char, pwlen+1);
1178 if (!pw) {
1179 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1181 if (!asn1_read(data, pw, pwlen)) goto prot_err;
1182 pw[pwlen] = '\0';
1183 r->creds.password = pw;
1185 if (!asn1_end_tag(data)) goto prot_err;
1186 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1187 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
1188 r->mechanism = LDAP_AUTH_MECH_SASL;
1189 if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
1190 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1191 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1192 if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
1193 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1194 if (!r->creds.SASL.secblob) {
1195 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1197 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1198 tmp_blob.data, tmp_blob.length);
1199 data_blob_free(&tmp_blob);
1200 } else {
1201 r->creds.SASL.secblob = NULL;
1203 if (!asn1_end_tag(data)) goto prot_err;
1204 } else {
1205 /* Neither Simple nor SASL bind */
1206 goto prot_err;
1208 if (!asn1_end_tag(data)) goto prot_err;
1209 break;
1212 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1213 struct ldap_BindResponse *r = &msg->r.BindResponse;
1214 msg->type = LDAP_TAG_BindResponse;
1215 if (!asn1_start_tag(data, tag)) goto prot_err;
1216 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1217 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1218 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1219 if (!asn1_read_ContextSimple(data, 7, &tmp_blob)) goto prot_err;
1220 r->SASL.secblob = talloc(msg, DATA_BLOB);
1221 if (!r->SASL.secblob) {
1222 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1224 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1225 tmp_blob.data, tmp_blob.length);
1226 data_blob_free(&tmp_blob);
1227 } else {
1228 r->SASL.secblob = NULL;
1230 if (!asn1_end_tag(data)) goto prot_err;
1231 break;
1234 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1235 msg->type = LDAP_TAG_UnbindRequest;
1236 if (!asn1_start_tag(data, tag)) goto prot_err;
1237 if (!asn1_end_tag(data)) goto prot_err;
1238 break;
1241 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1242 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1243 int sizelimit, timelimit;
1244 const char **attrs = NULL;
1245 msg->type = LDAP_TAG_SearchRequest;
1246 if (!asn1_start_tag(data, tag)) goto prot_err;
1247 if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
1248 if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
1249 if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
1250 if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
1251 r->sizelimit = sizelimit;
1252 if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
1253 r->timelimit = timelimit;
1254 if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
1256 r->tree = ldap_decode_filter_tree(msg, data);
1257 if (r->tree == NULL) {
1258 goto prot_err;
1261 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1263 r->num_attributes = 0;
1264 r->attributes = NULL;
1266 while (asn1_tag_remaining(data) > 0) {
1268 const char *attr;
1269 if (!asn1_read_OctetString_talloc(msg, data,
1270 &attr))
1271 goto prot_err;
1272 if (!add_string_to_array(msg, attr,
1273 &attrs,
1274 &r->num_attributes))
1275 goto prot_err;
1277 r->attributes = attrs;
1279 if (!asn1_end_tag(data)) goto prot_err;
1280 if (!asn1_end_tag(data)) goto prot_err;
1281 break;
1284 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1285 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1286 msg->type = LDAP_TAG_SearchResultEntry;
1287 r->attributes = NULL;
1288 r->num_attributes = 0;
1289 if (!asn1_start_tag(data, tag)) goto prot_err;
1290 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1291 if (!ldap_decode_attribs(msg, data, &r->attributes,
1292 &r->num_attributes)) goto prot_err;
1293 if (!asn1_end_tag(data)) goto prot_err;
1294 break;
1297 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1298 struct ldap_Result *r = &msg->r.SearchResultDone;
1299 msg->type = LDAP_TAG_SearchResultDone;
1300 if (!asn1_start_tag(data, tag)) goto prot_err;
1301 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1302 if (!asn1_end_tag(data)) goto prot_err;
1303 break;
1306 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1307 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1308 msg->type = LDAP_TAG_SearchResultReference;
1309 if (!asn1_start_tag(data, tag)) goto prot_err;
1310 if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
1311 if (!asn1_end_tag(data)) goto prot_err;
1312 break;
1315 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1316 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1317 msg->type = LDAP_TAG_ModifyRequest;
1318 if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
1319 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1320 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1322 r->num_mods = 0;
1323 r->mods = NULL;
1325 while (asn1_tag_remaining(data) > 0) {
1326 struct ldap_mod mod;
1327 int v;
1328 ZERO_STRUCT(mod);
1329 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1330 if (!asn1_read_enumerated(data, &v)) goto prot_err;
1331 mod.type = v;
1332 if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
1333 if (!asn1_end_tag(data)) goto prot_err;
1334 if (!add_mod_to_array_talloc(msg, &mod,
1335 &r->mods, &r->num_mods)) {
1336 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1340 if (!asn1_end_tag(data)) goto prot_err;
1341 if (!asn1_end_tag(data)) goto prot_err;
1342 break;
1345 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1346 struct ldap_Result *r = &msg->r.ModifyResponse;
1347 msg->type = LDAP_TAG_ModifyResponse;
1348 if (!asn1_start_tag(data, tag)) goto prot_err;
1349 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1350 if (!asn1_end_tag(data)) goto prot_err;
1351 break;
1354 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1355 struct ldap_AddRequest *r = &msg->r.AddRequest;
1356 msg->type = LDAP_TAG_AddRequest;
1357 if (!asn1_start_tag(data, tag)) goto prot_err;
1358 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1360 r->attributes = NULL;
1361 r->num_attributes = 0;
1362 if (!ldap_decode_attribs(msg, data, &r->attributes,
1363 &r->num_attributes)) goto prot_err;
1365 if (!asn1_end_tag(data)) goto prot_err;
1366 break;
1369 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1370 struct ldap_Result *r = &msg->r.AddResponse;
1371 msg->type = LDAP_TAG_AddResponse;
1372 if (!asn1_start_tag(data, tag)) goto prot_err;
1373 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1374 if (!asn1_end_tag(data)) goto prot_err;
1375 break;
1378 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1379 struct ldap_DelRequest *r = &msg->r.DelRequest;
1380 int len;
1381 char *dn;
1382 msg->type = LDAP_TAG_DelRequest;
1383 if (!asn1_start_tag(data,
1384 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
1385 len = asn1_tag_remaining(data);
1386 if (len == -1) {
1387 goto prot_err;
1389 dn = talloc_array(msg, char, len+1);
1390 if (dn == NULL)
1391 break;
1392 if (!asn1_read(data, dn, len)) goto prot_err;
1393 dn[len] = '\0';
1394 r->dn = dn;
1395 if (!asn1_end_tag(data)) goto prot_err;
1396 break;
1399 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1400 struct ldap_Result *r = &msg->r.DelResponse;
1401 msg->type = LDAP_TAG_DelResponse;
1402 if (!asn1_start_tag(data, tag)) goto prot_err;
1403 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1404 if (!asn1_end_tag(data)) goto prot_err;
1405 break;
1408 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1409 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1410 msg->type = LDAP_TAG_ModifyDNRequest;
1411 if (!asn1_start_tag(data,
1412 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
1413 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1414 if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
1415 if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
1416 r->newsuperior = NULL;
1417 if (asn1_tag_remaining(data) > 0) {
1418 int len;
1419 char *newsup;
1420 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1421 len = asn1_tag_remaining(data);
1422 if (len == -1) {
1423 goto prot_err;
1425 newsup = talloc_array(msg, char, len+1);
1426 if (newsup == NULL) {
1427 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1429 if (!asn1_read(data, newsup, len)) goto prot_err;
1430 newsup[len] = '\0';
1431 r->newsuperior = newsup;
1432 if (!asn1_end_tag(data)) goto prot_err;
1434 if (!asn1_end_tag(data)) goto prot_err;
1435 break;
1438 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1439 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1440 msg->type = LDAP_TAG_ModifyDNResponse;
1441 if (!asn1_start_tag(data, tag)) goto prot_err;
1442 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1443 if (!asn1_end_tag(data)) goto prot_err;
1444 break;
1447 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1448 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1449 msg->type = LDAP_TAG_CompareRequest;
1450 if (!asn1_start_tag(data,
1451 ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
1452 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1453 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1454 if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
1455 if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
1456 if (r->value.data) {
1457 talloc_steal(msg, r->value.data);
1459 if (!asn1_end_tag(data)) goto prot_err;
1460 if (!asn1_end_tag(data)) goto prot_err;
1461 break;
1464 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1465 struct ldap_Result *r = &msg->r.CompareResponse;
1466 msg->type = LDAP_TAG_CompareResponse;
1467 if (!asn1_start_tag(data, tag)) goto prot_err;
1468 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1469 if (!asn1_end_tag(data)) goto prot_err;
1470 break;
1473 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1474 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1475 msg->type = LDAP_TAG_AbandonRequest;
1476 if (!asn1_start_tag(data, tag)) goto prot_err;
1477 if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
1478 if (!asn1_end_tag(data)) goto prot_err;
1479 break;
1482 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1483 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1484 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1486 msg->type = LDAP_TAG_ExtendedRequest;
1487 if (!asn1_start_tag(data,tag)) goto prot_err;
1488 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1489 goto prot_err;
1491 r->oid = blob2string_talloc(msg, tmp_blob);
1492 data_blob_free(&tmp_blob);
1493 if (!r->oid) {
1494 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1497 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1498 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1499 r->value = talloc(msg, DATA_BLOB);
1500 if (!r->value) {
1501 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1503 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1504 data_blob_free(&tmp_blob);
1505 } else {
1506 r->value = NULL;
1509 if (!asn1_end_tag(data)) goto prot_err;
1510 break;
1513 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1514 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1515 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1517 msg->type = LDAP_TAG_ExtendedResponse;
1518 if (!asn1_start_tag(data, tag)) goto prot_err;
1519 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1521 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1522 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1523 r->oid = blob2string_talloc(msg, tmp_blob);
1524 data_blob_free(&tmp_blob);
1525 if (!r->oid) {
1526 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1528 } else {
1529 r->oid = NULL;
1532 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1533 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1534 r->value = talloc(msg, DATA_BLOB);
1535 if (!r->value) {
1536 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1538 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1539 data_blob_free(&tmp_blob);
1540 } else {
1541 r->value = NULL;
1544 if (!asn1_end_tag(data)) goto prot_err;
1545 break;
1547 default:
1548 goto prot_err;
1551 msg->controls = NULL;
1552 msg->controls_decoded = NULL;
1554 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1555 int i = 0;
1556 struct ldb_control **ctrl = NULL;
1557 bool *decoded = NULL;
1559 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
1561 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1562 DATA_BLOB value;
1563 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1565 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1566 if (!ctrl) {
1567 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1570 decoded = talloc_realloc(msg, decoded, bool, i+1);
1571 if (!decoded) {
1572 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1575 ctrl[i] = talloc(ctrl, struct ldb_control);
1576 if (!ctrl[i]) {
1577 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1580 if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1581 goto prot_err;
1584 if (!ldap_decode_control_value(ctrl[i], value,
1585 control_handlers,
1586 ctrl[i])) {
1587 if (ctrl[i]->critical) {
1588 ctrl[i]->data = NULL;
1589 decoded[i] = false;
1590 i++;
1591 } else {
1592 talloc_free(ctrl[i]);
1593 ctrl[i] = NULL;
1595 } else {
1596 decoded[i] = true;
1597 i++;
1601 if (ctrl != NULL) {
1602 ctrl[i] = NULL;
1605 msg->controls = ctrl;
1606 msg->controls_decoded = decoded;
1608 if (!asn1_end_tag(data)) goto prot_err;
1611 if (!asn1_end_tag(data)) goto prot_err;
1612 if ((data->has_error) || (data->nesting != NULL)) {
1613 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1615 return NT_STATUS_OK;
1617 prot_err:
1619 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1624 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1625 ldap packet. Set packet_size if true.
1627 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1629 if (blob.length < 6) {
1631 * We need at least 6 bytes to workout the length
1632 * of the pdu.
1634 return STATUS_MORE_ENTRIES;
1636 return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);