s3: modules: streaminfo: As we have no VFS function SMB_VFS_LLISTXATTR we can't cope...
[Samba.git] / libcli / ldap / ldap_message.c
blob1c5542c0d90b7d3106a2c92f4506fb77b692a2a4
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));
273 if (tree->u.substring.chunks && tree->u.substring.chunks[0]) {
274 i = 0;
275 if (!tree->u.substring.start_with_wildcard) {
276 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
277 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
278 asn1_pop_tag(data);
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 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
291 asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
292 asn1_pop_tag(data);
293 i++;
296 asn1_pop_tag(data);
297 asn1_pop_tag(data);
298 break;
300 case LDB_OP_GREATER:
301 /* greaterOrEqual test */
302 asn1_push_tag(data, ASN1_CONTEXT(5));
303 asn1_write_OctetString(data, tree->u.comparison.attr,
304 strlen(tree->u.comparison.attr));
305 asn1_write_OctetString(data, tree->u.comparison.value.data,
306 tree->u.comparison.value.length);
307 asn1_pop_tag(data);
308 break;
310 case LDB_OP_LESS:
311 /* lessOrEqual test */
312 asn1_push_tag(data, ASN1_CONTEXT(6));
313 asn1_write_OctetString(data, tree->u.comparison.attr,
314 strlen(tree->u.comparison.attr));
315 asn1_write_OctetString(data, tree->u.comparison.value.data,
316 tree->u.comparison.value.length);
317 asn1_pop_tag(data);
318 break;
320 case LDB_OP_PRESENT:
321 /* present test */
322 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
323 asn1_write_LDAPString(data, tree->u.present.attr);
324 asn1_pop_tag(data);
325 return !data->has_error;
327 case LDB_OP_APPROX:
328 /* approx test */
329 asn1_push_tag(data, ASN1_CONTEXT(8));
330 asn1_write_OctetString(data, tree->u.comparison.attr,
331 strlen(tree->u.comparison.attr));
332 asn1_write_OctetString(data, tree->u.comparison.value.data,
333 tree->u.comparison.value.length);
334 asn1_pop_tag(data);
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 asn1_push_tag(data, ASN1_CONTEXT(9));
347 if (tree->u.extended.rule_id) {
348 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
349 asn1_write_LDAPString(data, tree->u.extended.rule_id);
350 asn1_pop_tag(data);
352 if (tree->u.extended.attr) {
353 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
354 asn1_write_LDAPString(data, tree->u.extended.attr);
355 asn1_pop_tag(data);
357 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
358 asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
359 asn1_pop_tag(data);
360 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
361 asn1_write_uint8(data, tree->u.extended.dnAttributes);
362 asn1_pop_tag(data);
363 asn1_pop_tag(data);
364 break;
366 default:
367 return false;
369 return !data->has_error;
372 static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
374 asn1_write_enumerated(data, result->resultcode);
375 asn1_write_OctetString(data, result->dn,
376 (result->dn) ? strlen(result->dn) : 0);
377 asn1_write_OctetString(data, result->errormessage,
378 (result->errormessage) ?
379 strlen(result->errormessage) : 0);
380 if (result->referral) {
381 asn1_push_tag(data, ASN1_CONTEXT(3));
382 asn1_write_OctetString(data, result->referral,
383 strlen(result->referral));
384 asn1_pop_tag(data);
388 _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
389 const struct ldap_control_handler *control_handlers,
390 DATA_BLOB *result, TALLOC_CTX *mem_ctx)
392 struct asn1_data *data = asn1_init(mem_ctx);
393 int i, j;
395 if (!data) return false;
397 asn1_push_tag(data, ASN1_SEQUENCE(0));
398 asn1_write_Integer(data, msg->messageid);
400 switch (msg->type) {
401 case LDAP_TAG_BindRequest: {
402 struct ldap_BindRequest *r = &msg->r.BindRequest;
403 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
404 asn1_write_Integer(data, r->version);
405 asn1_write_OctetString(data, r->dn,
406 (r->dn != NULL) ? strlen(r->dn) : 0);
408 switch (r->mechanism) {
409 case LDAP_AUTH_MECH_SIMPLE:
410 /* context, primitive */
411 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
412 asn1_write(data, r->creds.password,
413 strlen(r->creds.password));
414 asn1_pop_tag(data);
415 break;
416 case LDAP_AUTH_MECH_SASL:
417 /* context, constructed */
418 asn1_push_tag(data, ASN1_CONTEXT(3));
419 asn1_write_OctetString(data, r->creds.SASL.mechanism,
420 strlen(r->creds.SASL.mechanism));
421 if (r->creds.SASL.secblob) {
422 asn1_write_OctetString(data, r->creds.SASL.secblob->data,
423 r->creds.SASL.secblob->length);
425 asn1_pop_tag(data);
426 break;
427 default:
428 return false;
431 asn1_pop_tag(data);
432 break;
434 case LDAP_TAG_BindResponse: {
435 struct ldap_BindResponse *r = &msg->r.BindResponse;
436 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
437 ldap_encode_response(data, &r->response);
438 if (r->SASL.secblob) {
439 asn1_write_ContextSimple(data, 7, r->SASL.secblob);
441 asn1_pop_tag(data);
442 break;
444 case LDAP_TAG_UnbindRequest: {
445 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
446 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
447 asn1_pop_tag(data);
448 break;
450 case LDAP_TAG_SearchRequest: {
451 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
452 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
453 asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
454 asn1_write_enumerated(data, r->scope);
455 asn1_write_enumerated(data, r->deref);
456 asn1_write_Integer(data, r->sizelimit);
457 asn1_write_Integer(data, r->timelimit);
458 asn1_write_BOOLEAN(data, r->attributesonly);
460 if (!ldap_push_filter(data, r->tree)) {
461 return false;
464 asn1_push_tag(data, ASN1_SEQUENCE(0));
465 for (i=0; i<r->num_attributes; i++) {
466 asn1_write_OctetString(data, r->attributes[i],
467 strlen(r->attributes[i]));
469 asn1_pop_tag(data);
470 asn1_pop_tag(data);
471 break;
473 case LDAP_TAG_SearchResultEntry: {
474 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
475 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
476 asn1_write_OctetString(data, r->dn, strlen(r->dn));
477 asn1_push_tag(data, ASN1_SEQUENCE(0));
478 for (i=0; i<r->num_attributes; i++) {
479 struct ldb_message_element *attr = &r->attributes[i];
480 asn1_push_tag(data, ASN1_SEQUENCE(0));
481 asn1_write_OctetString(data, attr->name,
482 strlen(attr->name));
483 asn1_push_tag(data, ASN1_SEQUENCE(1));
484 for (j=0; j<attr->num_values; j++) {
485 asn1_write_OctetString(data,
486 attr->values[j].data,
487 attr->values[j].length);
489 asn1_pop_tag(data);
490 asn1_pop_tag(data);
492 asn1_pop_tag(data);
493 asn1_pop_tag(data);
494 break;
496 case LDAP_TAG_SearchResultDone: {
497 struct ldap_Result *r = &msg->r.SearchResultDone;
498 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
499 ldap_encode_response(data, r);
500 asn1_pop_tag(data);
501 break;
503 case LDAP_TAG_ModifyRequest: {
504 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
505 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
506 asn1_write_OctetString(data, r->dn, strlen(r->dn));
507 asn1_push_tag(data, ASN1_SEQUENCE(0));
509 for (i=0; i<r->num_mods; i++) {
510 struct ldb_message_element *attrib = &r->mods[i].attrib;
511 asn1_push_tag(data, ASN1_SEQUENCE(0));
512 asn1_write_enumerated(data, r->mods[i].type);
513 asn1_push_tag(data, ASN1_SEQUENCE(0));
514 asn1_write_OctetString(data, attrib->name,
515 strlen(attrib->name));
516 asn1_push_tag(data, ASN1_SET);
517 for (j=0; j<attrib->num_values; j++) {
518 asn1_write_OctetString(data,
519 attrib->values[j].data,
520 attrib->values[j].length);
523 asn1_pop_tag(data);
524 asn1_pop_tag(data);
525 asn1_pop_tag(data);
528 asn1_pop_tag(data);
529 asn1_pop_tag(data);
530 break;
532 case LDAP_TAG_ModifyResponse: {
533 struct ldap_Result *r = &msg->r.ModifyResponse;
534 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
535 ldap_encode_response(data, r);
536 asn1_pop_tag(data);
537 break;
539 case LDAP_TAG_AddRequest: {
540 struct ldap_AddRequest *r = &msg->r.AddRequest;
541 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
542 asn1_write_OctetString(data, r->dn, strlen(r->dn));
543 asn1_push_tag(data, ASN1_SEQUENCE(0));
545 for (i=0; i<r->num_attributes; i++) {
546 struct ldb_message_element *attrib = &r->attributes[i];
547 asn1_push_tag(data, ASN1_SEQUENCE(0));
548 asn1_write_OctetString(data, attrib->name,
549 strlen(attrib->name));
550 asn1_push_tag(data, ASN1_SET);
551 for (j=0; j<r->attributes[i].num_values; j++) {
552 asn1_write_OctetString(data,
553 attrib->values[j].data,
554 attrib->values[j].length);
556 asn1_pop_tag(data);
557 asn1_pop_tag(data);
559 asn1_pop_tag(data);
560 asn1_pop_tag(data);
561 break;
563 case LDAP_TAG_AddResponse: {
564 struct ldap_Result *r = &msg->r.AddResponse;
565 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
566 ldap_encode_response(data, r);
567 asn1_pop_tag(data);
568 break;
570 case LDAP_TAG_DelRequest: {
571 struct ldap_DelRequest *r = &msg->r.DelRequest;
572 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
573 asn1_write(data, r->dn, strlen(r->dn));
574 asn1_pop_tag(data);
575 break;
577 case LDAP_TAG_DelResponse: {
578 struct ldap_Result *r = &msg->r.DelResponse;
579 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
580 ldap_encode_response(data, r);
581 asn1_pop_tag(data);
582 break;
584 case LDAP_TAG_ModifyDNRequest: {
585 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
586 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
587 asn1_write_OctetString(data, r->dn, strlen(r->dn));
588 asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
589 asn1_write_BOOLEAN(data, r->deleteolddn);
590 if (r->newsuperior) {
591 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
592 asn1_write(data, r->newsuperior,
593 strlen(r->newsuperior));
594 asn1_pop_tag(data);
596 asn1_pop_tag(data);
597 break;
599 case LDAP_TAG_ModifyDNResponse: {
600 struct ldap_Result *r = &msg->r.ModifyDNResponse;
601 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
602 ldap_encode_response(data, r);
603 asn1_pop_tag(data);
604 break;
606 case LDAP_TAG_CompareRequest: {
607 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
608 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
609 asn1_write_OctetString(data, r->dn, strlen(r->dn));
610 asn1_push_tag(data, ASN1_SEQUENCE(0));
611 asn1_write_OctetString(data, r->attribute,
612 strlen(r->attribute));
613 asn1_write_OctetString(data, r->value.data,
614 r->value.length);
615 asn1_pop_tag(data);
616 asn1_pop_tag(data);
617 break;
619 case LDAP_TAG_CompareResponse: {
620 struct ldap_Result *r = &msg->r.ModifyDNResponse;
621 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
622 ldap_encode_response(data, r);
623 asn1_pop_tag(data);
624 break;
626 case LDAP_TAG_AbandonRequest: {
627 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
628 asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
629 asn1_write_implicit_Integer(data, r->messageid);
630 asn1_pop_tag(data);
631 break;
633 case LDAP_TAG_SearchResultReference: {
634 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
635 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
636 asn1_write_OctetString(data, r->referral, strlen(r->referral));
637 asn1_pop_tag(data);
638 break;
640 case LDAP_TAG_ExtendedRequest: {
641 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
642 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
643 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
644 asn1_write(data, r->oid, strlen(r->oid));
645 asn1_pop_tag(data);
646 if (r->value) {
647 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
648 asn1_write(data, r->value->data, r->value->length);
649 asn1_pop_tag(data);
651 asn1_pop_tag(data);
652 break;
654 case LDAP_TAG_ExtendedResponse: {
655 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
656 asn1_push_tag(data, ASN1_APPLICATION(msg->type));
657 ldap_encode_response(data, &r->response);
658 if (r->oid) {
659 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
660 asn1_write(data, r->oid, strlen(r->oid));
661 asn1_pop_tag(data);
663 if (r->value) {
664 asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
665 asn1_write(data, r->value->data, r->value->length);
666 asn1_pop_tag(data);
668 asn1_pop_tag(data);
669 break;
671 default:
672 return false;
675 if (msg->controls != NULL) {
676 asn1_push_tag(data, ASN1_CONTEXT(0));
678 for (i = 0; msg->controls[i] != NULL; i++) {
679 if (!ldap_encode_control(mem_ctx, data,
680 control_handlers,
681 msg->controls[i])) {
682 DEBUG(0,("Unable to encode control %s\n",
683 msg->controls[i]->oid));
684 return false;
688 asn1_pop_tag(data);
691 asn1_pop_tag(data);
693 if (data->has_error) {
694 asn1_free(data);
695 return false;
698 *result = data_blob_talloc(mem_ctx, data->data, data->length);
699 asn1_free(data);
700 return true;
703 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
704 DATA_BLOB blob)
706 char *result = talloc_array(mem_ctx, char, blob.length+1);
707 memcpy(result, blob.data, blob.length);
708 result[blob.length] = '\0';
709 return result;
712 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
713 struct asn1_data *data,
714 const char **result)
716 DATA_BLOB string;
717 if (!asn1_read_OctetString(data, mem_ctx, &string))
718 return false;
719 *result = blob2string_talloc(mem_ctx, string);
720 data_blob_free(&string);
721 return true;
724 static void ldap_decode_response(TALLOC_CTX *mem_ctx,
725 struct asn1_data *data,
726 struct ldap_Result *result)
728 asn1_read_enumerated(data, &result->resultcode);
729 asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
730 asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
731 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
732 asn1_start_tag(data, ASN1_CONTEXT(3));
733 asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
734 asn1_end_tag(data);
735 } else {
736 result->referral = NULL;
740 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
743 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
744 if (chunks == NULL) {
745 return NULL;
748 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
749 if (chunks[chunk_num] == NULL) {
750 return NULL;
753 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
754 if (chunks[chunk_num]->data == NULL) {
755 return NULL;
757 chunks[chunk_num]->length = strlen(value);
759 chunks[chunk_num + 1] = '\0';
761 return chunks;
766 parse the ASN.1 formatted search string into a ldb_parse_tree
768 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
769 struct asn1_data *data)
771 uint8_t filter_tag;
772 struct ldb_parse_tree *ret;
774 if (!asn1_peek_uint8(data, &filter_tag)) {
775 return NULL;
778 filter_tag &= 0x1f; /* strip off the asn1 stuff */
780 ret = talloc(mem_ctx, struct ldb_parse_tree);
781 if (ret == NULL) return NULL;
783 switch(filter_tag) {
784 case 0:
785 case 1:
786 /* AND or OR of one or more filters */
787 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
788 ret->u.list.num_elements = 0;
789 ret->u.list.elements = NULL;
791 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
792 goto failed;
795 while (asn1_tag_remaining(data) > 0) {
796 struct ldb_parse_tree *subtree;
797 subtree = ldap_decode_filter_tree(ret, data);
798 if (subtree == NULL) {
799 goto failed;
801 ret->u.list.elements =
802 talloc_realloc(ret, ret->u.list.elements,
803 struct ldb_parse_tree *,
804 ret->u.list.num_elements+1);
805 if (ret->u.list.elements == NULL) {
806 goto failed;
808 talloc_steal(ret->u.list.elements, subtree);
809 ret->u.list.elements[ret->u.list.num_elements] = subtree;
810 ret->u.list.num_elements++;
812 if (!asn1_end_tag(data)) {
813 goto failed;
815 break;
817 case 2:
818 /* 'not' operation */
819 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
820 goto failed;
823 ret->operation = LDB_OP_NOT;
824 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
825 if (ret->u.isnot.child == NULL) {
826 goto failed;
828 if (!asn1_end_tag(data)) {
829 goto failed;
831 break;
833 case 3: {
834 /* equalityMatch */
835 const char *attrib;
836 DATA_BLOB value;
838 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
839 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
840 asn1_read_OctetString(data, mem_ctx, &value);
841 asn1_end_tag(data);
842 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
843 goto failed;
846 ret->operation = LDB_OP_EQUALITY;
847 ret->u.equality.attr = talloc_steal(ret, attrib);
848 ret->u.equality.value.data = talloc_steal(ret, value.data);
849 ret->u.equality.value.length = value.length;
850 break;
852 case 4: {
853 /* substrings */
854 DATA_BLOB attr;
855 uint8_t subs_tag;
856 char *value;
857 int chunk_num = 0;
859 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
860 goto failed;
862 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
863 goto failed;
866 ret->operation = LDB_OP_SUBSTRING;
867 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
868 ret->u.substring.chunks = NULL;
869 ret->u.substring.start_with_wildcard = 1;
870 ret->u.substring.end_with_wildcard = 1;
872 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
873 goto failed;
876 while (asn1_tag_remaining(data)) {
877 asn1_peek_uint8(data, &subs_tag);
878 subs_tag &= 0x1f; /* strip off the asn1 stuff */
879 if (subs_tag > 2) goto failed;
881 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
882 asn1_read_LDAPString(data, mem_ctx, &value);
883 asn1_end_tag(data);
885 switch (subs_tag) {
886 case 0:
887 if (ret->u.substring.chunks != NULL) {
888 /* initial value found in the middle */
889 goto failed;
892 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
893 if (ret->u.substring.chunks == NULL) {
894 goto failed;
897 ret->u.substring.start_with_wildcard = 0;
898 chunk_num = 1;
899 break;
901 case 1:
902 if (ret->u.substring.end_with_wildcard == 0) {
903 /* "any" value found after a "final" value */
904 goto failed;
907 ret->u.substring.chunks = ldap_decode_substring(ret,
908 ret->u.substring.chunks,
909 chunk_num,
910 value);
911 if (ret->u.substring.chunks == NULL) {
912 goto failed;
915 chunk_num++;
916 break;
918 case 2:
919 ret->u.substring.chunks = ldap_decode_substring(ret,
920 ret->u.substring.chunks,
921 chunk_num,
922 value);
923 if (ret->u.substring.chunks == NULL) {
924 goto failed;
927 ret->u.substring.end_with_wildcard = 0;
928 break;
930 default:
931 goto failed;
936 if (!asn1_end_tag(data)) { /* SEQUENCE */
937 goto failed;
940 if (!asn1_end_tag(data)) {
941 goto failed;
943 break;
945 case 5: {
946 /* greaterOrEqual */
947 const char *attrib;
948 DATA_BLOB value;
950 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
951 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
952 asn1_read_OctetString(data, mem_ctx, &value);
953 asn1_end_tag(data);
954 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
955 goto failed;
958 ret->operation = LDB_OP_GREATER;
959 ret->u.comparison.attr = talloc_steal(ret, attrib);
960 ret->u.comparison.value.data = talloc_steal(ret, value.data);
961 ret->u.comparison.value.length = value.length;
962 break;
964 case 6: {
965 /* lessOrEqual */
966 const char *attrib;
967 DATA_BLOB value;
969 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
970 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
971 asn1_read_OctetString(data, mem_ctx, &value);
972 asn1_end_tag(data);
973 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
974 goto failed;
977 ret->operation = LDB_OP_LESS;
978 ret->u.comparison.attr = talloc_steal(ret, attrib);
979 ret->u.comparison.value.data = talloc_steal(ret, value.data);
980 ret->u.comparison.value.length = value.length;
981 break;
983 case 7: {
984 /* Normal presence, "attribute=*" */
985 char *attr;
987 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
988 goto failed;
990 if (!asn1_read_LDAPString(data, ret, &attr)) {
991 goto failed;
994 ret->operation = LDB_OP_PRESENT;
995 ret->u.present.attr = talloc_steal(ret, attr);
997 if (!asn1_end_tag(data)) {
998 goto failed;
1000 break;
1002 case 8: {
1003 /* approx */
1004 const char *attrib;
1005 DATA_BLOB value;
1007 asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
1008 asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
1009 asn1_read_OctetString(data, mem_ctx, &value);
1010 asn1_end_tag(data);
1011 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1012 goto failed;
1015 ret->operation = LDB_OP_APPROX;
1016 ret->u.comparison.attr = talloc_steal(ret, attrib);
1017 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1018 ret->u.comparison.value.length = value.length;
1019 break;
1021 case 9: {
1022 char *oid = NULL, *attr = NULL, *value;
1023 uint8_t dnAttributes;
1024 /* an extended search */
1025 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1026 goto failed;
1029 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1030 we need to check we properly implement --SSS */
1031 /* either oid or type must be defined */
1032 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1033 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1034 asn1_read_LDAPString(data, ret, &oid);
1035 asn1_end_tag(data);
1037 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1038 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1039 asn1_read_LDAPString(data, ret, &attr);
1040 asn1_end_tag(data);
1042 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1043 asn1_read_LDAPString(data, ret, &value);
1044 asn1_end_tag(data);
1045 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1046 it is not marked as OPTIONAL but openldap tools
1047 do not set this unless it is to be set as TRUE
1048 NOTE: openldap tools do not work with AD as it
1049 seems that AD always requires the dnAttributes
1050 boolean value to be set */
1051 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1052 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1053 asn1_read_uint8(data, &dnAttributes);
1054 asn1_end_tag(data);
1055 } else {
1056 dnAttributes = 0;
1058 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1059 goto failed;
1062 if (oid) {
1063 ret->operation = LDB_OP_EXTENDED;
1065 /* From the RFC2251: If the type field is
1066 absent and matchingRule is present, the matchValue is compared
1067 against all attributes in an entry which support that matchingRule
1069 if (attr) {
1070 ret->u.extended.attr = talloc_steal(ret, attr);
1071 } else {
1072 ret->u.extended.attr = talloc_strdup(ret, "*");
1074 ret->u.extended.rule_id = talloc_steal(ret, oid);
1075 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1076 ret->u.extended.value.length = strlen(value);
1077 ret->u.extended.dnAttributes = dnAttributes;
1078 } else {
1079 ret->operation = LDB_OP_EQUALITY;
1080 ret->u.equality.attr = talloc_steal(ret, attr);
1081 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1082 ret->u.equality.value.length = strlen(value);
1084 if (!asn1_end_tag(data)) {
1085 goto failed;
1087 break;
1090 default:
1091 goto failed;
1094 return ret;
1096 failed:
1097 talloc_free(ret);
1098 return NULL;
1101 /* Decode a single LDAP attribute, possibly containing multiple values */
1102 static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1103 struct ldb_message_element *attrib)
1105 asn1_start_tag(data, ASN1_SEQUENCE(0));
1106 asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1107 asn1_start_tag(data, ASN1_SET);
1108 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1109 DATA_BLOB blob;
1110 asn1_read_OctetString(data, mem_ctx, &blob);
1111 add_value_to_attrib(mem_ctx, &blob, attrib);
1113 asn1_end_tag(data);
1114 asn1_end_tag(data);
1118 /* Decode a set of LDAP attributes, as found in the dereference control */
1119 void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1120 struct ldb_message_element **attributes,
1121 int *num_attributes)
1123 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1124 struct ldb_message_element attrib;
1125 ZERO_STRUCT(attrib);
1126 ldap_decode_attrib(mem_ctx, data, &attrib);
1127 add_attrib_to_array_talloc(mem_ctx, &attrib,
1128 attributes, num_attributes);
1132 /* Decode a set of LDAP attributes, as found in a search entry */
1133 static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1134 struct ldb_message_element **attributes,
1135 int *num_attributes)
1137 asn1_start_tag(data, ASN1_SEQUENCE(0));
1138 ldap_decode_attribs_bare(mem_ctx, data,
1139 attributes, num_attributes);
1140 asn1_end_tag(data);
1143 /* This routine returns LDAP status codes */
1145 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1146 const struct ldap_control_handler *control_handlers,
1147 struct ldap_message *msg)
1149 uint8_t tag;
1151 asn1_start_tag(data, ASN1_SEQUENCE(0));
1152 asn1_read_Integer(data, &msg->messageid);
1154 if (!asn1_peek_uint8(data, &tag))
1155 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1157 switch(tag) {
1159 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1160 struct ldap_BindRequest *r = &msg->r.BindRequest;
1161 msg->type = LDAP_TAG_BindRequest;
1162 asn1_start_tag(data, tag);
1163 asn1_read_Integer(data, &r->version);
1164 asn1_read_OctetString_talloc(msg, data, &r->dn);
1165 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1166 int pwlen;
1167 r->creds.password = "";
1168 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1169 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1170 pwlen = asn1_tag_remaining(data);
1171 if (pwlen == -1) {
1172 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1174 if (pwlen != 0) {
1175 char *pw = talloc_array(msg, char, pwlen+1);
1176 if (!pw) {
1177 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1179 asn1_read(data, pw, pwlen);
1180 pw[pwlen] = '\0';
1181 r->creds.password = pw;
1183 asn1_end_tag(data);
1184 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1185 asn1_start_tag(data, ASN1_CONTEXT(3));
1186 r->mechanism = LDAP_AUTH_MECH_SASL;
1187 asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1188 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1189 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1190 asn1_read_OctetString(data, msg, &tmp_blob);
1191 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1192 if (!r->creds.SASL.secblob) {
1193 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1195 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1196 tmp_blob.data, tmp_blob.length);
1197 data_blob_free(&tmp_blob);
1198 } else {
1199 r->creds.SASL.secblob = NULL;
1201 asn1_end_tag(data);
1202 } else {
1203 /* Neither Simple nor SASL bind */
1204 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1206 asn1_end_tag(data);
1207 break;
1210 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1211 struct ldap_BindResponse *r = &msg->r.BindResponse;
1212 msg->type = LDAP_TAG_BindResponse;
1213 asn1_start_tag(data, tag);
1214 ldap_decode_response(msg, data, &r->response);
1215 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1216 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1217 asn1_read_ContextSimple(data, 7, &tmp_blob);
1218 r->SASL.secblob = talloc(msg, DATA_BLOB);
1219 if (!r->SASL.secblob) {
1220 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1222 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1223 tmp_blob.data, tmp_blob.length);
1224 data_blob_free(&tmp_blob);
1225 } else {
1226 r->SASL.secblob = NULL;
1228 asn1_end_tag(data);
1229 break;
1232 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1233 msg->type = LDAP_TAG_UnbindRequest;
1234 asn1_start_tag(data, tag);
1235 asn1_end_tag(data);
1236 break;
1239 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1240 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1241 int sizelimit, timelimit;
1242 const char **attrs = NULL;
1243 msg->type = LDAP_TAG_SearchRequest;
1244 asn1_start_tag(data, tag);
1245 asn1_read_OctetString_talloc(msg, data, &r->basedn);
1246 asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1247 asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1248 asn1_read_Integer(data, &sizelimit);
1249 r->sizelimit = sizelimit;
1250 asn1_read_Integer(data, &timelimit);
1251 r->timelimit = timelimit;
1252 asn1_read_BOOLEAN(data, &r->attributesonly);
1254 r->tree = ldap_decode_filter_tree(msg, data);
1255 if (r->tree == NULL) {
1256 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1259 asn1_start_tag(data, ASN1_SEQUENCE(0));
1261 r->num_attributes = 0;
1262 r->attributes = NULL;
1264 while (asn1_tag_remaining(data) > 0) {
1266 const char *attr;
1267 if (!asn1_read_OctetString_talloc(msg, data,
1268 &attr))
1269 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1270 if (!add_string_to_array(msg, attr,
1271 &attrs,
1272 &r->num_attributes))
1273 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1275 r->attributes = attrs;
1277 asn1_end_tag(data);
1278 asn1_end_tag(data);
1279 break;
1282 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1283 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1284 msg->type = LDAP_TAG_SearchResultEntry;
1285 r->attributes = NULL;
1286 r->num_attributes = 0;
1287 asn1_start_tag(data, tag);
1288 asn1_read_OctetString_talloc(msg, data, &r->dn);
1289 ldap_decode_attribs(msg, data, &r->attributes,
1290 &r->num_attributes);
1291 asn1_end_tag(data);
1292 break;
1295 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1296 struct ldap_Result *r = &msg->r.SearchResultDone;
1297 msg->type = LDAP_TAG_SearchResultDone;
1298 asn1_start_tag(data, tag);
1299 ldap_decode_response(msg, data, r);
1300 asn1_end_tag(data);
1301 break;
1304 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1305 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1306 msg->type = LDAP_TAG_SearchResultReference;
1307 asn1_start_tag(data, tag);
1308 asn1_read_OctetString_talloc(msg, data, &r->referral);
1309 asn1_end_tag(data);
1310 break;
1313 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1314 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1315 msg->type = LDAP_TAG_ModifyRequest;
1316 asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1317 asn1_read_OctetString_talloc(msg, data, &r->dn);
1318 asn1_start_tag(data, ASN1_SEQUENCE(0));
1320 r->num_mods = 0;
1321 r->mods = NULL;
1323 while (asn1_tag_remaining(data) > 0) {
1324 struct ldap_mod mod;
1325 int v;
1326 ZERO_STRUCT(mod);
1327 asn1_start_tag(data, ASN1_SEQUENCE(0));
1328 asn1_read_enumerated(data, &v);
1329 mod.type = v;
1330 ldap_decode_attrib(msg, data, &mod.attrib);
1331 asn1_end_tag(data);
1332 if (!add_mod_to_array_talloc(msg, &mod,
1333 &r->mods, &r->num_mods)) {
1334 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1338 asn1_end_tag(data);
1339 asn1_end_tag(data);
1340 break;
1343 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1344 struct ldap_Result *r = &msg->r.ModifyResponse;
1345 msg->type = LDAP_TAG_ModifyResponse;
1346 asn1_start_tag(data, tag);
1347 ldap_decode_response(msg, data, r);
1348 asn1_end_tag(data);
1349 break;
1352 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1353 struct ldap_AddRequest *r = &msg->r.AddRequest;
1354 msg->type = LDAP_TAG_AddRequest;
1355 asn1_start_tag(data, tag);
1356 asn1_read_OctetString_talloc(msg, data, &r->dn);
1358 r->attributes = NULL;
1359 r->num_attributes = 0;
1360 ldap_decode_attribs(msg, data, &r->attributes,
1361 &r->num_attributes);
1363 asn1_end_tag(data);
1364 break;
1367 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1368 struct ldap_Result *r = &msg->r.AddResponse;
1369 msg->type = LDAP_TAG_AddResponse;
1370 asn1_start_tag(data, tag);
1371 ldap_decode_response(msg, data, r);
1372 asn1_end_tag(data);
1373 break;
1376 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1377 struct ldap_DelRequest *r = &msg->r.DelRequest;
1378 int len;
1379 char *dn;
1380 msg->type = LDAP_TAG_DelRequest;
1381 asn1_start_tag(data,
1382 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1383 len = asn1_tag_remaining(data);
1384 if (len == -1) {
1385 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1387 dn = talloc_array(msg, char, len+1);
1388 if (dn == NULL)
1389 break;
1390 asn1_read(data, dn, len);
1391 dn[len] = '\0';
1392 r->dn = dn;
1393 asn1_end_tag(data);
1394 break;
1397 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1398 struct ldap_Result *r = &msg->r.DelResponse;
1399 msg->type = LDAP_TAG_DelResponse;
1400 asn1_start_tag(data, tag);
1401 ldap_decode_response(msg, data, r);
1402 asn1_end_tag(data);
1403 break;
1406 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1407 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1408 msg->type = LDAP_TAG_ModifyDNRequest;
1409 asn1_start_tag(data,
1410 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1411 asn1_read_OctetString_talloc(msg, data, &r->dn);
1412 asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1413 asn1_read_BOOLEAN(data, &r->deleteolddn);
1414 r->newsuperior = NULL;
1415 if (asn1_tag_remaining(data) > 0) {
1416 int len;
1417 char *newsup;
1418 asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1419 len = asn1_tag_remaining(data);
1420 if (len == -1) {
1421 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1423 newsup = talloc_array(msg, char, len+1);
1424 if (newsup == NULL) {
1425 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1427 asn1_read(data, newsup, len);
1428 newsup[len] = '\0';
1429 r->newsuperior = newsup;
1430 asn1_end_tag(data);
1432 asn1_end_tag(data);
1433 break;
1436 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1437 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1438 msg->type = LDAP_TAG_ModifyDNResponse;
1439 asn1_start_tag(data, tag);
1440 ldap_decode_response(msg, data, r);
1441 asn1_end_tag(data);
1442 break;
1445 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1446 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1447 msg->type = LDAP_TAG_CompareRequest;
1448 asn1_start_tag(data,
1449 ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1450 asn1_read_OctetString_talloc(msg, data, &r->dn);
1451 asn1_start_tag(data, ASN1_SEQUENCE(0));
1452 asn1_read_OctetString_talloc(msg, data, &r->attribute);
1453 asn1_read_OctetString(data, msg, &r->value);
1454 if (r->value.data) {
1455 talloc_steal(msg, r->value.data);
1457 asn1_end_tag(data);
1458 asn1_end_tag(data);
1459 break;
1462 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1463 struct ldap_Result *r = &msg->r.CompareResponse;
1464 msg->type = LDAP_TAG_CompareResponse;
1465 asn1_start_tag(data, tag);
1466 ldap_decode_response(msg, data, r);
1467 asn1_end_tag(data);
1468 break;
1471 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1472 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1473 msg->type = LDAP_TAG_AbandonRequest;
1474 asn1_start_tag(data, tag);
1475 asn1_read_implicit_Integer(data, &r->messageid);
1476 asn1_end_tag(data);
1477 break;
1480 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1481 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1482 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1484 msg->type = LDAP_TAG_ExtendedRequest;
1485 asn1_start_tag(data,tag);
1486 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1487 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1489 r->oid = blob2string_talloc(msg, tmp_blob);
1490 data_blob_free(&tmp_blob);
1491 if (!r->oid) {
1492 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1495 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1496 asn1_read_ContextSimple(data, 1, &tmp_blob);
1497 r->value = talloc(msg, DATA_BLOB);
1498 if (!r->value) {
1499 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1501 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1502 data_blob_free(&tmp_blob);
1503 } else {
1504 r->value = NULL;
1507 asn1_end_tag(data);
1508 break;
1511 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1512 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1513 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1515 msg->type = LDAP_TAG_ExtendedResponse;
1516 asn1_start_tag(data, tag);
1517 ldap_decode_response(msg, data, &r->response);
1519 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1520 asn1_read_ContextSimple(data, 1, &tmp_blob);
1521 r->oid = blob2string_talloc(msg, tmp_blob);
1522 data_blob_free(&tmp_blob);
1523 if (!r->oid) {
1524 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1526 } else {
1527 r->oid = NULL;
1530 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1531 asn1_read_ContextSimple(data, 1, &tmp_blob);
1532 r->value = talloc(msg, DATA_BLOB);
1533 if (!r->value) {
1534 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1536 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1537 data_blob_free(&tmp_blob);
1538 } else {
1539 r->value = NULL;
1542 asn1_end_tag(data);
1543 break;
1545 default:
1546 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1549 msg->controls = NULL;
1550 msg->controls_decoded = NULL;
1552 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1553 int i = 0;
1554 struct ldb_control **ctrl = NULL;
1555 bool *decoded = NULL;
1557 asn1_start_tag(data, ASN1_CONTEXT(0));
1559 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1560 DATA_BLOB value;
1561 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1563 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1564 if (!ctrl) {
1565 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1568 decoded = talloc_realloc(msg, decoded, bool, i+1);
1569 if (!decoded) {
1570 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1573 ctrl[i] = talloc(ctrl, struct ldb_control);
1574 if (!ctrl[i]) {
1575 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1578 if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1579 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1582 if (!ldap_decode_control_value(ctrl[i], value,
1583 control_handlers,
1584 ctrl[i])) {
1585 if (ctrl[i]->critical) {
1586 ctrl[i]->data = NULL;
1587 decoded[i] = false;
1588 i++;
1589 } else {
1590 talloc_free(ctrl[i]);
1591 ctrl[i] = NULL;
1593 } else {
1594 decoded[i] = true;
1595 i++;
1599 if (ctrl != NULL) {
1600 ctrl[i] = NULL;
1603 msg->controls = ctrl;
1604 msg->controls_decoded = decoded;
1606 asn1_end_tag(data);
1609 asn1_end_tag(data);
1610 if ((data->has_error) || (data->nesting != NULL)) {
1611 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1613 return NT_STATUS_OK;
1618 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1619 ldap packet. Set packet_size if true.
1621 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1623 if (blob.length < 6) {
1625 * We need at least 6 bytes to workout the length
1626 * of the pdu.
1628 return STATUS_MORE_ENTRIES;
1630 return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);