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
.chunks
&& tree
->u
.substring
.chunks
[0]) {
275 if (!tree
->u
.substring
.start_with_wildcard
) {
276 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
277 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
281 while (tree
->u
.substring
.chunks
[i
]) {
284 if (( ! tree
->u
.substring
.chunks
[i
+ 1]) &&
285 (tree
->u
.substring
.end_with_wildcard
== 0)) {
290 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(ctx
));
291 asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
]);
301 /* greaterOrEqual test */
302 asn1_push_tag(data
, ASN1_CONTEXT(5));
303 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
304 strlen(tree
->u
.comparison
.attr
));
305 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
306 tree
->u
.comparison
.value
.length
);
311 /* lessOrEqual test */
312 asn1_push_tag(data
, ASN1_CONTEXT(6));
313 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
314 strlen(tree
->u
.comparison
.attr
));
315 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
316 tree
->u
.comparison
.value
.length
);
322 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(7));
323 asn1_write_LDAPString(data
, tree
->u
.present
.attr
);
325 return !data
->has_error
;
329 asn1_push_tag(data
, ASN1_CONTEXT(8));
330 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
331 strlen(tree
->u
.comparison
.attr
));
332 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
333 tree
->u
.comparison
.value
.length
);
337 case LDB_OP_EXTENDED
:
339 MatchingRuleAssertion ::= SEQUENCE {
340 matchingRule [1] MatchingRuleID OPTIONAL,
341 type [2] AttributeDescription OPTIONAL,
342 matchValue [3] AssertionValue,
343 dnAttributes [4] BOOLEAN DEFAULT FALSE
346 asn1_push_tag(data
, ASN1_CONTEXT(9));
347 if (tree
->u
.extended
.rule_id
) {
348 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
349 asn1_write_LDAPString(data
, tree
->u
.extended
.rule_id
);
352 if (tree
->u
.extended
.attr
) {
353 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2));
354 asn1_write_LDAPString(data
, tree
->u
.extended
.attr
);
357 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3));
358 asn1_write_DATA_BLOB_LDAPString(data
, &tree
->u
.extended
.value
);
360 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4));
361 asn1_write_uint8(data
, tree
->u
.extended
.dnAttributes
);
369 return !data
->has_error
;
372 static void ldap_encode_response(struct asn1_data
*data
, struct ldap_Result
*result
)
374 asn1_write_enumerated(data
, result
->resultcode
);
375 asn1_write_OctetString(data
, result
->dn
,
376 (result
->dn
) ? strlen(result
->dn
) : 0);
377 asn1_write_OctetString(data
, result
->errormessage
,
378 (result
->errormessage
) ?
379 strlen(result
->errormessage
) : 0);
380 if (result
->referral
) {
381 asn1_push_tag(data
, ASN1_CONTEXT(3));
382 asn1_write_OctetString(data
, result
->referral
,
383 strlen(result
->referral
));
388 _PUBLIC_
bool ldap_encode(struct ldap_message
*msg
,
389 const struct ldap_control_handler
*control_handlers
,
390 DATA_BLOB
*result
, TALLOC_CTX
*mem_ctx
)
392 struct asn1_data
*data
= asn1_init(mem_ctx
);
395 if (!data
) return false;
397 asn1_push_tag(data
, ASN1_SEQUENCE(0));
398 asn1_write_Integer(data
, msg
->messageid
);
401 case LDAP_TAG_BindRequest
: {
402 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
403 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
404 asn1_write_Integer(data
, r
->version
);
405 asn1_write_OctetString(data
, r
->dn
,
406 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0);
408 switch (r
->mechanism
) {
409 case LDAP_AUTH_MECH_SIMPLE
:
410 /* context, primitive */
411 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
412 asn1_write(data
, r
->creds
.password
,
413 strlen(r
->creds
.password
));
416 case LDAP_AUTH_MECH_SASL
:
417 /* context, constructed */
418 asn1_push_tag(data
, ASN1_CONTEXT(3));
419 asn1_write_OctetString(data
, r
->creds
.SASL
.mechanism
,
420 strlen(r
->creds
.SASL
.mechanism
));
421 if (r
->creds
.SASL
.secblob
) {
422 asn1_write_OctetString(data
, r
->creds
.SASL
.secblob
->data
,
423 r
->creds
.SASL
.secblob
->length
);
434 case LDAP_TAG_BindResponse
: {
435 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
436 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
437 ldap_encode_response(data
, &r
->response
);
438 if (r
->SASL
.secblob
) {
439 asn1_write_ContextSimple(data
, 7, r
->SASL
.secblob
);
444 case LDAP_TAG_UnbindRequest
: {
445 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
446 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
450 case LDAP_TAG_SearchRequest
: {
451 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
452 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
453 asn1_write_OctetString(data
, r
->basedn
, strlen(r
->basedn
));
454 asn1_write_enumerated(data
, r
->scope
);
455 asn1_write_enumerated(data
, r
->deref
);
456 asn1_write_Integer(data
, r
->sizelimit
);
457 asn1_write_Integer(data
, r
->timelimit
);
458 asn1_write_BOOLEAN(data
, r
->attributesonly
);
460 if (!ldap_push_filter(data
, r
->tree
)) {
464 asn1_push_tag(data
, ASN1_SEQUENCE(0));
465 for (i
=0; i
<r
->num_attributes
; i
++) {
466 asn1_write_OctetString(data
, r
->attributes
[i
],
467 strlen(r
->attributes
[i
]));
473 case LDAP_TAG_SearchResultEntry
: {
474 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
475 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
476 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
477 asn1_push_tag(data
, ASN1_SEQUENCE(0));
478 for (i
=0; i
<r
->num_attributes
; i
++) {
479 struct ldb_message_element
*attr
= &r
->attributes
[i
];
480 asn1_push_tag(data
, ASN1_SEQUENCE(0));
481 asn1_write_OctetString(data
, attr
->name
,
483 asn1_push_tag(data
, ASN1_SEQUENCE(1));
484 for (j
=0; j
<attr
->num_values
; j
++) {
485 asn1_write_OctetString(data
,
486 attr
->values
[j
].data
,
487 attr
->values
[j
].length
);
496 case LDAP_TAG_SearchResultDone
: {
497 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
498 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
499 ldap_encode_response(data
, r
);
503 case LDAP_TAG_ModifyRequest
: {
504 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
505 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
506 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
507 asn1_push_tag(data
, ASN1_SEQUENCE(0));
509 for (i
=0; i
<r
->num_mods
; i
++) {
510 struct ldb_message_element
*attrib
= &r
->mods
[i
].attrib
;
511 asn1_push_tag(data
, ASN1_SEQUENCE(0));
512 asn1_write_enumerated(data
, r
->mods
[i
].type
);
513 asn1_push_tag(data
, ASN1_SEQUENCE(0));
514 asn1_write_OctetString(data
, attrib
->name
,
515 strlen(attrib
->name
));
516 asn1_push_tag(data
, ASN1_SET
);
517 for (j
=0; j
<attrib
->num_values
; j
++) {
518 asn1_write_OctetString(data
,
519 attrib
->values
[j
].data
,
520 attrib
->values
[j
].length
);
532 case LDAP_TAG_ModifyResponse
: {
533 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
534 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
535 ldap_encode_response(data
, r
);
539 case LDAP_TAG_AddRequest
: {
540 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
541 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
542 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
543 asn1_push_tag(data
, ASN1_SEQUENCE(0));
545 for (i
=0; i
<r
->num_attributes
; i
++) {
546 struct ldb_message_element
*attrib
= &r
->attributes
[i
];
547 asn1_push_tag(data
, ASN1_SEQUENCE(0));
548 asn1_write_OctetString(data
, attrib
->name
,
549 strlen(attrib
->name
));
550 asn1_push_tag(data
, ASN1_SET
);
551 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
552 asn1_write_OctetString(data
,
553 attrib
->values
[j
].data
,
554 attrib
->values
[j
].length
);
563 case LDAP_TAG_AddResponse
: {
564 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
565 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
566 ldap_encode_response(data
, r
);
570 case LDAP_TAG_DelRequest
: {
571 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
572 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
573 asn1_write(data
, r
->dn
, strlen(r
->dn
));
577 case LDAP_TAG_DelResponse
: {
578 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
579 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
580 ldap_encode_response(data
, r
);
584 case LDAP_TAG_ModifyDNRequest
: {
585 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
586 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
587 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
588 asn1_write_OctetString(data
, r
->newrdn
, strlen(r
->newrdn
));
589 asn1_write_BOOLEAN(data
, r
->deleteolddn
);
590 if (r
->newsuperior
) {
591 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
592 asn1_write(data
, r
->newsuperior
,
593 strlen(r
->newsuperior
));
599 case LDAP_TAG_ModifyDNResponse
: {
600 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
601 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
602 ldap_encode_response(data
, r
);
606 case LDAP_TAG_CompareRequest
: {
607 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
608 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
609 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
610 asn1_push_tag(data
, ASN1_SEQUENCE(0));
611 asn1_write_OctetString(data
, r
->attribute
,
612 strlen(r
->attribute
));
613 asn1_write_OctetString(data
, r
->value
.data
,
619 case LDAP_TAG_CompareResponse
: {
620 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
621 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
622 ldap_encode_response(data
, r
);
626 case LDAP_TAG_AbandonRequest
: {
627 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
628 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
629 asn1_write_implicit_Integer(data
, r
->messageid
);
633 case LDAP_TAG_SearchResultReference
: {
634 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
635 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
636 asn1_write_OctetString(data
, r
->referral
, strlen(r
->referral
));
640 case LDAP_TAG_ExtendedRequest
: {
641 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
642 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
643 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
644 asn1_write(data
, r
->oid
, strlen(r
->oid
));
647 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
648 asn1_write(data
, r
->value
->data
, r
->value
->length
);
654 case LDAP_TAG_ExtendedResponse
: {
655 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
656 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
657 ldap_encode_response(data
, &r
->response
);
659 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10));
660 asn1_write(data
, r
->oid
, strlen(r
->oid
));
664 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11));
665 asn1_write(data
, r
->value
->data
, r
->value
->length
);
675 if (msg
->controls
!= NULL
) {
676 asn1_push_tag(data
, ASN1_CONTEXT(0));
678 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
679 if (!ldap_encode_control(mem_ctx
, data
,
682 DEBUG(0,("Unable to encode control %s\n",
683 msg
->controls
[i
]->oid
));
693 if (data
->has_error
) {
698 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
703 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
706 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
707 memcpy(result
, blob
.data
, blob
.length
);
708 result
[blob
.length
] = '\0';
712 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
713 struct asn1_data
*data
,
717 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
719 *result
= blob2string_talloc(mem_ctx
, string
);
720 data_blob_free(&string
);
724 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
725 struct asn1_data
*data
,
726 struct ldap_Result
*result
)
728 asn1_read_enumerated(data
, &result
->resultcode
);
729 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
730 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
731 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
732 asn1_start_tag(data
, ASN1_CONTEXT(3));
733 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
736 result
->referral
= NULL
;
740 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
743 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
744 if (chunks
== NULL
) {
748 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
749 if (chunks
[chunk_num
] == NULL
) {
753 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
754 if (chunks
[chunk_num
]->data
== NULL
) {
757 chunks
[chunk_num
]->length
= strlen(value
);
759 chunks
[chunk_num
+ 1] = '\0';
766 parse the ASN.1 formatted search string into a ldb_parse_tree
768 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
769 struct asn1_data
*data
)
772 struct ldb_parse_tree
*ret
;
774 if (!asn1_peek_uint8(data
, &filter_tag
)) {
778 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
780 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
781 if (ret
== NULL
) return NULL
;
786 /* AND or OR of one or more filters */
787 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
788 ret
->u
.list
.num_elements
= 0;
789 ret
->u
.list
.elements
= NULL
;
791 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
795 while (asn1_tag_remaining(data
) > 0) {
796 struct ldb_parse_tree
*subtree
;
797 subtree
= ldap_decode_filter_tree(ret
, data
);
798 if (subtree
== NULL
) {
801 ret
->u
.list
.elements
=
802 talloc_realloc(ret
, ret
->u
.list
.elements
,
803 struct ldb_parse_tree
*,
804 ret
->u
.list
.num_elements
+1);
805 if (ret
->u
.list
.elements
== NULL
) {
808 talloc_steal(ret
->u
.list
.elements
, subtree
);
809 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
810 ret
->u
.list
.num_elements
++;
812 if (!asn1_end_tag(data
)) {
818 /* 'not' operation */
819 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
823 ret
->operation
= LDB_OP_NOT
;
824 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
825 if (ret
->u
.isnot
.child
== NULL
) {
828 if (!asn1_end_tag(data
)) {
838 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
839 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
840 asn1_read_OctetString(data
, mem_ctx
, &value
);
842 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
846 ret
->operation
= LDB_OP_EQUALITY
;
847 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
848 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
849 ret
->u
.equality
.value
.length
= value
.length
;
859 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
862 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
866 ret
->operation
= LDB_OP_SUBSTRING
;
867 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
868 ret
->u
.substring
.chunks
= NULL
;
869 ret
->u
.substring
.start_with_wildcard
= 1;
870 ret
->u
.substring
.end_with_wildcard
= 1;
872 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
876 while (asn1_tag_remaining(data
)) {
877 asn1_peek_uint8(data
, &subs_tag
);
878 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
879 if (subs_tag
> 2) goto failed
;
881 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
));
882 asn1_read_LDAPString(data
, mem_ctx
, &value
);
887 if (ret
->u
.substring
.chunks
!= NULL
) {
888 /* initial value found in the middle */
892 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
893 if (ret
->u
.substring
.chunks
== NULL
) {
897 ret
->u
.substring
.start_with_wildcard
= 0;
902 if (ret
->u
.substring
.end_with_wildcard
== 0) {
903 /* "any" value found after a "final" value */
907 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
908 ret
->u
.substring
.chunks
,
911 if (ret
->u
.substring
.chunks
== NULL
) {
919 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
920 ret
->u
.substring
.chunks
,
923 if (ret
->u
.substring
.chunks
== NULL
) {
927 ret
->u
.substring
.end_with_wildcard
= 0;
936 if (!asn1_end_tag(data
)) { /* SEQUENCE */
940 if (!asn1_end_tag(data
)) {
950 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
951 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
952 asn1_read_OctetString(data
, mem_ctx
, &value
);
954 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
958 ret
->operation
= LDB_OP_GREATER
;
959 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
960 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
961 ret
->u
.comparison
.value
.length
= value
.length
;
969 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
970 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
971 asn1_read_OctetString(data
, mem_ctx
, &value
);
973 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
977 ret
->operation
= LDB_OP_LESS
;
978 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
979 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
980 ret
->u
.comparison
.value
.length
= value
.length
;
984 /* Normal presence, "attribute=*" */
987 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
990 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
994 ret
->operation
= LDB_OP_PRESENT
;
995 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
997 if (!asn1_end_tag(data
)) {
1007 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
1008 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
1009 asn1_read_OctetString(data
, mem_ctx
, &value
);
1011 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
1015 ret
->operation
= LDB_OP_APPROX
;
1016 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
1017 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
1018 ret
->u
.comparison
.value
.length
= value
.length
;
1022 char *oid
= NULL
, *attr
= NULL
, *value
;
1023 uint8_t dnAttributes
;
1024 /* an extended search */
1025 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
1029 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1030 we need to check we properly implement --SSS */
1031 /* either oid or type must be defined */
1032 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1033 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1));
1034 asn1_read_LDAPString(data
, ret
, &oid
);
1037 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1038 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2));
1039 asn1_read_LDAPString(data
, ret
, &attr
);
1042 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
1043 asn1_read_LDAPString(data
, ret
, &value
);
1045 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1046 it is not marked as OPTIONAL but openldap tools
1047 do not set this unless it is to be set as TRUE
1048 NOTE: openldap tools do not work with AD as it
1049 seems that AD always requires the dnAttributes
1050 boolean value to be set */
1051 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
1052 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4));
1053 asn1_read_uint8(data
, &dnAttributes
);
1058 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
1063 ret
->operation
= LDB_OP_EXTENDED
;
1065 /* From the RFC2251: If the type field is
1066 absent and matchingRule is present, the matchValue is compared
1067 against all attributes in an entry which support that matchingRule
1070 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
1072 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
1074 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
1075 ret
->u
.extended
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1076 ret
->u
.extended
.value
.length
= strlen(value
);
1077 ret
->u
.extended
.dnAttributes
= dnAttributes
;
1079 ret
->operation
= LDB_OP_EQUALITY
;
1080 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
1081 ret
->u
.equality
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1082 ret
->u
.equality
.value
.length
= strlen(value
);
1084 if (!asn1_end_tag(data
)) {
1101 /* Decode a single LDAP attribute, possibly containing multiple values */
1102 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1103 struct ldb_message_element
*attrib
)
1105 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1106 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
1107 asn1_start_tag(data
, ASN1_SET
);
1108 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
1110 asn1_read_OctetString(data
, mem_ctx
, &blob
);
1111 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
1118 /* Decode a set of LDAP attributes, as found in the dereference control */
1119 void ldap_decode_attribs_bare(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1120 struct ldb_message_element
**attributes
,
1121 int *num_attributes
)
1123 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1124 struct ldb_message_element attrib
;
1125 ZERO_STRUCT(attrib
);
1126 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
1127 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
1128 attributes
, num_attributes
);
1132 /* Decode a set of LDAP attributes, as found in a search entry */
1133 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1134 struct ldb_message_element
**attributes
,
1135 int *num_attributes
)
1137 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1138 ldap_decode_attribs_bare(mem_ctx
, data
,
1139 attributes
, num_attributes
);
1143 /* This routine returns LDAP status codes */
1145 _PUBLIC_ NTSTATUS
ldap_decode(struct asn1_data
*data
,
1146 const struct ldap_control_handler
*control_handlers
,
1147 struct ldap_message
*msg
)
1151 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1152 asn1_read_Integer(data
, &msg
->messageid
);
1154 if (!asn1_peek_uint8(data
, &tag
))
1155 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1159 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
1160 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
1161 msg
->type
= LDAP_TAG_BindRequest
;
1162 asn1_start_tag(data
, tag
);
1163 asn1_read_Integer(data
, &r
->version
);
1164 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1165 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
1167 r
->creds
.password
= "";
1168 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
1169 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1170 pwlen
= asn1_tag_remaining(data
);
1172 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1175 char *pw
= talloc_array(msg
, char, pwlen
+1);
1177 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1179 asn1_read(data
, pw
, pwlen
);
1181 r
->creds
.password
= pw
;
1184 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
1185 asn1_start_tag(data
, ASN1_CONTEXT(3));
1186 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
1187 asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
);
1188 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
1189 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1190 asn1_read_OctetString(data
, msg
, &tmp_blob
);
1191 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1192 if (!r
->creds
.SASL
.secblob
) {
1193 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1195 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
1196 tmp_blob
.data
, tmp_blob
.length
);
1197 data_blob_free(&tmp_blob
);
1199 r
->creds
.SASL
.secblob
= NULL
;
1203 /* Neither Simple nor SASL bind */
1204 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1210 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
1211 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
1212 msg
->type
= LDAP_TAG_BindResponse
;
1213 asn1_start_tag(data
, tag
);
1214 ldap_decode_response(msg
, data
, &r
->response
);
1215 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
1216 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1217 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
1218 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1219 if (!r
->SASL
.secblob
) {
1220 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1222 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1223 tmp_blob
.data
, tmp_blob
.length
);
1224 data_blob_free(&tmp_blob
);
1226 r
->SASL
.secblob
= NULL
;
1232 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1233 msg
->type
= LDAP_TAG_UnbindRequest
;
1234 asn1_start_tag(data
, tag
);
1239 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1240 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1241 int sizelimit
, timelimit
;
1242 const char **attrs
= NULL
;
1243 msg
->type
= LDAP_TAG_SearchRequest
;
1244 asn1_start_tag(data
, tag
);
1245 asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
);
1246 asn1_read_enumerated(data
, (int *)(void *)&(r
->scope
));
1247 asn1_read_enumerated(data
, (int *)(void *)&(r
->deref
));
1248 asn1_read_Integer(data
, &sizelimit
);
1249 r
->sizelimit
= sizelimit
;
1250 asn1_read_Integer(data
, &timelimit
);
1251 r
->timelimit
= timelimit
;
1252 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
1254 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1255 if (r
->tree
== NULL
) {
1256 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1259 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1261 r
->num_attributes
= 0;
1262 r
->attributes
= NULL
;
1264 while (asn1_tag_remaining(data
) > 0) {
1267 if (!asn1_read_OctetString_talloc(msg
, data
,
1269 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1270 if (!add_string_to_array(msg
, attr
,
1272 &r
->num_attributes
))
1273 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1275 r
->attributes
= attrs
;
1282 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1283 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1284 msg
->type
= LDAP_TAG_SearchResultEntry
;
1285 r
->attributes
= NULL
;
1286 r
->num_attributes
= 0;
1287 asn1_start_tag(data
, tag
);
1288 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1289 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1290 &r
->num_attributes
);
1295 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1296 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1297 msg
->type
= LDAP_TAG_SearchResultDone
;
1298 asn1_start_tag(data
, tag
);
1299 ldap_decode_response(msg
, data
, r
);
1304 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1305 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1306 msg
->type
= LDAP_TAG_SearchResultReference
;
1307 asn1_start_tag(data
, tag
);
1308 asn1_read_OctetString_talloc(msg
, data
, &r
->referral
);
1313 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1314 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1315 msg
->type
= LDAP_TAG_ModifyRequest
;
1316 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
1317 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1318 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1323 while (asn1_tag_remaining(data
) > 0) {
1324 struct ldap_mod mod
;
1327 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1328 asn1_read_enumerated(data
, &v
);
1330 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1332 if (!add_mod_to_array_talloc(msg
, &mod
,
1333 &r
->mods
, &r
->num_mods
)) {
1334 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1343 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1344 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1345 msg
->type
= LDAP_TAG_ModifyResponse
;
1346 asn1_start_tag(data
, tag
);
1347 ldap_decode_response(msg
, data
, r
);
1352 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1353 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1354 msg
->type
= LDAP_TAG_AddRequest
;
1355 asn1_start_tag(data
, tag
);
1356 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1358 r
->attributes
= NULL
;
1359 r
->num_attributes
= 0;
1360 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1361 &r
->num_attributes
);
1367 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1368 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1369 msg
->type
= LDAP_TAG_AddResponse
;
1370 asn1_start_tag(data
, tag
);
1371 ldap_decode_response(msg
, data
, r
);
1376 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1377 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1380 msg
->type
= LDAP_TAG_DelRequest
;
1381 asn1_start_tag(data
,
1382 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1383 len
= asn1_tag_remaining(data
);
1385 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1387 dn
= talloc_array(msg
, char, len
+1);
1390 asn1_read(data
, dn
, len
);
1397 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1398 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1399 msg
->type
= LDAP_TAG_DelResponse
;
1400 asn1_start_tag(data
, tag
);
1401 ldap_decode_response(msg
, data
, r
);
1406 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1407 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1408 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1409 asn1_start_tag(data
,
1410 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
1411 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1412 asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
);
1413 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
1414 r
->newsuperior
= NULL
;
1415 if (asn1_tag_remaining(data
) > 0) {
1418 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1419 len
= asn1_tag_remaining(data
);
1421 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1423 newsup
= talloc_array(msg
, char, len
+1);
1424 if (newsup
== NULL
) {
1425 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1427 asn1_read(data
, newsup
, len
);
1429 r
->newsuperior
= newsup
;
1436 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1437 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1438 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1439 asn1_start_tag(data
, tag
);
1440 ldap_decode_response(msg
, data
, r
);
1445 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1446 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1447 msg
->type
= LDAP_TAG_CompareRequest
;
1448 asn1_start_tag(data
,
1449 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
1450 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1451 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1452 asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
);
1453 asn1_read_OctetString(data
, msg
, &r
->value
);
1454 if (r
->value
.data
) {
1455 talloc_steal(msg
, r
->value
.data
);
1462 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1463 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1464 msg
->type
= LDAP_TAG_CompareResponse
;
1465 asn1_start_tag(data
, tag
);
1466 ldap_decode_response(msg
, data
, r
);
1471 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1472 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1473 msg
->type
= LDAP_TAG_AbandonRequest
;
1474 asn1_start_tag(data
, tag
);
1475 asn1_read_implicit_Integer(data
, &r
->messageid
);
1480 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1481 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1482 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1484 msg
->type
= LDAP_TAG_ExtendedRequest
;
1485 asn1_start_tag(data
,tag
);
1486 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1487 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1489 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1490 data_blob_free(&tmp_blob
);
1492 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1495 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1496 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1497 r
->value
= talloc(msg
, DATA_BLOB
);
1499 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1501 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1502 data_blob_free(&tmp_blob
);
1511 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1512 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1513 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1515 msg
->type
= LDAP_TAG_ExtendedResponse
;
1516 asn1_start_tag(data
, tag
);
1517 ldap_decode_response(msg
, data
, &r
->response
);
1519 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1520 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1521 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1522 data_blob_free(&tmp_blob
);
1524 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1530 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1531 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1532 r
->value
= talloc(msg
, DATA_BLOB
);
1534 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1536 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1537 data_blob_free(&tmp_blob
);
1546 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1549 msg
->controls
= NULL
;
1550 msg
->controls_decoded
= NULL
;
1552 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1554 struct ldb_control
**ctrl
= NULL
;
1555 bool *decoded
= NULL
;
1557 asn1_start_tag(data
, ASN1_CONTEXT(0));
1559 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1561 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1563 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1565 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1568 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1570 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1573 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1575 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1578 if (!ldap_decode_control_wrapper(ctrl
[i
], data
, ctrl
[i
], &value
)) {
1579 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1582 if (!ldap_decode_control_value(ctrl
[i
], value
,
1585 if (ctrl
[i
]->critical
) {
1586 ctrl
[i
]->data
= NULL
;
1590 talloc_free(ctrl
[i
]);
1603 msg
->controls
= ctrl
;
1604 msg
->controls_decoded
= decoded
;
1610 if ((data
->has_error
) || (data
->nesting
!= NULL
)) {
1611 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1613 return NT_STATUS_OK
;
1618 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1619 ldap packet. Set packet_size if true.
1621 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1623 if (blob
.length
< 6) {
1625 * We need at least 6 bytes to workout the length
1628 return STATUS_MORE_ENTRIES
;
1630 return asn1_peek_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);