s3:smbd: add a fsp_persistent_id() function
[Samba.git] / libcli / ldap / ldap_message.c
blob7756e731b247fd08796c0303d228dd5eaf098d22
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 asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
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 asn1_pop_tag(data);
239 break;
241 case LDB_OP_NOT:
242 asn1_push_tag(data, ASN1_CONTEXT(2));
243 if (!ldap_push_filter(data, tree->u.isnot.child)) {
244 return false;
246 asn1_pop_tag(data);
247 break;
249 case LDB_OP_EQUALITY:
250 /* equality test */
251 asn1_push_tag(data, ASN1_CONTEXT(3));
252 asn1_write_OctetString(data, tree->u.equality.attr,
253 strlen(tree->u.equality.attr));
254 asn1_write_OctetString(data, tree->u.equality.value.data,
255 tree->u.equality.value.length);
256 asn1_pop_tag(data);
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 asn1_push_tag(data, ASN1_CONTEXT(4));
270 asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
271 asn1_push_tag(data, ASN1_SEQUENCE(0));
272 i = 0;
273 if ( ! tree->u.substring.start_with_wildcard) {
274 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
275 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
276 asn1_pop_tag(data);
277 i++;
279 while (tree->u.substring.chunks[i]) {
280 int ctx;
282 if (( ! tree->u.substring.chunks[i + 1]) &&
283 (tree->u.substring.end_with_wildcard == 0)) {
284 ctx = 2;
285 } else {
286 ctx = 1;
288 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
289 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
290 asn1_pop_tag(data);
291 i++;
293 asn1_pop_tag(data);
294 asn1_pop_tag(data);
295 break;
297 case LDB_OP_GREATER:
298 /* greaterOrEqual test */
299 asn1_push_tag(data, ASN1_CONTEXT(5));
300 asn1_write_OctetString(data, tree->u.comparison.attr,
301 strlen(tree->u.comparison.attr));
302 asn1_write_OctetString(data, tree->u.comparison.value.data,
303 tree->u.comparison.value.length);
304 asn1_pop_tag(data);
305 break;
307 case LDB_OP_LESS:
308 /* lessOrEqual test */
309 asn1_push_tag(data, ASN1_CONTEXT(6));
310 asn1_write_OctetString(data, tree->u.comparison.attr,
311 strlen(tree->u.comparison.attr));
312 asn1_write_OctetString(data, tree->u.comparison.value.data,
313 tree->u.comparison.value.length);
314 asn1_pop_tag(data);
315 break;
317 case LDB_OP_PRESENT:
318 /* present test */
319 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
320 asn1_write_LDAPString(data, tree->u.present.attr);
321 asn1_pop_tag(data);
322 return !data->has_error;
324 case LDB_OP_APPROX:
325 /* approx test */
326 asn1_push_tag(data, ASN1_CONTEXT(8));
327 asn1_write_OctetString(data, tree->u.comparison.attr,
328 strlen(tree->u.comparison.attr));
329 asn1_write_OctetString(data, tree->u.comparison.value.data,
330 tree->u.comparison.value.length);
331 asn1_pop_tag(data);
332 break;
334 case LDB_OP_EXTENDED:
336 MatchingRuleAssertion ::= SEQUENCE {
337 matchingRule [1] MatchingRuleID OPTIONAL,
338 type [2] AttributeDescription OPTIONAL,
339 matchValue [3] AssertionValue,
340 dnAttributes [4] BOOLEAN DEFAULT FALSE
343 asn1_push_tag(data, ASN1_CONTEXT(9));
344 if (tree->u.extended.rule_id) {
345 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
346 asn1_write_LDAPString(data, tree->u.extended.rule_id);
347 asn1_pop_tag(data);
349 if (tree->u.extended.attr) {
350 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
351 asn1_write_LDAPString(data, tree->u.extended.attr);
352 asn1_pop_tag(data);
354 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
355 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
356 asn1_pop_tag(data);
357 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
358 asn1_write_uint8(data, tree->u.extended.dnAttributes);
359 asn1_pop_tag(data);
360 asn1_pop_tag(data);
361 break;
363 default:
364 return false;
366 return !data->has_error;
369 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
371 asn1_write_enumerated(data, result->resultcode);
372 asn1_write_OctetString(data, result->dn,
373 (result->dn) ? strlen(result->dn) : 0);
374 asn1_write_OctetString(data, result->errormessage,
375 (result->errormessage) ?
376 strlen(result->errormessage) : 0);
377 if (result->referral) {
378 asn1_push_tag(data, ASN1_CONTEXT(3));
379 asn1_write_OctetString(data, result->referral,
380 strlen(result->referral));
381 asn1_pop_tag(data);
385 _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
386 const struct ldap_control_handler *control_handlers,
387 DATA_BLOB *result, TALLOC_CTX *mem_ctx)
389 struct asn1_data *data = asn1_init(mem_ctx);
390 int i, j;
392 if (!data) return false;
394 asn1_push_tag(data, ASN1_SEQUENCE(0));
395 asn1_write_Integer(data, msg->messageid);
397 switch (msg->type) {
398 case LDAP_TAG_BindRequest: {
399 struct ldap_BindRequest *r = &msg->r.BindRequest;
400 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
401 asn1_write_Integer(data, r->version);
402 asn1_write_OctetString(data, r->dn,
403 (r->dn != NULL) ? strlen(r->dn) : 0);
405 switch (r->mechanism) {
406 case LDAP_AUTH_MECH_SIMPLE:
407 /* context, primitive */
408 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
409 asn1_write(data, r->creds.password,
410 strlen(r->creds.password));
411 asn1_pop_tag(data);
412 break;
413 case LDAP_AUTH_MECH_SASL:
414 /* context, constructed */
415 asn1_push_tag(data, ASN1_CONTEXT(3));
416 asn1_write_OctetString(data, r->creds.SASL.mechanism,
417 strlen(r->creds.SASL.mechanism));
418 if (r->creds.SASL.secblob) {
419 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
420 r->creds.SASL.secblob->length);
422 asn1_pop_tag(data);
423 break;
424 default:
425 return false;
428 asn1_pop_tag(data);
429 break;
431 case LDAP_TAG_BindResponse: {
432 struct ldap_BindResponse *r = &msg->r.BindResponse;
433 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
434 ldap_encode_response(data, &r->response);
435 if (r->SASL.secblob) {
436 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
438 asn1_pop_tag(data);
439 break;
441 case LDAP_TAG_UnbindRequest: {
442 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
443 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
444 asn1_pop_tag(data);
445 break;
447 case LDAP_TAG_SearchRequest: {
448 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
449 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
450 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
451 asn1_write_enumerated(data, r->scope);
452 asn1_write_enumerated(data, r->deref);
453 asn1_write_Integer(data, r->sizelimit);
454 asn1_write_Integer(data, r->timelimit);
455 asn1_write_BOOLEAN(data, r->attributesonly);
457 if (!ldap_push_filter(data, r->tree)) {
458 return false;
461 asn1_push_tag(data, ASN1_SEQUENCE(0));
462 for (i=0; i<r->num_attributes; i++) {
463 asn1_write_OctetString(data, r->attributes[i],
464 strlen(r->attributes[i]));
466 asn1_pop_tag(data);
467 asn1_pop_tag(data);
468 break;
470 case LDAP_TAG_SearchResultEntry: {
471 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
472 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
473 asn1_write_OctetString(data, r->dn, strlen(r->dn));
474 asn1_push_tag(data, ASN1_SEQUENCE(0));
475 for (i=0; i<r->num_attributes; i++) {
476 struct ldb_message_element *attr = &r->attributes[i];
477 asn1_push_tag(data, ASN1_SEQUENCE(0));
478 asn1_write_OctetString(data, attr->name,
479 strlen(attr->name));
480 asn1_push_tag(data, ASN1_SEQUENCE(1));
481 for (j=0; j<attr->num_values; j++) {
482 asn1_write_OctetString(data,
483 attr->values[j].data,
484 attr->values[j].length);
486 asn1_pop_tag(data);
487 asn1_pop_tag(data);
489 asn1_pop_tag(data);
490 asn1_pop_tag(data);
491 break;
493 case LDAP_TAG_SearchResultDone: {
494 struct ldap_Result *r = &msg->r.SearchResultDone;
495 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
496 ldap_encode_response(data, r);
497 asn1_pop_tag(data);
498 break;
500 case LDAP_TAG_ModifyRequest: {
501 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
502 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
503 asn1_write_OctetString(data, r->dn, strlen(r->dn));
504 asn1_push_tag(data, ASN1_SEQUENCE(0));
506 for (i=0; i<r->num_mods; i++) {
507 struct ldb_message_element *attrib = &r->mods[i].attrib;
508 asn1_push_tag(data, ASN1_SEQUENCE(0));
509 asn1_write_enumerated(data, r->mods[i].type);
510 asn1_push_tag(data, ASN1_SEQUENCE(0));
511 asn1_write_OctetString(data, attrib->name,
512 strlen(attrib->name));
513 asn1_push_tag(data, ASN1_SET);
514 for (j=0; j<attrib->num_values; j++) {
515 asn1_write_OctetString(data,
516 attrib->values[j].data,
517 attrib->values[j].length);
520 asn1_pop_tag(data);
521 asn1_pop_tag(data);
522 asn1_pop_tag(data);
525 asn1_pop_tag(data);
526 asn1_pop_tag(data);
527 break;
529 case LDAP_TAG_ModifyResponse: {
530 struct ldap_Result *r = &msg->r.ModifyResponse;
531 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
532 ldap_encode_response(data, r);
533 asn1_pop_tag(data);
534 break;
536 case LDAP_TAG_AddRequest: {
537 struct ldap_AddRequest *r = &msg->r.AddRequest;
538 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
539 asn1_write_OctetString(data, r->dn, strlen(r->dn));
540 asn1_push_tag(data, ASN1_SEQUENCE(0));
542 for (i=0; i<r->num_attributes; i++) {
543 struct ldb_message_element *attrib = &r->attributes[i];
544 asn1_push_tag(data, ASN1_SEQUENCE(0));
545 asn1_write_OctetString(data, attrib->name,
546 strlen(attrib->name));
547 asn1_push_tag(data, ASN1_SET);
548 for (j=0; j<r->attributes[i].num_values; j++) {
549 asn1_write_OctetString(data,
550 attrib->values[j].data,
551 attrib->values[j].length);
553 asn1_pop_tag(data);
554 asn1_pop_tag(data);
556 asn1_pop_tag(data);
557 asn1_pop_tag(data);
558 break;
560 case LDAP_TAG_AddResponse: {
561 struct ldap_Result *r = &msg->r.AddResponse;
562 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
563 ldap_encode_response(data, r);
564 asn1_pop_tag(data);
565 break;
567 case LDAP_TAG_DelRequest: {
568 struct ldap_DelRequest *r = &msg->r.DelRequest;
569 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
570 asn1_write(data, r->dn, strlen(r->dn));
571 asn1_pop_tag(data);
572 break;
574 case LDAP_TAG_DelResponse: {
575 struct ldap_Result *r = &msg->r.DelResponse;
576 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
577 ldap_encode_response(data, r);
578 asn1_pop_tag(data);
579 break;
581 case LDAP_TAG_ModifyDNRequest: {
582 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
583 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
584 asn1_write_OctetString(data, r->dn, strlen(r->dn));
585 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
586 asn1_write_BOOLEAN(data, r->deleteolddn);
587 if (r->newsuperior) {
588 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
589 asn1_write(data, r->newsuperior,
590 strlen(r->newsuperior));
591 asn1_pop_tag(data);
593 asn1_pop_tag(data);
594 break;
596 case LDAP_TAG_ModifyDNResponse: {
597 struct ldap_Result *r = &msg->r.ModifyDNResponse;
598 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
599 ldap_encode_response(data, r);
600 asn1_pop_tag(data);
601 break;
603 case LDAP_TAG_CompareRequest: {
604 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
605 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
606 asn1_write_OctetString(data, r->dn, strlen(r->dn));
607 asn1_push_tag(data, ASN1_SEQUENCE(0));
608 asn1_write_OctetString(data, r->attribute,
609 strlen(r->attribute));
610 asn1_write_OctetString(data, r->value.data,
611 r->value.length);
612 asn1_pop_tag(data);
613 asn1_pop_tag(data);
614 break;
616 case LDAP_TAG_CompareResponse: {
617 struct ldap_Result *r = &msg->r.ModifyDNResponse;
618 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
619 ldap_encode_response(data, r);
620 asn1_pop_tag(data);
621 break;
623 case LDAP_TAG_AbandonRequest: {
624 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
625 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
626 asn1_write_implicit_Integer(data, r->messageid);
627 asn1_pop_tag(data);
628 break;
630 case LDAP_TAG_SearchResultReference: {
631 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
632 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
633 asn1_write_OctetString(data, r->referral, strlen(r->referral));
634 asn1_pop_tag(data);
635 break;
637 case LDAP_TAG_ExtendedRequest: {
638 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
639 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
640 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
641 asn1_write(data, r->oid, strlen(r->oid));
642 asn1_pop_tag(data);
643 if (r->value) {
644 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
645 asn1_write(data, r->value->data, r->value->length);
646 asn1_pop_tag(data);
648 asn1_pop_tag(data);
649 break;
651 case LDAP_TAG_ExtendedResponse: {
652 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
653 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
654 ldap_encode_response(data, &r->response);
655 if (r->oid) {
656 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
657 asn1_write(data, r->oid, strlen(r->oid));
658 asn1_pop_tag(data);
660 if (r->value) {
661 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
662 asn1_write(data, r->value->data, r->value->length);
663 asn1_pop_tag(data);
665 asn1_pop_tag(data);
666 break;
668 default:
669 return false;
672 if (msg->controls != NULL) {
673 asn1_push_tag(data, ASN1_CONTEXT(0));
675 for (i = 0; msg->controls[i] != NULL; i++) {
676 if (!ldap_encode_control(mem_ctx, data,
677 control_handlers,
678 msg->controls[i])) {
679 DEBUG(1,("Unable to encode control %s\n",
680 msg->controls[i]->oid));
681 return false;
685 asn1_pop_tag(data);
688 asn1_pop_tag(data);
690 if (data->has_error) {
691 asn1_free(data);
692 return false;
695 *result = data_blob_talloc(mem_ctx, data->data, data->length);
696 asn1_free(data);
697 return true;
700 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
701 DATA_BLOB blob)
703 char *result = talloc_array(mem_ctx, char, blob.length+1);
704 memcpy(result, blob.data, blob.length);
705 result[blob.length] = '\0';
706 return result;
709 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
710 struct asn1_data *data,
711 const char **result)
713 DATA_BLOB string;
714 if (!asn1_read_OctetString(data, mem_ctx, &string))
715 return false;
716 *result = blob2string_talloc(mem_ctx, string);
717 data_blob_free(&string);
718 return true;
721 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
722 struct asn1_data *data,
723 struct ldap_Result *result)
725 asn1_read_enumerated(data, &result->resultcode);
726 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
727 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
728 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
729 asn1_start_tag(data, ASN1_CONTEXT(3));
730 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
731 asn1_end_tag(data);
732 } else {
733 result->referral = NULL;
737 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
740 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
741 if (chunks == NULL) {
742 return NULL;
745 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
746 if (chunks[chunk_num] == NULL) {
747 return NULL;
750 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
751 if (chunks[chunk_num]->data == NULL) {
752 return NULL;
754 chunks[chunk_num]->length = strlen(value);
756 chunks[chunk_num + 1] = '\0';
758 return chunks;
763 parse the ASN.1 formatted search string into a ldb_parse_tree
765 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
766 struct asn1_data *data)
768 uint8_t filter_tag;
769 struct ldb_parse_tree *ret;
771 if (!asn1_peek_uint8(data, &filter_tag)) {
772 return NULL;
775 filter_tag &= 0x1f; /* strip off the asn1 stuff */
777 ret = talloc(mem_ctx, struct ldb_parse_tree);
778 if (ret == NULL) return NULL;
780 switch(filter_tag) {
781 case 0:
782 case 1:
783 /* AND or OR of one or more filters */
784 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
785 ret->u.list.num_elements = 0;
786 ret->u.list.elements = NULL;
788 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
789 goto failed;
792 while (asn1_tag_remaining(data) > 0) {
793 struct ldb_parse_tree *subtree;
794 subtree = ldap_decode_filter_tree(ret, data);
795 if (subtree == NULL) {
796 goto failed;
798 ret->u.list.elements =
799 talloc_realloc(ret, ret->u.list.elements,
800 struct ldb_parse_tree *,
801 ret->u.list.num_elements+1);
802 if (ret->u.list.elements == NULL) {
803 goto failed;
805 talloc_steal(ret->u.list.elements, subtree);
806 ret->u.list.elements[ret->u.list.num_elements] = subtree;
807 ret->u.list.num_elements++;
809 if (!asn1_end_tag(data)) {
810 goto failed;
812 break;
814 case 2:
815 /* 'not' operation */
816 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
817 goto failed;
820 ret->operation = LDB_OP_NOT;
821 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
822 if (ret->u.isnot.child == NULL) {
823 goto failed;
825 if (!asn1_end_tag(data)) {
826 goto failed;
828 break;
830 case 3: {
831 /* equalityMatch */
832 const char *attrib;
833 DATA_BLOB value;
835 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
836 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
837 asn1_read_OctetString(data, mem_ctx, &value);
838 asn1_end_tag(data);
839 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
840 goto failed;
843 ret->operation = LDB_OP_EQUALITY;
844 ret->u.equality.attr = talloc_steal(ret, attrib);
845 ret->u.equality.value.data = talloc_steal(ret, value.data);
846 ret->u.equality.value.length = value.length;
847 break;
849 case 4: {
850 /* substrings */
851 DATA_BLOB attr;
852 uint8_t subs_tag;
853 char *value;
854 int chunk_num = 0;
856 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
857 goto failed;
859 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
860 goto failed;
863 ret->operation = LDB_OP_SUBSTRING;
864 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
865 ret->u.substring.chunks = NULL;
866 ret->u.substring.start_with_wildcard = 1;
867 ret->u.substring.end_with_wildcard = 1;
869 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
870 goto failed;
873 while (asn1_tag_remaining(data)) {
874 asn1_peek_uint8(data, &subs_tag);
875 subs_tag &= 0x1f; /* strip off the asn1 stuff */
876 if (subs_tag > 2) goto failed;
878 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
879 asn1_read_LDAPString(data, mem_ctx, &value);
880 asn1_end_tag(data);
882 switch (subs_tag) {
883 case 0:
884 if (ret->u.substring.chunks != NULL) {
885 /* initial value found in the middle */
886 goto failed;
889 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
890 if (ret->u.substring.chunks == NULL) {
891 goto failed;
894 ret->u.substring.start_with_wildcard = 0;
895 chunk_num = 1;
896 break;
898 case 1:
899 if (ret->u.substring.end_with_wildcard == 0) {
900 /* "any" value found after a "final" value */
901 goto failed;
904 ret->u.substring.chunks = ldap_decode_substring(ret,
905 ret->u.substring.chunks,
906 chunk_num,
907 value);
908 if (ret->u.substring.chunks == NULL) {
909 goto failed;
912 chunk_num++;
913 break;
915 case 2:
916 ret->u.substring.chunks = ldap_decode_substring(ret,
917 ret->u.substring.chunks,
918 chunk_num,
919 value);
920 if (ret->u.substring.chunks == NULL) {
921 goto failed;
924 ret->u.substring.end_with_wildcard = 0;
925 break;
927 default:
928 goto failed;
933 if (!asn1_end_tag(data)) { /* SEQUENCE */
934 goto failed;
937 if (!asn1_end_tag(data)) {
938 goto failed;
940 break;
942 case 5: {
943 /* greaterOrEqual */
944 const char *attrib;
945 DATA_BLOB value;
947 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
948 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
949 asn1_read_OctetString(data, mem_ctx, &value);
950 asn1_end_tag(data);
951 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
952 goto failed;
955 ret->operation = LDB_OP_GREATER;
956 ret->u.comparison.attr = talloc_steal(ret, attrib);
957 ret->u.comparison.value.data = talloc_steal(ret, value.data);
958 ret->u.comparison.value.length = value.length;
959 break;
961 case 6: {
962 /* lessOrEqual */
963 const char *attrib;
964 DATA_BLOB value;
966 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
967 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
968 asn1_read_OctetString(data, mem_ctx, &value);
969 asn1_end_tag(data);
970 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
971 goto failed;
974 ret->operation = LDB_OP_LESS;
975 ret->u.comparison.attr = talloc_steal(ret, attrib);
976 ret->u.comparison.value.data = talloc_steal(ret, value.data);
977 ret->u.comparison.value.length = value.length;
978 break;
980 case 7: {
981 /* Normal presence, "attribute=*" */
982 char *attr;
984 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
985 goto failed;
987 if (!asn1_read_LDAPString(data, ret, &attr)) {
988 goto failed;
991 ret->operation = LDB_OP_PRESENT;
992 ret->u.present.attr = talloc_steal(ret, attr);
994 if (!asn1_end_tag(data)) {
995 goto failed;
997 break;
999 case 8: {
1000 /* approx */
1001 const char *attrib;
1002 DATA_BLOB value;
1004 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
1005 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
1006 asn1_read_OctetString(data, mem_ctx, &value);
1007 asn1_end_tag(data);
1008 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1009 goto failed;
1012 ret->operation = LDB_OP_APPROX;
1013 ret->u.comparison.attr = talloc_steal(ret, attrib);
1014 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1015 ret->u.comparison.value.length = value.length;
1016 break;
1018 case 9: {
1019 char *oid = NULL, *attr = NULL, *value;
1020 uint8_t dnAttributes;
1021 /* an extended search */
1022 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1023 goto failed;
1026 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1027 we need to check we properly implement --SSS */
1028 /* either oid or type must be defined */
1029 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1030 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1031 asn1_read_LDAPString(data, ret, &oid);
1032 asn1_end_tag(data);
1034 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1035 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1036 asn1_read_LDAPString(data, ret, &attr);
1037 asn1_end_tag(data);
1039 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1040 asn1_read_LDAPString(data, ret, &value);
1041 asn1_end_tag(data);
1042 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1043 it is not marked as OPTIONAL but openldap tools
1044 do not set this unless it is to be set as TRUE
1045 NOTE: openldap tools do not work with AD as it
1046 seems that AD always requires the dnAttributes
1047 boolean value to be set */
1048 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1049 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1050 asn1_read_uint8(data, &dnAttributes);
1051 asn1_end_tag(data);
1052 } else {
1053 dnAttributes = 0;
1055 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1056 goto failed;
1059 if (oid) {
1060 ret->operation = LDB_OP_EXTENDED;
1062 /* From the RFC2251: If the type field is
1063 absent and matchingRule is present, the matchValue is compared
1064 against all attributes in an entry which support that matchingRule
1066 if (attr) {
1067 ret->u.extended.attr = talloc_steal(ret, attr);
1068 } else {
1069 ret->u.extended.attr = talloc_strdup(ret, "*");
1071 ret->u.extended.rule_id = talloc_steal(ret, oid);
1072 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1073 ret->u.extended.value.length = strlen(value);
1074 ret->u.extended.dnAttributes = dnAttributes;
1075 } else {
1076 ret->operation = LDB_OP_EQUALITY;
1077 ret->u.equality.attr = talloc_steal(ret, attr);
1078 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1079 ret->u.equality.value.length = strlen(value);
1081 if (!asn1_end_tag(data)) {
1082 goto failed;
1084 break;
1087 default:
1088 goto failed;
1091 return ret;
1093 failed:
1094 talloc_free(ret);
1095 return NULL;
1098 /* Decode a single LDAP attribute, possibly containing multiple values */
1099 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1100 struct ldb_message_element *attrib)
1102 asn1_start_tag(data, ASN1_SEQUENCE(0));
1103 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1104 asn1_start_tag(data, ASN1_SET);
1105 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1106 DATA_BLOB blob;
1107 asn1_read_OctetString(data, mem_ctx, &blob);
1108 add_value_to_attrib(mem_ctx, &blob, attrib);
1110 asn1_end_tag(data);
1111 asn1_end_tag(data);
1115 /* Decode a set of LDAP attributes, as found in the dereference control */
1116 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1117 struct ldb_message_element **attributes,
1118 int *num_attributes)
1120 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1121 struct ldb_message_element attrib;
1122 ZERO_STRUCT(attrib);
1123 ldap_decode_attrib(mem_ctx, data, &attrib);
1124 add_attrib_to_array_talloc(mem_ctx, &attrib,
1125 attributes, num_attributes);
1129 /* Decode a set of LDAP attributes, as found in a search entry */
1130 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1131 struct ldb_message_element **attributes,
1132 int *num_attributes)
1134 asn1_start_tag(data, ASN1_SEQUENCE(0));
1135 ldap_decode_attribs_bare(mem_ctx, data,
1136 attributes, num_attributes);
1137 asn1_end_tag(data);
1140 /* This routine returns LDAP status codes */
1142 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1143 const struct ldap_control_handler *control_handlers,
1144 struct ldap_message *msg)
1146 uint8_t tag;
1148 asn1_start_tag(data, ASN1_SEQUENCE(0));
1149 asn1_read_Integer(data, &msg->messageid);
1151 if (!asn1_peek_uint8(data, &tag))
1152 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1154 switch(tag) {
1156 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1157 struct ldap_BindRequest *r = &msg->r.BindRequest;
1158 msg->type = LDAP_TAG_BindRequest;
1159 asn1_start_tag(data, tag);
1160 asn1_read_Integer(data, &r->version);
1161 asn1_read_OctetString_talloc(msg, data, &r->dn);
1162 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1163 int pwlen;
1164 r->creds.password = "";
1165 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1166 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1167 pwlen = asn1_tag_remaining(data);
1168 if (pwlen == -1) {
1169 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1171 if (pwlen != 0) {
1172 char *pw = talloc_array(msg, char, pwlen+1);
1173 if (!pw) {
1174 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1176 asn1_read(data, pw, pwlen);
1177 pw[pwlen] = '\0';
1178 r->creds.password = pw;
1180 asn1_end_tag(data);
1181 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1182 asn1_start_tag(data, ASN1_CONTEXT(3));
1183 r->mechanism = LDAP_AUTH_MECH_SASL;
1184 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1185 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1186 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1187 asn1_read_OctetString(data, msg, &tmp_blob);
1188 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1189 if (!r->creds.SASL.secblob) {
1190 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1192 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1193 tmp_blob.data, tmp_blob.length);
1194 data_blob_free(&tmp_blob);
1195 } else {
1196 r->creds.SASL.secblob = NULL;
1198 asn1_end_tag(data);
1199 } else {
1200 /* Neither Simple nor SASL bind */
1201 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1203 asn1_end_tag(data);
1204 break;
1207 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1208 struct ldap_BindResponse *r = &msg->r.BindResponse;
1209 msg->type = LDAP_TAG_BindResponse;
1210 asn1_start_tag(data, tag);
1211 ldap_decode_response(msg, data, &r->response);
1212 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1213 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1214 asn1_read_ContextSimple(data, 7, &tmp_blob);
1215 r->SASL.secblob = talloc(msg, DATA_BLOB);
1216 if (!r->SASL.secblob) {
1217 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1219 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1220 tmp_blob.data, tmp_blob.length);
1221 data_blob_free(&tmp_blob);
1222 } else {
1223 r->SASL.secblob = NULL;
1225 asn1_end_tag(data);
1226 break;
1229 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1230 msg->type = LDAP_TAG_UnbindRequest;
1231 asn1_start_tag(data, tag);
1232 asn1_end_tag(data);
1233 break;
1236 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1237 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1238 int sizelimit, timelimit;
1239 const char **attrs = NULL;
1240 msg->type = LDAP_TAG_SearchRequest;
1241 asn1_start_tag(data, tag);
1242 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1243 asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1244 asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1245 asn1_read_Integer(data, &sizelimit);
1246 r->sizelimit = sizelimit;
1247 asn1_read_Integer(data, &timelimit);
1248 r->timelimit = timelimit;
1249 asn1_read_BOOLEAN(data, &r->attributesonly);
1251 r->tree = ldap_decode_filter_tree(msg, data);
1252 if (r->tree == NULL) {
1253 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1256 asn1_start_tag(data, ASN1_SEQUENCE(0));
1258 r->num_attributes = 0;
1259 r->attributes = NULL;
1261 while (asn1_tag_remaining(data) > 0) {
1263 const char *attr;
1264 if (!asn1_read_OctetString_talloc(msg, data,
1265 &attr))
1266 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1267 if (!add_string_to_array(msg, attr,
1268 &attrs,
1269 &r->num_attributes))
1270 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1272 r->attributes = attrs;
1274 asn1_end_tag(data);
1275 asn1_end_tag(data);
1276 break;
1279 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1280 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1281 msg->type = LDAP_TAG_SearchResultEntry;
1282 r->attributes = NULL;
1283 r->num_attributes = 0;
1284 asn1_start_tag(data, tag);
1285 asn1_read_OctetString_talloc(msg, data, &r->dn);
1286 ldap_decode_attribs(msg, data, &r->attributes,
1287 &r->num_attributes);
1288 asn1_end_tag(data);
1289 break;
1292 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1293 struct ldap_Result *r = &msg->r.SearchResultDone;
1294 msg->type = LDAP_TAG_SearchResultDone;
1295 asn1_start_tag(data, tag);
1296 ldap_decode_response(msg, data, r);
1297 asn1_end_tag(data);
1298 break;
1301 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1302 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1303 msg->type = LDAP_TAG_SearchResultReference;
1304 asn1_start_tag(data, tag);
1305 asn1_read_OctetString_talloc(msg, data, &r->referral);
1306 asn1_end_tag(data);
1307 break;
1310 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1311 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1312 msg->type = LDAP_TAG_ModifyRequest;
1313 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1314 asn1_read_OctetString_talloc(msg, data, &r->dn);
1315 asn1_start_tag(data, ASN1_SEQUENCE(0));
1317 r->num_mods = 0;
1318 r->mods = NULL;
1320 while (asn1_tag_remaining(data) > 0) {
1321 struct ldap_mod mod;
1322 int v;
1323 ZERO_STRUCT(mod);
1324 asn1_start_tag(data, ASN1_SEQUENCE(0));
1325 asn1_read_enumerated(data, &v);
1326 mod.type = v;
1327 ldap_decode_attrib(msg, data, &mod.attrib);
1328 asn1_end_tag(data);
1329 if (!add_mod_to_array_talloc(msg, &mod,
1330 &r->mods, &r->num_mods)) {
1331 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1335 asn1_end_tag(data);
1336 asn1_end_tag(data);
1337 break;
1340 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1341 struct ldap_Result *r = &msg->r.ModifyResponse;
1342 msg->type = LDAP_TAG_ModifyResponse;
1343 asn1_start_tag(data, tag);
1344 ldap_decode_response(msg, data, r);
1345 asn1_end_tag(data);
1346 break;
1349 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1350 struct ldap_AddRequest *r = &msg->r.AddRequest;
1351 msg->type = LDAP_TAG_AddRequest;
1352 asn1_start_tag(data, tag);
1353 asn1_read_OctetString_talloc(msg, data, &r->dn);
1355 r->attributes = NULL;
1356 r->num_attributes = 0;
1357 ldap_decode_attribs(msg, data, &r->attributes,
1358 &r->num_attributes);
1360 asn1_end_tag(data);
1361 break;
1364 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1365 struct ldap_Result *r = &msg->r.AddResponse;
1366 msg->type = LDAP_TAG_AddResponse;
1367 asn1_start_tag(data, tag);
1368 ldap_decode_response(msg, data, r);
1369 asn1_end_tag(data);
1370 break;
1373 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1374 struct ldap_DelRequest *r = &msg->r.DelRequest;
1375 int len;
1376 char *dn;
1377 msg->type = LDAP_TAG_DelRequest;
1378 asn1_start_tag(data,
1379 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1380 len = asn1_tag_remaining(data);
1381 if (len == -1) {
1382 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1384 dn = talloc_array(msg, char, len+1);
1385 if (dn == NULL)
1386 break;
1387 asn1_read(data, dn, len);
1388 dn[len] = '\0';
1389 r->dn = dn;
1390 asn1_end_tag(data);
1391 break;
1394 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1395 struct ldap_Result *r = &msg->r.DelResponse;
1396 msg->type = LDAP_TAG_DelResponse;
1397 asn1_start_tag(data, tag);
1398 ldap_decode_response(msg, data, r);
1399 asn1_end_tag(data);
1400 break;
1403 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1404 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1405 msg->type = LDAP_TAG_ModifyDNRequest;
1406 asn1_start_tag(data,
1407 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1408 asn1_read_OctetString_talloc(msg, data, &r->dn);
1409 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1410 asn1_read_BOOLEAN(data, &r->deleteolddn);
1411 r->newsuperior = NULL;
1412 if (asn1_tag_remaining(data) > 0) {
1413 int len;
1414 char *newsup;
1415 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1416 len = asn1_tag_remaining(data);
1417 if (len == -1) {
1418 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1420 newsup = talloc_array(msg, char, len+1);
1421 if (newsup == NULL) {
1422 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1424 asn1_read(data, newsup, len);
1425 newsup[len] = '\0';
1426 r->newsuperior = newsup;
1427 asn1_end_tag(data);
1429 asn1_end_tag(data);
1430 break;
1433 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1434 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1435 msg->type = LDAP_TAG_ModifyDNResponse;
1436 asn1_start_tag(data, tag);
1437 ldap_decode_response(msg, data, r);
1438 asn1_end_tag(data);
1439 break;
1442 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1443 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1444 msg->type = LDAP_TAG_CompareRequest;
1445 asn1_start_tag(data,
1446 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1447 asn1_read_OctetString_talloc(msg, data, &r->dn);
1448 asn1_start_tag(data, ASN1_SEQUENCE(0));
1449 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1450 asn1_read_OctetString(data, msg, &r->value);
1451 if (r->value.data) {
1452 talloc_steal(msg, r->value.data);
1454 asn1_end_tag(data);
1455 asn1_end_tag(data);
1456 break;
1459 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1460 struct ldap_Result *r = &msg->r.CompareResponse;
1461 msg->type = LDAP_TAG_CompareResponse;
1462 asn1_start_tag(data, tag);
1463 ldap_decode_response(msg, data, r);
1464 asn1_end_tag(data);
1465 break;
1468 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1469 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1470 msg->type = LDAP_TAG_AbandonRequest;
1471 asn1_start_tag(data, tag);
1472 asn1_read_implicit_Integer(data, &r->messageid);
1473 asn1_end_tag(data);
1474 break;
1477 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1478 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1479 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1481 msg->type = LDAP_TAG_ExtendedRequest;
1482 asn1_start_tag(data,tag);
1483 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1484 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1486 r->oid = blob2string_talloc(msg, tmp_blob);
1487 data_blob_free(&tmp_blob);
1488 if (!r->oid) {
1489 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1492 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1493 asn1_read_ContextSimple(data, 1, &tmp_blob);
1494 r->value = talloc(msg, DATA_BLOB);
1495 if (!r->value) {
1496 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1498 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1499 data_blob_free(&tmp_blob);
1500 } else {
1501 r->value = NULL;
1504 asn1_end_tag(data);
1505 break;
1508 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1509 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1510 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1512 msg->type = LDAP_TAG_ExtendedResponse;
1513 asn1_start_tag(data, tag);
1514 ldap_decode_response(msg, data, &r->response);
1516 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1517 asn1_read_ContextSimple(data, 1, &tmp_blob);
1518 r->oid = blob2string_talloc(msg, tmp_blob);
1519 data_blob_free(&tmp_blob);
1520 if (!r->oid) {
1521 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1523 } else {
1524 r->oid = NULL;
1527 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1528 asn1_read_ContextSimple(data, 1, &tmp_blob);
1529 r->value = talloc(msg, DATA_BLOB);
1530 if (!r->value) {
1531 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1533 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1534 data_blob_free(&tmp_blob);
1535 } else {
1536 r->value = NULL;
1539 asn1_end_tag(data);
1540 break;
1542 default:
1543 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1546 msg->controls = NULL;
1547 msg->controls_decoded = NULL;
1549 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1550 int i = 0;
1551 struct ldb_control **ctrl = NULL;
1552 bool *decoded = NULL;
1554 asn1_start_tag(data, ASN1_CONTEXT(0));
1556 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1557 DATA_BLOB value;
1558 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1560 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1561 if (!ctrl) {
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1565 decoded = talloc_realloc(msg, decoded, bool, i+1);
1566 if (!decoded) {
1567 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1570 ctrl[i] = talloc(ctrl, struct ldb_control);
1571 if (!ctrl[i]) {
1572 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1575 if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1576 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1579 if (!ldap_decode_control_value(ctrl, value,
1580 control_handlers,
1581 ctrl[i])) {
1582 if (ctrl[i]->critical) {
1583 ctrl[i]->data = NULL;
1584 decoded[i] = false;
1585 i++;
1586 } else {
1587 talloc_free(ctrl[i]);
1588 ctrl[i] = NULL;
1590 } else {
1591 decoded[i] = true;
1592 i++;
1596 if (ctrl != NULL) {
1597 ctrl[i] = NULL;
1600 msg->controls = ctrl;
1601 msg->controls_decoded = decoded;
1603 asn1_end_tag(data);
1606 asn1_end_tag(data);
1607 if ((data->has_error) || (data->nesting != NULL)) {
1608 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1610 return NT_STATUS_OK;
1615 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1616 ldap packet. Set packet_size if true.
1618 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1620 if (blob.length < 6) {
1622 * We need at least 6 bytes to workout the length
1623 * of the pdu.
1625 return STATUS_MORE_ENTRIES;
1627 return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);