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/>.
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
,
41 attrib
->num_values
+1);
42 if (attrib
->values
== NULL
)
45 attrib
->values
[attrib
->num_values
].data
= talloc_steal(attrib
->values
,
47 attrib
->values
[attrib
->num_values
].length
= value
->length
;
48 attrib
->num_values
+= 1;
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
,
57 *attribs
= talloc_realloc(mem_ctx
,
59 struct ldb_message_element
,
65 (*attribs
)[*num_attribs
] = *attrib
;
66 talloc_steal(*attribs
, attrib
->values
);
67 talloc_steal(*attribs
, attrib
->name
);
72 static bool add_mod_to_array_talloc(TALLOC_CTX
*mem_ctx
,
74 struct ldap_mod
**mods
,
77 *mods
= talloc_realloc(mem_ctx
, *mods
, struct ldap_mod
, (*num_mods
)+1);
82 (*mods
)[*num_mods
] = *mod
;
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
)
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
)) {
105 if (handlers
[i
].oid
== NULL
) {
112 static bool ldap_decode_control_wrapper(void *mem_ctx
, struct asn1_data
*data
,
113 struct ldb_control
*ctrl
, DATA_BLOB
*value
)
117 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
121 if (!asn1_read_OctetString(data
, mem_ctx
, &oid
)) {
124 ctrl
->oid
= talloc_strndup(mem_ctx
, (char *)oid
.data
, oid
.length
);
129 if (asn1_peek_tag(data
, ASN1_BOOLEAN
)) {
131 if (!asn1_read_BOOLEAN(data
, &critical
)) {
134 ctrl
->critical
= critical
;
136 ctrl
->critical
= false;
141 if (!asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
142 *value
= data_blob(NULL
, 0);
146 if (!asn1_read_OctetString(data
, mem_ctx
, value
)) {
151 if (!asn1_end_tag(data
)) {
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
)
169 for (i
= 0; handlers
[i
].oid
!= NULL
; i
++) {
171 /* not encoding this control, the OID has been
172 * set to NULL indicating it isn't really
176 if (strcmp(handlers
[i
].oid
, ctrl
->oid
) == 0) {
177 if (!handlers
[i
].encode
) {
178 if (ctrl
->critical
) {
181 /* not encoding this control */
185 if (!handlers
[i
].encode(mem_ctx
, ctrl
->data
, &value
)) {
191 if (handlers
[i
].oid
== NULL
) {
195 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) {
199 if (!asn1_write_OctetString(data
, ctrl
->oid
, strlen(ctrl
->oid
))) {
203 if (ctrl
->critical
) {
204 if (!asn1_write_BOOLEAN(data
, ctrl
->critical
)) {
213 if (!asn1_write_OctetString(data
, value
.data
, value
.length
)) {
218 if (!asn1_pop_tag(data
)) {
225 static bool ldap_push_filter(struct asn1_data
*data
, struct ldb_parse_tree
*tree
)
229 switch (tree
->operation
) {
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
])) {
242 asn1_push_tag(data
, ASN1_CONTEXT(2));
243 if (!ldap_push_filter(data
, tree
->u
.isnot
.child
)) {
249 case LDB_OP_EQUALITY
:
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
);
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,
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
.start_with_wildcard
) {
274 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
275 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
279 while (tree
->u
.substring
.chunks
[i
]) {
282 if (( ! tree
->u
.substring
.chunks
[i
+ 1]) &&
283 (tree
->u
.substring
.end_with_wildcard
== 0)) {
288 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(ctx
));
289 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
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
);
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
);
319 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(7));
320 asn1_write_LDAPString(data
, tree
->u
.present
.attr
);
322 return !data
->has_error
;
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
);
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
);
349 if (tree
->u
.extended
.attr
) {
350 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2));
351 asn1_write_LDAPString(data
, tree
->u
.extended
.attr
);
354 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3));
355 asn1_write_DATA_BLOB_LDAPString(data
, &tree
->u
.extended
.value
);
357 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4));
358 asn1_write_uint8(data
, tree
->u
.extended
.dnAttributes
);
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
));
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
);
392 if (!data
) return false;
394 asn1_push_tag(data
, ASN1_SEQUENCE(0));
395 asn1_write_Integer(data
, msg
->messageid
);
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
));
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
);
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
);
441 case LDAP_TAG_UnbindRequest
: {
442 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
443 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
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
)) {
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
]));
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
,
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
);
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
);
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
);
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
);
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
);
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
);
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
));
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
);
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
));
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
);
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
,
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
);
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
);
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
));
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
));
644 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
645 asn1_write(data
, r
->value
->data
, r
->value
->length
);
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
);
656 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10));
657 asn1_write(data
, r
->oid
, strlen(r
->oid
));
661 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11));
662 asn1_write(data
, r
->value
->data
, r
->value
->length
);
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
,
679 DEBUG(1,("Unable to encode control %s\n",
680 msg
->controls
[i
]->oid
));
690 if (data
->has_error
) {
695 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
700 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
703 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
704 memcpy(result
, blob
.data
, blob
.length
);
705 result
[blob
.length
] = '\0';
709 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
710 struct asn1_data
*data
,
714 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
716 *result
= blob2string_talloc(mem_ctx
, string
);
717 data_blob_free(&string
);
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
);
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
) {
745 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
746 if (chunks
[chunk_num
] == NULL
) {
750 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
751 if (chunks
[chunk_num
]->data
== NULL
) {
754 chunks
[chunk_num
]->length
= strlen(value
);
756 chunks
[chunk_num
+ 1] = '\0';
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
)
769 struct ldb_parse_tree
*ret
;
771 if (!asn1_peek_uint8(data
, &filter_tag
)) {
775 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
777 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
778 if (ret
== NULL
) return NULL
;
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
))) {
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
) {
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
) {
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
)) {
815 /* 'not' operation */
816 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
820 ret
->operation
= LDB_OP_NOT
;
821 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
822 if (ret
->u
.isnot
.child
== NULL
) {
825 if (!asn1_end_tag(data
)) {
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
);
839 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
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
;
856 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
859 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
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))) {
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
);
884 if (ret
->u
.substring
.chunks
!= NULL
) {
885 /* initial value found in the middle */
889 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
890 if (ret
->u
.substring
.chunks
== NULL
) {
894 ret
->u
.substring
.start_with_wildcard
= 0;
899 if (ret
->u
.substring
.end_with_wildcard
== 0) {
900 /* "any" value found after a "final" value */
904 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
905 ret
->u
.substring
.chunks
,
908 if (ret
->u
.substring
.chunks
== NULL
) {
916 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
917 ret
->u
.substring
.chunks
,
920 if (ret
->u
.substring
.chunks
== NULL
) {
924 ret
->u
.substring
.end_with_wildcard
= 0;
933 if (!asn1_end_tag(data
)) { /* SEQUENCE */
937 if (!asn1_end_tag(data
)) {
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
);
951 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
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
;
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
);
970 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
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
;
981 /* Normal presence, "attribute=*" */
984 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
987 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
991 ret
->operation
= LDB_OP_PRESENT
;
992 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
994 if (!asn1_end_tag(data
)) {
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
);
1008 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
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
;
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
))) {
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
);
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
);
1039 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
1040 asn1_read_LDAPString(data
, ret
, &value
);
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
);
1055 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
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
1067 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
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
;
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
)) {
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
)) {
1107 asn1_read_OctetString(data
, mem_ctx
, &blob
);
1108 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
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
);
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
)
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
);
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))) {
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
);
1169 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1172 char *pw
= talloc_array(msg
, char, pwlen
+1);
1174 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1176 asn1_read(data
, pw
, pwlen
);
1178 r
->creds
.password
= pw
;
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
);
1196 r
->creds
.SASL
.secblob
= NULL
;
1200 /* Neither Simple nor SASL bind */
1201 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
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
);
1223 r
->SASL
.secblob
= NULL
;
1229 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1230 msg
->type
= LDAP_TAG_UnbindRequest
;
1231 asn1_start_tag(data
, tag
);
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) {
1264 if (!asn1_read_OctetString_talloc(msg
, data
,
1266 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1267 if (!add_string_to_array(msg
, attr
,
1269 &r
->num_attributes
))
1270 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1272 r
->attributes
= attrs
;
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
);
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
);
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
);
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));
1320 while (asn1_tag_remaining(data
) > 0) {
1321 struct ldap_mod mod
;
1324 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1325 asn1_read_enumerated(data
, &v
);
1327 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1329 if (!add_mod_to_array_talloc(msg
, &mod
,
1330 &r
->mods
, &r
->num_mods
)) {
1331 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
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
);
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
);
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
);
1373 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1374 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1377 msg
->type
= LDAP_TAG_DelRequest
;
1378 asn1_start_tag(data
,
1379 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1380 len
= asn1_tag_remaining(data
);
1382 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1384 dn
= talloc_array(msg
, char, len
+1);
1387 asn1_read(data
, dn
, len
);
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
);
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) {
1415 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1416 len
= asn1_tag_remaining(data
);
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
);
1426 r
->newsuperior
= newsup
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1521 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
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
);
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
);
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))) {
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))) {
1558 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1560 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1565 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1567 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1570 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1572 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1575 if (!ldap_decode_control_wrapper(ctrl
[i
], data
, ctrl
[i
], &value
)) {
1576 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1579 if (!ldap_decode_control_value(ctrl
[i
], value
,
1582 if (ctrl
[i
]->critical
) {
1583 ctrl
[i
]->data
= NULL
;
1587 talloc_free(ctrl
[i
]);
1600 msg
->controls
= ctrl
;
1601 msg
->controls_decoded
= decoded
;
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
1625 return STATUS_MORE_ENTRIES
;
1627 return asn1_peek_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);