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
,
671 DEBUG(1,("Unable to encode control %s\n",
672 msg
->controls
[i
]->oid
));
682 if (data
->has_error
) {
687 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
692 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
695 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
696 memcpy(result
, blob
.data
, blob
.length
);
697 result
[blob
.length
] = '\0';
701 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
702 struct asn1_data
*data
,
706 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
708 *result
= blob2string_talloc(mem_ctx
, string
);
709 data_blob_free(&string
);
713 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
714 struct asn1_data
*data
,
715 struct ldap_Result
*result
)
717 asn1_read_enumerated(data
, &result
->resultcode
);
718 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
719 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
720 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
721 asn1_start_tag(data
, ASN1_CONTEXT(3));
722 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
725 result
->referral
= NULL
;
729 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
732 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
733 if (chunks
== NULL
) {
737 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
738 if (chunks
[chunk_num
] == NULL
) {
742 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
743 if (chunks
[chunk_num
]->data
== NULL
) {
746 chunks
[chunk_num
]->length
= strlen(value
);
748 chunks
[chunk_num
+ 1] = '\0';
755 parse the ASN.1 formatted search string into a ldb_parse_tree
757 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
758 struct asn1_data
*data
)
761 struct ldb_parse_tree
*ret
;
763 if (!asn1_peek_uint8(data
, &filter_tag
)) {
767 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
769 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
770 if (ret
== NULL
) return NULL
;
775 /* AND or OR of one or more filters */
776 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
777 ret
->u
.list
.num_elements
= 0;
778 ret
->u
.list
.elements
= NULL
;
780 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
784 while (asn1_tag_remaining(data
) > 0) {
785 struct ldb_parse_tree
*subtree
;
786 subtree
= ldap_decode_filter_tree(ret
, data
);
787 if (subtree
== NULL
) {
790 ret
->u
.list
.elements
=
791 talloc_realloc(ret
, ret
->u
.list
.elements
,
792 struct ldb_parse_tree
*,
793 ret
->u
.list
.num_elements
+1);
794 if (ret
->u
.list
.elements
== NULL
) {
797 talloc_steal(ret
->u
.list
.elements
, subtree
);
798 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
799 ret
->u
.list
.num_elements
++;
801 if (!asn1_end_tag(data
)) {
807 /* 'not' operation */
808 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
812 ret
->operation
= LDB_OP_NOT
;
813 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
814 if (ret
->u
.isnot
.child
== NULL
) {
817 if (!asn1_end_tag(data
)) {
827 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
828 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
829 asn1_read_OctetString(data
, mem_ctx
, &value
);
831 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
835 ret
->operation
= LDB_OP_EQUALITY
;
836 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
837 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
838 ret
->u
.equality
.value
.length
= value
.length
;
848 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
851 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
855 ret
->operation
= LDB_OP_SUBSTRING
;
856 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
857 ret
->u
.substring
.chunks
= NULL
;
858 ret
->u
.substring
.start_with_wildcard
= 1;
859 ret
->u
.substring
.end_with_wildcard
= 1;
861 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
865 while (asn1_tag_remaining(data
)) {
866 asn1_peek_uint8(data
, &subs_tag
);
867 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
868 if (subs_tag
> 2) goto failed
;
870 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
));
871 asn1_read_LDAPString(data
, mem_ctx
, &value
);
876 if (ret
->u
.substring
.chunks
!= NULL
) {
877 /* initial value found in the middle */
881 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
882 if (ret
->u
.substring
.chunks
== NULL
) {
886 ret
->u
.substring
.start_with_wildcard
= 0;
891 if (ret
->u
.substring
.end_with_wildcard
== 0) {
892 /* "any" value found after a "final" value */
896 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
897 ret
->u
.substring
.chunks
,
900 if (ret
->u
.substring
.chunks
== NULL
) {
908 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
909 ret
->u
.substring
.chunks
,
912 if (ret
->u
.substring
.chunks
== NULL
) {
916 ret
->u
.substring
.end_with_wildcard
= 0;
925 if (!asn1_end_tag(data
)) { /* SEQUENCE */
929 if (!asn1_end_tag(data
)) {
939 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
940 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
941 asn1_read_OctetString(data
, mem_ctx
, &value
);
943 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
947 ret
->operation
= LDB_OP_GREATER
;
948 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
949 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
950 ret
->u
.comparison
.value
.length
= value
.length
;
958 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
959 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
960 asn1_read_OctetString(data
, mem_ctx
, &value
);
962 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
966 ret
->operation
= LDB_OP_LESS
;
967 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
968 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
969 ret
->u
.comparison
.value
.length
= value
.length
;
973 /* Normal presence, "attribute=*" */
976 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
979 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
983 ret
->operation
= LDB_OP_PRESENT
;
984 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
986 if (!asn1_end_tag(data
)) {
996 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
997 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
998 asn1_read_OctetString(data
, mem_ctx
, &value
);
1000 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
1004 ret
->operation
= LDB_OP_APPROX
;
1005 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
1006 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
1007 ret
->u
.comparison
.value
.length
= value
.length
;
1011 char *oid
= NULL
, *attr
= NULL
, *value
;
1012 uint8_t dnAttributes
;
1013 /* an extended search */
1014 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
1018 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1019 we need to check we properly implement --SSS */
1020 /* either oid or type must be defined */
1021 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1022 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1));
1023 asn1_read_LDAPString(data
, ret
, &oid
);
1026 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1027 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2));
1028 asn1_read_LDAPString(data
, ret
, &attr
);
1031 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
1032 asn1_read_LDAPString(data
, ret
, &value
);
1034 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1035 it is not marked as OPTIONAL but openldap tools
1036 do not set this unless it is to be set as TRUE
1037 NOTE: openldap tools do not work with AD as it
1038 seems that AD always requires the dnAttributes
1039 boolean value to be set */
1040 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
1041 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4));
1042 asn1_read_uint8(data
, &dnAttributes
);
1047 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
1052 ret
->operation
= LDB_OP_EXTENDED
;
1054 /* From the RFC2251: If the type field is
1055 absent and matchingRule is present, the matchValue is compared
1056 against all attributes in an entry which support that matchingRule
1059 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
1061 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
1063 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
1064 ret
->u
.extended
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1065 ret
->u
.extended
.value
.length
= strlen(value
);
1066 ret
->u
.extended
.dnAttributes
= dnAttributes
;
1068 ret
->operation
= LDB_OP_EQUALITY
;
1069 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
1070 ret
->u
.equality
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1071 ret
->u
.equality
.value
.length
= strlen(value
);
1073 if (!asn1_end_tag(data
)) {
1090 /* Decode a single LDAP attribute, possibly containing multiple values */
1091 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1092 struct ldb_message_element
*attrib
)
1094 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1095 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
1096 asn1_start_tag(data
, ASN1_SET
);
1097 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
1099 asn1_read_OctetString(data
, mem_ctx
, &blob
);
1100 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
1107 /* Decode a set of LDAP attributes, as found in the dereference control */
1108 void ldap_decode_attribs_bare(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1109 struct ldb_message_element
**attributes
,
1110 int *num_attributes
)
1112 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1113 struct ldb_message_element attrib
;
1114 ZERO_STRUCT(attrib
);
1115 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
1116 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
1117 attributes
, num_attributes
);
1121 /* Decode a set of LDAP attributes, as found in a search entry */
1122 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1123 struct ldb_message_element
**attributes
,
1124 int *num_attributes
)
1126 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1127 ldap_decode_attribs_bare(mem_ctx
, data
,
1128 attributes
, num_attributes
);
1132 /* This routine returns LDAP status codes */
1134 _PUBLIC_ NTSTATUS
ldap_decode(struct asn1_data
*data
,
1135 const struct ldap_control_handler
*control_handlers
,
1136 struct ldap_message
*msg
)
1140 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1141 asn1_read_Integer(data
, &msg
->messageid
);
1143 if (!asn1_peek_uint8(data
, &tag
))
1144 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1148 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
1149 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
1150 msg
->type
= LDAP_TAG_BindRequest
;
1151 asn1_start_tag(data
, tag
);
1152 asn1_read_Integer(data
, &r
->version
);
1153 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1154 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
1156 r
->creds
.password
= "";
1157 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
1158 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1159 pwlen
= asn1_tag_remaining(data
);
1161 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1164 char *pw
= talloc_array(msg
, char, pwlen
+1);
1166 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1168 asn1_read(data
, pw
, pwlen
);
1170 r
->creds
.password
= pw
;
1173 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
1174 asn1_start_tag(data
, ASN1_CONTEXT(3));
1175 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
1176 asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
);
1177 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
1178 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1179 asn1_read_OctetString(data
, msg
, &tmp_blob
);
1180 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1181 if (!r
->creds
.SASL
.secblob
) {
1182 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1184 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
1185 tmp_blob
.data
, tmp_blob
.length
);
1186 data_blob_free(&tmp_blob
);
1188 r
->creds
.SASL
.secblob
= NULL
;
1192 /* Neither Simple nor SASL bind */
1193 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1199 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
1200 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
1201 msg
->type
= LDAP_TAG_BindResponse
;
1202 asn1_start_tag(data
, tag
);
1203 ldap_decode_response(msg
, data
, &r
->response
);
1204 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
1205 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1206 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
1207 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1208 if (!r
->SASL
.secblob
) {
1209 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1211 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1212 tmp_blob
.data
, tmp_blob
.length
);
1213 data_blob_free(&tmp_blob
);
1215 r
->SASL
.secblob
= NULL
;
1221 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1222 msg
->type
= LDAP_TAG_UnbindRequest
;
1223 asn1_start_tag(data
, tag
);
1228 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1229 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1230 int sizelimit
, timelimit
;
1231 const char **attrs
= NULL
;
1232 msg
->type
= LDAP_TAG_SearchRequest
;
1233 asn1_start_tag(data
, tag
);
1234 asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
);
1235 asn1_read_enumerated(data
, (int *)(void *)&(r
->scope
));
1236 asn1_read_enumerated(data
, (int *)(void *)&(r
->deref
));
1237 asn1_read_Integer(data
, &sizelimit
);
1238 r
->sizelimit
= sizelimit
;
1239 asn1_read_Integer(data
, &timelimit
);
1240 r
->timelimit
= timelimit
;
1241 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
1243 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1244 if (r
->tree
== NULL
) {
1245 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1248 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1250 r
->num_attributes
= 0;
1251 r
->attributes
= NULL
;
1253 while (asn1_tag_remaining(data
) > 0) {
1256 if (!asn1_read_OctetString_talloc(msg
, data
,
1258 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1259 if (!add_string_to_array(msg
, attr
,
1261 &r
->num_attributes
))
1262 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1264 r
->attributes
= attrs
;
1271 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1272 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1273 msg
->type
= LDAP_TAG_SearchResultEntry
;
1274 r
->attributes
= NULL
;
1275 r
->num_attributes
= 0;
1276 asn1_start_tag(data
, tag
);
1277 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1278 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1279 &r
->num_attributes
);
1284 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1285 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1286 msg
->type
= LDAP_TAG_SearchResultDone
;
1287 asn1_start_tag(data
, tag
);
1288 ldap_decode_response(msg
, data
, r
);
1293 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1294 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1295 msg
->type
= LDAP_TAG_SearchResultReference
;
1296 asn1_start_tag(data
, tag
);
1297 asn1_read_OctetString_talloc(msg
, data
, &r
->referral
);
1302 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1303 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1304 msg
->type
= LDAP_TAG_ModifyRequest
;
1305 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
1306 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1307 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1312 while (asn1_tag_remaining(data
) > 0) {
1313 struct ldap_mod mod
;
1316 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1317 asn1_read_enumerated(data
, &v
);
1319 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1321 if (!add_mod_to_array_talloc(msg
, &mod
,
1322 &r
->mods
, &r
->num_mods
)) {
1323 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1332 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1333 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1334 msg
->type
= LDAP_TAG_ModifyResponse
;
1335 asn1_start_tag(data
, tag
);
1336 ldap_decode_response(msg
, data
, r
);
1341 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1342 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1343 msg
->type
= LDAP_TAG_AddRequest
;
1344 asn1_start_tag(data
, tag
);
1345 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1347 r
->attributes
= NULL
;
1348 r
->num_attributes
= 0;
1349 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1350 &r
->num_attributes
);
1356 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1357 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1358 msg
->type
= LDAP_TAG_AddResponse
;
1359 asn1_start_tag(data
, tag
);
1360 ldap_decode_response(msg
, data
, r
);
1365 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1366 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1369 msg
->type
= LDAP_TAG_DelRequest
;
1370 asn1_start_tag(data
,
1371 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1372 len
= asn1_tag_remaining(data
);
1374 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1376 dn
= talloc_array(msg
, char, len
+1);
1379 asn1_read(data
, dn
, len
);
1386 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1387 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1388 msg
->type
= LDAP_TAG_DelResponse
;
1389 asn1_start_tag(data
, tag
);
1390 ldap_decode_response(msg
, data
, r
);
1395 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1396 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1397 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1398 asn1_start_tag(data
,
1399 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
1400 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1401 asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
);
1402 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
1403 r
->newsuperior
= NULL
;
1404 if (asn1_tag_remaining(data
) > 0) {
1407 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1408 len
= asn1_tag_remaining(data
);
1410 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1412 newsup
= talloc_array(msg
, char, len
+1);
1413 if (newsup
== NULL
) {
1414 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1416 asn1_read(data
, newsup
, len
);
1418 r
->newsuperior
= newsup
;
1425 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1426 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1427 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1428 asn1_start_tag(data
, tag
);
1429 ldap_decode_response(msg
, data
, r
);
1434 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1435 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1436 msg
->type
= LDAP_TAG_CompareRequest
;
1437 asn1_start_tag(data
,
1438 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
1439 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1440 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1441 asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
);
1442 asn1_read_OctetString(data
, msg
, &r
->value
);
1443 if (r
->value
.data
) {
1444 talloc_steal(msg
, r
->value
.data
);
1451 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1452 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1453 msg
->type
= LDAP_TAG_CompareResponse
;
1454 asn1_start_tag(data
, tag
);
1455 ldap_decode_response(msg
, data
, r
);
1460 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1461 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1462 msg
->type
= LDAP_TAG_AbandonRequest
;
1463 asn1_start_tag(data
, tag
);
1464 asn1_read_implicit_Integer(data
, &r
->messageid
);
1469 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1470 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1471 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1473 msg
->type
= LDAP_TAG_ExtendedRequest
;
1474 asn1_start_tag(data
,tag
);
1475 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1476 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1478 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1479 data_blob_free(&tmp_blob
);
1481 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1484 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1485 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1486 r
->value
= talloc(msg
, DATA_BLOB
);
1488 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1490 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1491 data_blob_free(&tmp_blob
);
1500 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1501 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1502 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1504 msg
->type
= LDAP_TAG_ExtendedResponse
;
1505 asn1_start_tag(data
, tag
);
1506 ldap_decode_response(msg
, data
, &r
->response
);
1508 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1509 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1510 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1511 data_blob_free(&tmp_blob
);
1513 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1519 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1520 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1521 r
->value
= talloc(msg
, DATA_BLOB
);
1523 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1525 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1526 data_blob_free(&tmp_blob
);
1535 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1538 msg
->controls
= NULL
;
1539 msg
->controls_decoded
= NULL
;
1541 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1543 struct ldb_control
**ctrl
= NULL
;
1544 bool *decoded
= NULL
;
1546 asn1_start_tag(data
, ASN1_CONTEXT(0));
1548 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1550 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1552 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1554 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1557 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1559 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1562 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1564 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1567 if (!ldap_decode_control_wrapper(ctrl
, data
, ctrl
[i
], &value
)) {
1568 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1571 if (!ldap_decode_control_value(ctrl
, value
,
1574 if (ctrl
[i
]->critical
) {
1575 ctrl
[i
]->data
= NULL
;
1579 talloc_free(ctrl
[i
]);
1592 msg
->controls
= ctrl
;
1593 msg
->controls_decoded
= decoded
;
1599 if ((data
->has_error
) || (data
->nesting
!= NULL
)) {
1600 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1602 return NT_STATUS_OK
;
1607 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1608 ldap packet. Set packet_size if true.
1610 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1612 return asn1_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);