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
++) {
170 if (strcmp(handlers
[i
].oid
, ctrl
->oid
) == 0) {
171 if (!handlers
[i
].encode
) {
172 if (ctrl
->critical
) {
175 /* not encoding this control */
179 if (!handlers
[i
].encode(mem_ctx
, ctrl
->data
, &value
)) {
185 if (handlers
[i
].oid
== NULL
) {
189 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) {
193 if (!asn1_write_OctetString(data
, ctrl
->oid
, strlen(ctrl
->oid
))) {
197 if (ctrl
->critical
) {
198 if (!asn1_write_BOOLEAN(data
, ctrl
->critical
)) {
207 if (!asn1_write_OctetString(data
, value
.data
, value
.length
)) {
212 if (!asn1_pop_tag(data
)) {
219 static bool ldap_push_filter(struct asn1_data
*data
, struct ldb_parse_tree
*tree
)
223 switch (tree
->operation
) {
226 asn1_push_tag(data
, ASN1_CONTEXT(tree
->operation
==LDB_OP_AND
?0:1));
227 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
228 if (!ldap_push_filter(data
, tree
->u
.list
.elements
[i
])) {
236 asn1_push_tag(data
, ASN1_CONTEXT(2));
237 if (!ldap_push_filter(data
, tree
->u
.isnot
.child
)) {
243 case LDB_OP_EQUALITY
:
245 asn1_push_tag(data
, ASN1_CONTEXT(3));
246 asn1_write_OctetString(data
, tree
->u
.equality
.attr
,
247 strlen(tree
->u
.equality
.attr
));
248 asn1_write_OctetString(data
, tree
->u
.equality
.value
.data
,
249 tree
->u
.equality
.value
.length
);
253 case LDB_OP_SUBSTRING
:
255 SubstringFilter ::= SEQUENCE {
256 type AttributeDescription,
257 -- at least one must be present
258 substrings SEQUENCE OF CHOICE {
259 initial [0] LDAPString,
261 final [2] LDAPString } }
263 asn1_push_tag(data
, ASN1_CONTEXT(4));
264 asn1_write_OctetString(data
, tree
->u
.substring
.attr
, strlen(tree
->u
.substring
.attr
));
265 asn1_push_tag(data
, ASN1_SEQUENCE(0));
267 if ( ! tree
->u
.substring
.start_with_wildcard
) {
268 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
269 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
273 while (tree
->u
.substring
.chunks
[i
]) {
276 if (( ! tree
->u
.substring
.chunks
[i
+ 1]) &&
277 (tree
->u
.substring
.end_with_wildcard
== 0)) {
282 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(ctx
));
283 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
292 /* greaterOrEqual test */
293 asn1_push_tag(data
, ASN1_CONTEXT(5));
294 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
295 strlen(tree
->u
.comparison
.attr
));
296 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
297 tree
->u
.comparison
.value
.length
);
302 /* lessOrEqual test */
303 asn1_push_tag(data
, ASN1_CONTEXT(6));
304 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
305 strlen(tree
->u
.comparison
.attr
));
306 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
307 tree
->u
.comparison
.value
.length
);
313 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(7));
314 asn1_write_LDAPString(data
, tree
->u
.present
.attr
);
316 return !data
->has_error
;
320 asn1_push_tag(data
, ASN1_CONTEXT(8));
321 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
322 strlen(tree
->u
.comparison
.attr
));
323 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
324 tree
->u
.comparison
.value
.length
);
328 case LDB_OP_EXTENDED
:
330 MatchingRuleAssertion ::= SEQUENCE {
331 matchingRule [1] MatchingRuleID OPTIONAL,
332 type [2] AttributeDescription OPTIONAL,
333 matchValue [3] AssertionValue,
334 dnAttributes [4] BOOLEAN DEFAULT FALSE
337 asn1_push_tag(data
, ASN1_CONTEXT(9));
338 if (tree
->u
.extended
.rule_id
) {
339 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
340 asn1_write_LDAPString(data
, tree
->u
.extended
.rule_id
);
343 if (tree
->u
.extended
.attr
) {
344 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2));
345 asn1_write_LDAPString(data
, tree
->u
.extended
.attr
);
348 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3));
349 asn1_write_DATA_BLOB_LDAPString(data
, &tree
->u
.extended
.value
);
351 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4));
352 asn1_write_uint8(data
, tree
->u
.extended
.dnAttributes
);
360 return !data
->has_error
;
363 static void ldap_encode_response(struct asn1_data
*data
, struct ldap_Result
*result
)
365 asn1_write_enumerated(data
, result
->resultcode
);
366 asn1_write_OctetString(data
, result
->dn
,
367 (result
->dn
) ? strlen(result
->dn
) : 0);
368 asn1_write_OctetString(data
, result
->errormessage
,
369 (result
->errormessage
) ?
370 strlen(result
->errormessage
) : 0);
371 if (result
->referral
) {
372 asn1_push_tag(data
, ASN1_CONTEXT(3));
373 asn1_write_OctetString(data
, result
->referral
,
374 strlen(result
->referral
));
379 _PUBLIC_
bool ldap_encode(struct ldap_message
*msg
,
380 const struct ldap_control_handler
*control_handlers
,
381 DATA_BLOB
*result
, TALLOC_CTX
*mem_ctx
)
383 struct asn1_data
*data
= asn1_init(mem_ctx
);
386 if (!data
) return false;
388 asn1_push_tag(data
, ASN1_SEQUENCE(0));
389 asn1_write_Integer(data
, msg
->messageid
);
392 case LDAP_TAG_BindRequest
: {
393 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
394 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
395 asn1_write_Integer(data
, r
->version
);
396 asn1_write_OctetString(data
, r
->dn
,
397 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0);
399 switch (r
->mechanism
) {
400 case LDAP_AUTH_MECH_SIMPLE
:
401 /* context, primitive */
402 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
403 asn1_write(data
, r
->creds
.password
,
404 strlen(r
->creds
.password
));
407 case LDAP_AUTH_MECH_SASL
:
408 /* context, constructed */
409 asn1_push_tag(data
, ASN1_CONTEXT(3));
410 asn1_write_OctetString(data
, r
->creds
.SASL
.mechanism
,
411 strlen(r
->creds
.SASL
.mechanism
));
412 if (r
->creds
.SASL
.secblob
) {
413 asn1_write_OctetString(data
, r
->creds
.SASL
.secblob
->data
,
414 r
->creds
.SASL
.secblob
->length
);
425 case LDAP_TAG_BindResponse
: {
426 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
427 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
428 ldap_encode_response(data
, &r
->response
);
429 if (r
->SASL
.secblob
) {
430 asn1_write_ContextSimple(data
, 7, r
->SASL
.secblob
);
435 case LDAP_TAG_UnbindRequest
: {
436 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
439 case LDAP_TAG_SearchRequest
: {
440 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
441 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
442 asn1_write_OctetString(data
, r
->basedn
, strlen(r
->basedn
));
443 asn1_write_enumerated(data
, r
->scope
);
444 asn1_write_enumerated(data
, r
->deref
);
445 asn1_write_Integer(data
, r
->sizelimit
);
446 asn1_write_Integer(data
, r
->timelimit
);
447 asn1_write_BOOLEAN(data
, r
->attributesonly
);
449 if (!ldap_push_filter(data
, r
->tree
)) {
453 asn1_push_tag(data
, ASN1_SEQUENCE(0));
454 for (i
=0; i
<r
->num_attributes
; i
++) {
455 asn1_write_OctetString(data
, r
->attributes
[i
],
456 strlen(r
->attributes
[i
]));
462 case LDAP_TAG_SearchResultEntry
: {
463 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
464 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
465 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
466 asn1_push_tag(data
, ASN1_SEQUENCE(0));
467 for (i
=0; i
<r
->num_attributes
; i
++) {
468 struct ldb_message_element
*attr
= &r
->attributes
[i
];
469 asn1_push_tag(data
, ASN1_SEQUENCE(0));
470 asn1_write_OctetString(data
, attr
->name
,
472 asn1_push_tag(data
, ASN1_SEQUENCE(1));
473 for (j
=0; j
<attr
->num_values
; j
++) {
474 asn1_write_OctetString(data
,
475 attr
->values
[j
].data
,
476 attr
->values
[j
].length
);
485 case LDAP_TAG_SearchResultDone
: {
486 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
487 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
488 ldap_encode_response(data
, r
);
492 case LDAP_TAG_ModifyRequest
: {
493 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
494 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
495 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
496 asn1_push_tag(data
, ASN1_SEQUENCE(0));
498 for (i
=0; i
<r
->num_mods
; i
++) {
499 struct ldb_message_element
*attrib
= &r
->mods
[i
].attrib
;
500 asn1_push_tag(data
, ASN1_SEQUENCE(0));
501 asn1_write_enumerated(data
, r
->mods
[i
].type
);
502 asn1_push_tag(data
, ASN1_SEQUENCE(0));
503 asn1_write_OctetString(data
, attrib
->name
,
504 strlen(attrib
->name
));
505 asn1_push_tag(data
, ASN1_SET
);
506 for (j
=0; j
<attrib
->num_values
; j
++) {
507 asn1_write_OctetString(data
,
508 attrib
->values
[j
].data
,
509 attrib
->values
[j
].length
);
521 case LDAP_TAG_ModifyResponse
: {
522 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
523 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
524 ldap_encode_response(data
, r
);
528 case LDAP_TAG_AddRequest
: {
529 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
530 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
531 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
532 asn1_push_tag(data
, ASN1_SEQUENCE(0));
534 for (i
=0; i
<r
->num_attributes
; i
++) {
535 struct ldb_message_element
*attrib
= &r
->attributes
[i
];
536 asn1_push_tag(data
, ASN1_SEQUENCE(0));
537 asn1_write_OctetString(data
, attrib
->name
,
538 strlen(attrib
->name
));
539 asn1_push_tag(data
, ASN1_SET
);
540 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
541 asn1_write_OctetString(data
,
542 attrib
->values
[j
].data
,
543 attrib
->values
[j
].length
);
552 case LDAP_TAG_AddResponse
: {
553 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
554 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
555 ldap_encode_response(data
, r
);
559 case LDAP_TAG_DelRequest
: {
560 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
561 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
562 asn1_write(data
, r
->dn
, strlen(r
->dn
));
566 case LDAP_TAG_DelResponse
: {
567 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
568 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
569 ldap_encode_response(data
, r
);
573 case LDAP_TAG_ModifyDNRequest
: {
574 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
575 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
576 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
577 asn1_write_OctetString(data
, r
->newrdn
, strlen(r
->newrdn
));
578 asn1_write_BOOLEAN(data
, r
->deleteolddn
);
579 if (r
->newsuperior
) {
580 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
581 asn1_write(data
, r
->newsuperior
,
582 strlen(r
->newsuperior
));
588 case LDAP_TAG_ModifyDNResponse
: {
589 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
590 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
591 ldap_encode_response(data
, r
);
595 case LDAP_TAG_CompareRequest
: {
596 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
597 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
598 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
599 asn1_push_tag(data
, ASN1_SEQUENCE(0));
600 asn1_write_OctetString(data
, r
->attribute
,
601 strlen(r
->attribute
));
602 asn1_write_OctetString(data
, r
->value
.data
,
608 case LDAP_TAG_CompareResponse
: {
609 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
610 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
611 ldap_encode_response(data
, r
);
615 case LDAP_TAG_AbandonRequest
: {
616 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
617 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
618 asn1_write_implicit_Integer(data
, r
->messageid
);
622 case LDAP_TAG_SearchResultReference
: {
623 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
624 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
625 asn1_write_OctetString(data
, r
->referral
, strlen(r
->referral
));
629 case LDAP_TAG_ExtendedRequest
: {
630 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
631 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
632 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
633 asn1_write(data
, r
->oid
, strlen(r
->oid
));
636 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
637 asn1_write(data
, r
->value
->data
, r
->value
->length
);
643 case LDAP_TAG_ExtendedResponse
: {
644 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
645 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
646 ldap_encode_response(data
, &r
->response
);
648 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10));
649 asn1_write(data
, r
->oid
, strlen(r
->oid
));
653 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11));
654 asn1_write(data
, r
->value
->data
, r
->value
->length
);
664 if (msg
->controls
!= NULL
) {
665 asn1_push_tag(data
, ASN1_CONTEXT(0));
667 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
668 if (!ldap_encode_control(mem_ctx
, data
,
680 if (data
->has_error
) {
685 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
690 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
693 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
694 memcpy(result
, blob
.data
, blob
.length
);
695 result
[blob
.length
] = '\0';
699 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
700 struct asn1_data
*data
,
704 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
706 *result
= blob2string_talloc(mem_ctx
, string
);
707 data_blob_free(&string
);
711 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
712 struct asn1_data
*data
,
713 struct ldap_Result
*result
)
715 asn1_read_enumerated(data
, &result
->resultcode
);
716 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
717 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
718 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
719 asn1_start_tag(data
, ASN1_CONTEXT(3));
720 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
723 result
->referral
= NULL
;
727 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
730 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
731 if (chunks
== NULL
) {
735 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
736 if (chunks
[chunk_num
] == NULL
) {
740 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
741 if (chunks
[chunk_num
]->data
== NULL
) {
744 chunks
[chunk_num
]->length
= strlen(value
);
746 chunks
[chunk_num
+ 1] = '\0';
753 parse the ASN.1 formatted search string into a ldb_parse_tree
755 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
756 struct asn1_data
*data
)
759 struct ldb_parse_tree
*ret
;
761 if (!asn1_peek_uint8(data
, &filter_tag
)) {
765 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
767 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
768 if (ret
== NULL
) return NULL
;
773 /* AND or OR of one or more filters */
774 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
775 ret
->u
.list
.num_elements
= 0;
776 ret
->u
.list
.elements
= NULL
;
778 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
782 while (asn1_tag_remaining(data
) > 0) {
783 struct ldb_parse_tree
*subtree
;
784 subtree
= ldap_decode_filter_tree(ret
, data
);
785 if (subtree
== NULL
) {
788 ret
->u
.list
.elements
=
789 talloc_realloc(ret
, ret
->u
.list
.elements
,
790 struct ldb_parse_tree
*,
791 ret
->u
.list
.num_elements
+1);
792 if (ret
->u
.list
.elements
== NULL
) {
795 talloc_steal(ret
->u
.list
.elements
, subtree
);
796 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
797 ret
->u
.list
.num_elements
++;
799 if (!asn1_end_tag(data
)) {
805 /* 'not' operation */
806 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
810 ret
->operation
= LDB_OP_NOT
;
811 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
812 if (ret
->u
.isnot
.child
== NULL
) {
815 if (!asn1_end_tag(data
)) {
825 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
826 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
827 asn1_read_OctetString(data
, mem_ctx
, &value
);
829 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
833 ret
->operation
= LDB_OP_EQUALITY
;
834 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
835 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
836 ret
->u
.equality
.value
.length
= value
.length
;
846 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
849 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
853 ret
->operation
= LDB_OP_SUBSTRING
;
854 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
855 ret
->u
.substring
.chunks
= NULL
;
856 ret
->u
.substring
.start_with_wildcard
= 1;
857 ret
->u
.substring
.end_with_wildcard
= 1;
859 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
863 while (asn1_tag_remaining(data
)) {
864 asn1_peek_uint8(data
, &subs_tag
);
865 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
866 if (subs_tag
> 2) goto failed
;
868 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
));
869 asn1_read_LDAPString(data
, mem_ctx
, &value
);
874 if (ret
->u
.substring
.chunks
!= NULL
) {
875 /* initial value found in the middle */
879 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
880 if (ret
->u
.substring
.chunks
== NULL
) {
884 ret
->u
.substring
.start_with_wildcard
= 0;
889 if (ret
->u
.substring
.end_with_wildcard
== 0) {
890 /* "any" value found after a "final" value */
894 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
895 ret
->u
.substring
.chunks
,
898 if (ret
->u
.substring
.chunks
== NULL
) {
906 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
907 ret
->u
.substring
.chunks
,
910 if (ret
->u
.substring
.chunks
== NULL
) {
914 ret
->u
.substring
.end_with_wildcard
= 0;
923 if (!asn1_end_tag(data
)) { /* SEQUENCE */
927 if (!asn1_end_tag(data
)) {
937 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
938 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
939 asn1_read_OctetString(data
, mem_ctx
, &value
);
941 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
945 ret
->operation
= LDB_OP_GREATER
;
946 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
947 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
948 ret
->u
.comparison
.value
.length
= value
.length
;
956 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
957 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
958 asn1_read_OctetString(data
, mem_ctx
, &value
);
960 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
964 ret
->operation
= LDB_OP_LESS
;
965 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
966 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
967 ret
->u
.comparison
.value
.length
= value
.length
;
971 /* Normal presence, "attribute=*" */
974 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
977 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
981 ret
->operation
= LDB_OP_PRESENT
;
982 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
984 if (!asn1_end_tag(data
)) {
994 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
995 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
996 asn1_read_OctetString(data
, mem_ctx
, &value
);
998 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
1002 ret
->operation
= LDB_OP_APPROX
;
1003 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
1004 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
1005 ret
->u
.comparison
.value
.length
= value
.length
;
1009 char *oid
= NULL
, *attr
= NULL
, *value
;
1010 uint8_t dnAttributes
;
1011 /* an extended search */
1012 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
1016 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1017 we need to check we properly implement --SSS */
1018 /* either oid or type must be defined */
1019 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1020 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1));
1021 asn1_read_LDAPString(data
, ret
, &oid
);
1024 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1025 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2));
1026 asn1_read_LDAPString(data
, ret
, &attr
);
1029 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
1030 asn1_read_LDAPString(data
, ret
, &value
);
1032 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1033 it is not marked as OPTIONAL but openldap tools
1034 do not set this unless it is to be set as TRUE
1035 NOTE: openldap tools do not work with AD as it
1036 seems that AD always requires the dnAttributes
1037 boolean value to be set */
1038 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
1039 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4));
1040 asn1_read_uint8(data
, &dnAttributes
);
1045 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
1050 ret
->operation
= LDB_OP_EXTENDED
;
1052 /* From the RFC2251: If the type field is
1053 absent and matchingRule is present, the matchValue is compared
1054 against all attributes in an entry which support that matchingRule
1057 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
1059 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
1061 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
1062 ret
->u
.extended
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1063 ret
->u
.extended
.value
.length
= strlen(value
);
1064 ret
->u
.extended
.dnAttributes
= dnAttributes
;
1066 ret
->operation
= LDB_OP_EQUALITY
;
1067 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
1068 ret
->u
.equality
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1069 ret
->u
.equality
.value
.length
= strlen(value
);
1071 if (!asn1_end_tag(data
)) {
1088 /* Decode a single LDAP attribute, possibly containing multiple values */
1089 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1090 struct ldb_message_element
*attrib
)
1092 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1093 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
1094 asn1_start_tag(data
, ASN1_SET
);
1095 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
1097 asn1_read_OctetString(data
, mem_ctx
, &blob
);
1098 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
1105 /* Decode a set of LDAP attributes, as found in the dereference control */
1106 void ldap_decode_attribs_bare(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1107 struct ldb_message_element
**attributes
,
1108 int *num_attributes
)
1110 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1111 struct ldb_message_element attrib
;
1112 ZERO_STRUCT(attrib
);
1113 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
1114 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
1115 attributes
, num_attributes
);
1119 /* Decode a set of LDAP attributes, as found in a search entry */
1120 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1121 struct ldb_message_element
**attributes
,
1122 int *num_attributes
)
1124 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1125 ldap_decode_attribs_bare(mem_ctx
, data
,
1126 attributes
, num_attributes
);
1130 /* This routine returns LDAP status codes */
1132 _PUBLIC_ NTSTATUS
ldap_decode(struct asn1_data
*data
,
1133 const struct ldap_control_handler
*control_handlers
,
1134 struct ldap_message
*msg
)
1138 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1139 asn1_read_Integer(data
, &msg
->messageid
);
1141 if (!asn1_peek_uint8(data
, &tag
))
1142 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1146 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
1147 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
1148 msg
->type
= LDAP_TAG_BindRequest
;
1149 asn1_start_tag(data
, tag
);
1150 asn1_read_Integer(data
, &r
->version
);
1151 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1152 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
1154 r
->creds
.password
= "";
1155 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
1156 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1157 pwlen
= asn1_tag_remaining(data
);
1159 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1162 char *pw
= talloc_array(msg
, char, pwlen
+1);
1164 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1166 asn1_read(data
, pw
, pwlen
);
1168 r
->creds
.password
= pw
;
1171 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
1172 asn1_start_tag(data
, ASN1_CONTEXT(3));
1173 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
1174 asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
);
1175 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
1176 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1177 asn1_read_OctetString(data
, msg
, &tmp_blob
);
1178 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1179 if (!r
->creds
.SASL
.secblob
) {
1180 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1182 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
1183 tmp_blob
.data
, tmp_blob
.length
);
1184 data_blob_free(&tmp_blob
);
1186 r
->creds
.SASL
.secblob
= NULL
;
1190 /* Neither Simple nor SASL bind */
1191 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1197 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
1198 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
1199 msg
->type
= LDAP_TAG_BindResponse
;
1200 asn1_start_tag(data
, tag
);
1201 ldap_decode_response(msg
, data
, &r
->response
);
1202 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
1203 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1204 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
1205 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1206 if (!r
->SASL
.secblob
) {
1207 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1209 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1210 tmp_blob
.data
, tmp_blob
.length
);
1211 data_blob_free(&tmp_blob
);
1213 r
->SASL
.secblob
= NULL
;
1219 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1220 msg
->type
= LDAP_TAG_UnbindRequest
;
1221 asn1_start_tag(data
, tag
);
1226 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1227 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1228 int sizelimit
, timelimit
;
1229 const char **attrs
= NULL
;
1230 msg
->type
= LDAP_TAG_SearchRequest
;
1231 asn1_start_tag(data
, tag
);
1232 asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
);
1233 asn1_read_enumerated(data
, (int *)&(r
->scope
));
1234 asn1_read_enumerated(data
, (int *)&(r
->deref
));
1235 asn1_read_Integer(data
, &sizelimit
);
1236 r
->sizelimit
= sizelimit
;
1237 asn1_read_Integer(data
, &timelimit
);
1238 r
->timelimit
= timelimit
;
1239 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
1241 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1242 if (r
->tree
== NULL
) {
1243 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1246 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1248 r
->num_attributes
= 0;
1249 r
->attributes
= NULL
;
1251 while (asn1_tag_remaining(data
) > 0) {
1254 if (!asn1_read_OctetString_talloc(msg
, data
,
1256 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1257 if (!add_string_to_array(msg
, attr
,
1259 &r
->num_attributes
))
1260 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1262 r
->attributes
= attrs
;
1269 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1270 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1271 msg
->type
= LDAP_TAG_SearchResultEntry
;
1272 r
->attributes
= NULL
;
1273 r
->num_attributes
= 0;
1274 asn1_start_tag(data
, tag
);
1275 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1276 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1277 &r
->num_attributes
);
1282 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1283 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1284 msg
->type
= LDAP_TAG_SearchResultDone
;
1285 asn1_start_tag(data
, tag
);
1286 ldap_decode_response(msg
, data
, r
);
1291 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1292 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1293 msg
->type
= LDAP_TAG_SearchResultReference
;
1294 asn1_start_tag(data
, tag
);
1295 asn1_read_OctetString_talloc(msg
, data
, &r
->referral
);
1300 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1301 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1302 msg
->type
= LDAP_TAG_ModifyRequest
;
1303 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
1304 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1305 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1310 while (asn1_tag_remaining(data
) > 0) {
1311 struct ldap_mod mod
;
1314 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1315 asn1_read_enumerated(data
, &v
);
1317 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1319 if (!add_mod_to_array_talloc(msg
, &mod
,
1320 &r
->mods
, &r
->num_mods
)) {
1321 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1330 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1331 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1332 msg
->type
= LDAP_TAG_ModifyResponse
;
1333 asn1_start_tag(data
, tag
);
1334 ldap_decode_response(msg
, data
, r
);
1339 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1340 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1341 msg
->type
= LDAP_TAG_AddRequest
;
1342 asn1_start_tag(data
, tag
);
1343 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1345 r
->attributes
= NULL
;
1346 r
->num_attributes
= 0;
1347 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1348 &r
->num_attributes
);
1354 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1355 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1356 msg
->type
= LDAP_TAG_AddResponse
;
1357 asn1_start_tag(data
, tag
);
1358 ldap_decode_response(msg
, data
, r
);
1363 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1364 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1367 msg
->type
= LDAP_TAG_DelRequest
;
1368 asn1_start_tag(data
,
1369 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1370 len
= asn1_tag_remaining(data
);
1372 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1374 dn
= talloc_array(msg
, char, len
+1);
1377 asn1_read(data
, dn
, len
);
1384 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1385 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1386 msg
->type
= LDAP_TAG_DelResponse
;
1387 asn1_start_tag(data
, tag
);
1388 ldap_decode_response(msg
, data
, r
);
1393 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1394 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1395 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1396 asn1_start_tag(data
,
1397 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
1398 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1399 asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
);
1400 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
1401 r
->newsuperior
= NULL
;
1402 if (asn1_tag_remaining(data
) > 0) {
1405 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1406 len
= asn1_tag_remaining(data
);
1408 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1410 newsup
= talloc_array(msg
, char, len
+1);
1411 if (newsup
== NULL
) {
1412 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1414 asn1_read(data
, newsup
, len
);
1416 r
->newsuperior
= newsup
;
1423 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1424 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1425 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1426 asn1_start_tag(data
, tag
);
1427 ldap_decode_response(msg
, data
, r
);
1432 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1433 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1434 msg
->type
= LDAP_TAG_CompareRequest
;
1435 asn1_start_tag(data
,
1436 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
1437 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1438 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1439 asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
);
1440 asn1_read_OctetString(data
, msg
, &r
->value
);
1441 if (r
->value
.data
) {
1442 talloc_steal(msg
, r
->value
.data
);
1449 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1450 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1451 msg
->type
= LDAP_TAG_CompareResponse
;
1452 asn1_start_tag(data
, tag
);
1453 ldap_decode_response(msg
, data
, r
);
1458 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1459 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1460 msg
->type
= LDAP_TAG_AbandonRequest
;
1461 asn1_start_tag(data
, tag
);
1462 asn1_read_implicit_Integer(data
, &r
->messageid
);
1467 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1468 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1469 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1471 msg
->type
= LDAP_TAG_ExtendedRequest
;
1472 asn1_start_tag(data
,tag
);
1473 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1474 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1476 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1477 data_blob_free(&tmp_blob
);
1479 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1482 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1483 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1484 r
->value
= talloc(msg
, DATA_BLOB
);
1486 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1488 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1489 data_blob_free(&tmp_blob
);
1498 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1499 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1500 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1502 msg
->type
= LDAP_TAG_ExtendedResponse
;
1503 asn1_start_tag(data
, tag
);
1504 ldap_decode_response(msg
, data
, &r
->response
);
1506 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1507 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1508 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1509 data_blob_free(&tmp_blob
);
1511 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1517 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1518 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1519 r
->value
= talloc(msg
, DATA_BLOB
);
1521 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1523 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1524 data_blob_free(&tmp_blob
);
1533 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1536 msg
->controls
= NULL
;
1537 msg
->controls_decoded
= NULL
;
1539 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1541 struct ldb_control
**ctrl
= NULL
;
1542 bool *decoded
= NULL
;
1544 asn1_start_tag(data
, ASN1_CONTEXT(0));
1546 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1548 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1550 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1552 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1555 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1557 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1560 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1565 if (!ldap_decode_control_wrapper(ctrl
, data
, ctrl
[i
], &value
)) {
1566 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1569 if (!ldap_decode_control_value(ctrl
, value
,
1572 if (ctrl
[i
]->critical
) {
1573 ctrl
[i
]->data
= NULL
;
1577 talloc_free(ctrl
[i
]);
1590 msg
->controls
= ctrl
;
1591 msg
->controls_decoded
= decoded
;
1597 if ((data
->has_error
) || (data
->nesting
!= NULL
)) {
1598 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1600 return NT_STATUS_OK
;
1605 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1606 ldap packet. Set packet_size if true.
1608 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1610 return asn1_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);