2 Unix SMB/CIFS implementation.
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 if (!asn1_push_tag(data
, ASN1_CONTEXT(tree
->operation
==LDB_OP_AND
?0:1))) return false;
233 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
234 if (!ldap_push_filter(data
, tree
->u
.list
.elements
[i
])) {
238 if (!asn1_pop_tag(data
)) return false;
242 if (!asn1_push_tag(data
, ASN1_CONTEXT(2))) return false;
243 if (!ldap_push_filter(data
, tree
->u
.isnot
.child
)) {
246 if (!asn1_pop_tag(data
)) return false;
249 case LDB_OP_EQUALITY
:
251 if (!asn1_push_tag(data
, ASN1_CONTEXT(3))) return false;
252 if (!asn1_write_OctetString(data
, tree
->u
.equality
.attr
,
253 strlen(tree
->u
.equality
.attr
))) return false;
254 if (!asn1_write_OctetString(data
, tree
->u
.equality
.value
.data
,
255 tree
->u
.equality
.value
.length
)) return false;
256 if (!asn1_pop_tag(data
)) return false;
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 if (!asn1_push_tag(data
, ASN1_CONTEXT(4))) return false;
270 if (!asn1_write_OctetString(data
, tree
->u
.substring
.attr
, strlen(tree
->u
.substring
.attr
))) return false;
271 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) return false;
273 if (tree
->u
.substring
.chunks
&& tree
->u
.substring
.chunks
[0]) {
275 if (!tree
->u
.substring
.start_with_wildcard
) {
276 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) return false;
277 if (!asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
])) return false;
278 if (!asn1_pop_tag(data
)) return false;
281 while (tree
->u
.substring
.chunks
[i
]) {
284 if (( ! tree
->u
.substring
.chunks
[i
+ 1]) &&
285 (tree
->u
.substring
.end_with_wildcard
== 0)) {
290 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(ctx
))) return false;
291 if (!asn1_write_DATA_BLOB_LDAPString(data
, tree
->u
.substring
.chunks
[i
])) return false;
292 if (!asn1_pop_tag(data
)) return false;
296 if (!asn1_pop_tag(data
)) return false;
297 if (!asn1_pop_tag(data
)) return false;
301 /* greaterOrEqual test */
302 if (!asn1_push_tag(data
, ASN1_CONTEXT(5))) return false;
303 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
304 strlen(tree
->u
.comparison
.attr
))) return false;
305 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
306 tree
->u
.comparison
.value
.length
)) return false;
307 if (!asn1_pop_tag(data
)) return false;
311 /* lessOrEqual test */
312 if (!asn1_push_tag(data
, ASN1_CONTEXT(6))) return false;
313 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
314 strlen(tree
->u
.comparison
.attr
))) return false;
315 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
316 tree
->u
.comparison
.value
.length
)) return false;
317 if (!asn1_pop_tag(data
)) return false;
322 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(7))) return false;
323 if (!asn1_write_LDAPString(data
, tree
->u
.present
.attr
)) return false;
324 if (!asn1_pop_tag(data
)) return false;
325 return !asn1_has_error(data
);
329 if (!asn1_push_tag(data
, ASN1_CONTEXT(8))) return false;
330 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
331 strlen(tree
->u
.comparison
.attr
))) return false;
332 if (!asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
333 tree
->u
.comparison
.value
.length
)) return false;
334 if (!asn1_pop_tag(data
)) return false;
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 if (!asn1_push_tag(data
, ASN1_CONTEXT(9))) return false;
347 if (tree
->u
.extended
.rule_id
) {
348 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1))) return false;
349 if (!asn1_write_LDAPString(data
, tree
->u
.extended
.rule_id
)) return false;
350 if (!asn1_pop_tag(data
)) return false;
352 if (tree
->u
.extended
.attr
) {
353 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2))) return false;
354 if (!asn1_write_LDAPString(data
, tree
->u
.extended
.attr
)) return false;
355 if (!asn1_pop_tag(data
)) return false;
357 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3))) return false;
358 if (!asn1_write_DATA_BLOB_LDAPString(data
, &tree
->u
.extended
.value
)) return false;
359 if (!asn1_pop_tag(data
)) return false;
360 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4))) return false;
361 if (!asn1_write_uint8(data
, tree
->u
.extended
.dnAttributes
)) return false;
362 if (!asn1_pop_tag(data
)) return false;
363 if (!asn1_pop_tag(data
)) return false;
369 return !asn1_has_error(data
);
372 static bool ldap_encode_response(struct asn1_data
*data
, struct ldap_Result
*result
)
374 if (!asn1_write_enumerated(data
, result
->resultcode
)) return false;
375 if (!asn1_write_OctetString(data
, result
->dn
,
376 (result
->dn
) ? strlen(result
->dn
) : 0)) return false;
377 if (!asn1_write_OctetString(data
, result
->errormessage
,
378 (result
->errormessage
) ?
379 strlen(result
->errormessage
) : 0)) return false;
380 if (result
->referral
) {
381 if (!asn1_push_tag(data
, ASN1_CONTEXT(3))) return false;
382 if (!asn1_write_OctetString(data
, result
->referral
,
383 strlen(result
->referral
))) return false;
384 if (!asn1_pop_tag(data
)) return false;
389 _PUBLIC_
bool ldap_encode(struct ldap_message
*msg
,
390 const struct ldap_control_handler
*control_handlers
,
391 DATA_BLOB
*result
, TALLOC_CTX
*mem_ctx
)
393 struct asn1_data
*data
= asn1_init(mem_ctx
, ASN1_MAX_TREE_DEPTH
);
396 if (!data
) return false;
398 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
399 if (!asn1_write_Integer(data
, msg
->messageid
)) goto err
;
402 case LDAP_TAG_BindRequest
: {
403 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
404 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
405 if (!asn1_write_Integer(data
, r
->version
)) goto err
;
406 if (!asn1_write_OctetString(data
, r
->dn
,
407 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0)) goto err
;
409 switch (r
->mechanism
) {
410 case LDAP_AUTH_MECH_SIMPLE
:
411 /* context, primitive */
412 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
413 if (!asn1_write(data
, r
->creds
.password
,
414 strlen(r
->creds
.password
))) goto err
;
415 if (!asn1_pop_tag(data
)) goto err
;
417 case LDAP_AUTH_MECH_SASL
:
418 /* context, constructed */
419 if (!asn1_push_tag(data
, ASN1_CONTEXT(3))) goto err
;
420 if (!asn1_write_OctetString(data
, r
->creds
.SASL
.mechanism
,
421 strlen(r
->creds
.SASL
.mechanism
))) goto err
;
422 if (r
->creds
.SASL
.secblob
) {
423 if (!asn1_write_OctetString(data
, r
->creds
.SASL
.secblob
->data
,
424 r
->creds
.SASL
.secblob
->length
)) goto err
;
426 if (!asn1_pop_tag(data
)) goto err
;
432 if (!asn1_pop_tag(data
)) goto err
;
435 case LDAP_TAG_BindResponse
: {
436 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
437 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
438 if (!ldap_encode_response(data
, &r
->response
)) goto err
;
439 if (r
->SASL
.secblob
) {
440 if (!asn1_write_ContextSimple(data
, 7, r
->SASL
.secblob
)) goto err
;
442 if (!asn1_pop_tag(data
)) goto err
;
445 case LDAP_TAG_UnbindRequest
: {
446 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
447 if (!asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
))) goto err
;
448 if (!asn1_pop_tag(data
)) goto err
;
451 case LDAP_TAG_SearchRequest
: {
452 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
453 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
454 if (!asn1_write_OctetString(data
, r
->basedn
, strlen(r
->basedn
))) goto err
;
455 if (!asn1_write_enumerated(data
, r
->scope
)) goto err
;
456 if (!asn1_write_enumerated(data
, r
->deref
)) goto err
;
457 if (!asn1_write_Integer(data
, r
->sizelimit
)) goto err
;
458 if (!asn1_write_Integer(data
, r
->timelimit
)) goto err
;
459 if (!asn1_write_BOOLEAN(data
, r
->attributesonly
)) goto err
;
461 if (!ldap_push_filter(data
, r
->tree
)) {
465 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
466 for (i
=0; i
<r
->num_attributes
; i
++) {
467 if (!asn1_write_OctetString(data
, r
->attributes
[i
],
468 strlen(r
->attributes
[i
]))) goto err
;
470 if (!asn1_pop_tag(data
)) goto err
;
471 if (!asn1_pop_tag(data
)) goto err
;
474 case LDAP_TAG_SearchResultEntry
: {
475 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
476 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
477 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
478 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
479 for (i
=0; i
<r
->num_attributes
; i
++) {
480 struct ldb_message_element
*attr
= &r
->attributes
[i
];
481 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
482 if (!asn1_write_OctetString(data
, attr
->name
,
483 strlen(attr
->name
))) goto err
;
484 if (!asn1_push_tag(data
, ASN1_SEQUENCE(1))) goto err
;
485 for (j
=0; j
<attr
->num_values
; j
++) {
486 if (!asn1_write_OctetString(data
,
487 attr
->values
[j
].data
,
488 attr
->values
[j
].length
)) goto err
;
490 if (!asn1_pop_tag(data
)) goto err
;
491 if (!asn1_pop_tag(data
)) goto err
;
493 if (!asn1_pop_tag(data
)) goto err
;
494 if (!asn1_pop_tag(data
)) goto err
;
497 case LDAP_TAG_SearchResultDone
: {
498 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
499 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
500 if (!ldap_encode_response(data
, r
)) goto err
;
501 if (!asn1_pop_tag(data
)) goto err
;
504 case LDAP_TAG_ModifyRequest
: {
505 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
506 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
507 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
508 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
510 for (i
=0; i
<r
->num_mods
; i
++) {
511 struct ldb_message_element
*attrib
= &r
->mods
[i
].attrib
;
512 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
513 if (!asn1_write_enumerated(data
, r
->mods
[i
].type
)) goto err
;
514 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
515 if (!asn1_write_OctetString(data
, attrib
->name
,
516 strlen(attrib
->name
))) goto err
;
517 if (!asn1_push_tag(data
, ASN1_SET
)) goto err
;
518 for (j
=0; j
<attrib
->num_values
; j
++) {
519 if (!asn1_write_OctetString(data
,
520 attrib
->values
[j
].data
,
521 attrib
->values
[j
].length
)) goto err
;
524 if (!asn1_pop_tag(data
)) goto err
;
525 if (!asn1_pop_tag(data
)) goto err
;
526 if (!asn1_pop_tag(data
)) goto err
;
529 if (!asn1_pop_tag(data
)) goto err
;
530 if (!asn1_pop_tag(data
)) goto err
;
533 case LDAP_TAG_ModifyResponse
: {
534 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
535 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
536 if (!ldap_encode_response(data
, r
)) goto err
;
537 if (!asn1_pop_tag(data
)) goto err
;
540 case LDAP_TAG_AddRequest
: {
541 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
542 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
543 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
544 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
546 for (i
=0; i
<r
->num_attributes
; i
++) {
547 struct ldb_message_element
*attrib
= &r
->attributes
[i
];
548 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
549 if (attrib
->name
== NULL
) {
552 if (!asn1_write_OctetString(data
, attrib
->name
,
553 strlen(attrib
->name
))) goto err
;
554 if (!asn1_push_tag(data
, ASN1_SET
)) goto err
;
555 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
556 if (!asn1_write_OctetString(data
,
557 attrib
->values
[j
].data
,
558 attrib
->values
[j
].length
)) goto err
;
560 if (!asn1_pop_tag(data
)) goto err
;
561 if (!asn1_pop_tag(data
)) goto err
;
563 if (!asn1_pop_tag(data
)) goto err
;
564 if (!asn1_pop_tag(data
)) goto err
;
567 case LDAP_TAG_AddResponse
: {
568 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
569 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
570 if (!ldap_encode_response(data
, r
)) goto err
;
571 if (!asn1_pop_tag(data
)) goto err
;
574 case LDAP_TAG_DelRequest
: {
575 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
576 if (!asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
))) goto err
;
577 if (!asn1_write(data
, r
->dn
, strlen(r
->dn
))) goto err
;
578 if (!asn1_pop_tag(data
)) goto err
;
581 case LDAP_TAG_DelResponse
: {
582 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
583 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
584 if (!ldap_encode_response(data
, r
)) goto err
;
585 if (!asn1_pop_tag(data
)) goto err
;
588 case LDAP_TAG_ModifyDNRequest
: {
589 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
590 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
591 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
592 if (!asn1_write_OctetString(data
, r
->newrdn
, strlen(r
->newrdn
))) goto err
;
593 if (!asn1_write_BOOLEAN(data
, r
->deleteolddn
)) goto err
;
594 if (r
->newsuperior
) {
595 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
596 if (!asn1_write(data
, r
->newsuperior
,
597 strlen(r
->newsuperior
))) goto err
;
598 if (!asn1_pop_tag(data
)) goto err
;
600 if (!asn1_pop_tag(data
)) goto err
;
603 case LDAP_TAG_ModifyDNResponse
: {
604 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
605 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
606 if (!ldap_encode_response(data
, r
)) goto err
;
607 if (!asn1_pop_tag(data
)) goto err
;
610 case LDAP_TAG_CompareRequest
: {
611 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
612 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
613 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
614 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
615 if (!asn1_write_OctetString(data
, r
->attribute
,
616 strlen(r
->attribute
))) goto err
;
617 if (!asn1_write_OctetString(data
, r
->value
.data
,
618 r
->value
.length
)) goto err
;
619 if (!asn1_pop_tag(data
)) goto err
;
620 if (!asn1_pop_tag(data
)) goto err
;
623 case LDAP_TAG_CompareResponse
: {
624 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
625 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
626 if (!ldap_encode_response(data
, r
)) goto err
;
627 if (!asn1_pop_tag(data
)) goto err
;
630 case LDAP_TAG_AbandonRequest
: {
631 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
632 if (!asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
))) goto err
;
633 if (!asn1_write_implicit_Integer(data
, r
->messageid
)) goto err
;
634 if (!asn1_pop_tag(data
)) goto err
;
637 case LDAP_TAG_SearchResultReference
: {
638 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
639 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
640 if (!asn1_write_OctetString(data
, r
->referral
, strlen(r
->referral
))) goto err
;
641 if (!asn1_pop_tag(data
)) goto err
;
644 case LDAP_TAG_ExtendedRequest
: {
645 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
646 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
647 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
648 if (!asn1_write(data
, r
->oid
, strlen(r
->oid
))) goto err
;
649 if (!asn1_pop_tag(data
)) goto err
;
651 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1))) goto err
;
652 if (!asn1_write(data
, r
->value
->data
, r
->value
->length
)) goto err
;
653 if (!asn1_pop_tag(data
)) goto err
;
655 if (!asn1_pop_tag(data
)) goto err
;
658 case LDAP_TAG_ExtendedResponse
: {
659 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
660 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
661 if (!ldap_encode_response(data
, &r
->response
)) goto err
;
663 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10))) goto err
;
664 if (!asn1_write(data
, r
->oid
, strlen(r
->oid
))) goto err
;
665 if (!asn1_pop_tag(data
)) goto err
;
668 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11))) goto err
;
669 if (!asn1_write(data
, r
->value
->data
, r
->value
->length
)) goto err
;
670 if (!asn1_pop_tag(data
)) goto err
;
672 if (!asn1_pop_tag(data
)) goto err
;
679 if (msg
->controls
!= NULL
) {
680 if (!asn1_push_tag(data
, ASN1_CONTEXT(0))) goto err
;
682 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
683 if (!ldap_encode_control(mem_ctx
, data
,
686 DEBUG(0,("Unable to encode control %s\n",
687 msg
->controls
[i
]->oid
));
692 if (!asn1_pop_tag(data
)) goto err
;
695 if (!asn1_pop_tag(data
)) goto err
;
697 if (!asn1_extract_blob(data
, mem_ctx
, result
)) {
711 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
714 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
715 if (result
== NULL
) {
718 memcpy(result
, blob
.data
, blob
.length
);
719 result
[blob
.length
] = '\0';
723 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
724 struct asn1_data
*data
,
728 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
730 *result
= blob2string_talloc(mem_ctx
, string
);
731 data_blob_free(&string
);
732 return *result
? true : false;
735 static bool ldap_decode_response(TALLOC_CTX
*mem_ctx
,
736 struct asn1_data
*data
,
737 struct ldap_Result
*result
)
739 if (!asn1_read_enumerated(data
, &result
->resultcode
)) return false;
740 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
)) return false;
741 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
)) return false;
742 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
743 if (!asn1_start_tag(data
, ASN1_CONTEXT(3))) return false;
744 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
)) return false;
745 if (!asn1_end_tag(data
)) return false;
747 result
->referral
= NULL
;
752 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
755 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
756 if (chunks
== NULL
) {
760 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
761 if (chunks
[chunk_num
] == NULL
) {
765 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
766 if (chunks
[chunk_num
]->data
== NULL
) {
769 chunks
[chunk_num
]->length
= strlen(value
);
771 chunks
[chunk_num
+ 1] = NULL
;
778 parse the ASN.1 formatted search string into a ldb_parse_tree
780 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
781 struct asn1_data
*data
)
784 struct ldb_parse_tree
*ret
;
786 if (!asn1_peek_uint8(data
, &filter_tag
)) {
790 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
792 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
793 if (ret
== NULL
) return NULL
;
798 /* AND or OR of one or more filters */
799 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
800 ret
->u
.list
.num_elements
= 0;
801 ret
->u
.list
.elements
= NULL
;
803 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
807 while (asn1_tag_remaining(data
) > 0) {
808 struct ldb_parse_tree
*subtree
;
809 subtree
= ldap_decode_filter_tree(ret
, data
);
810 if (subtree
== NULL
) {
813 ret
->u
.list
.elements
=
814 talloc_realloc(ret
, ret
->u
.list
.elements
,
815 struct ldb_parse_tree
*,
816 ret
->u
.list
.num_elements
+1);
817 if (ret
->u
.list
.elements
== NULL
) {
820 talloc_steal(ret
->u
.list
.elements
, subtree
);
821 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
822 ret
->u
.list
.num_elements
++;
824 if (!asn1_end_tag(data
)) {
830 /* 'not' operation */
831 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
835 ret
->operation
= LDB_OP_NOT
;
836 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
837 if (ret
->u
.isnot
.child
== NULL
) {
840 if (!asn1_end_tag(data
)) {
850 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
851 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
852 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
853 if (!asn1_end_tag(data
)) goto failed
;
854 if (asn1_has_error(data
) || (attrib
== NULL
) ||
855 (value
.data
== NULL
)) {
859 ret
->operation
= LDB_OP_EQUALITY
;
860 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
861 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
862 ret
->u
.equality
.value
.length
= value
.length
;
872 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
875 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
879 ret
->operation
= LDB_OP_SUBSTRING
;
880 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
881 if (ret
->u
.substring
.attr
== NULL
) {
884 ret
->u
.substring
.chunks
= NULL
;
885 ret
->u
.substring
.start_with_wildcard
= 1;
886 ret
->u
.substring
.end_with_wildcard
= 1;
888 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
892 while (asn1_tag_remaining(data
) > 0) {
893 if (!asn1_peek_uint8(data
, &subs_tag
)) goto failed
;
894 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
895 if (subs_tag
> 2) goto failed
;
897 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
))) goto failed
;
898 if (!asn1_read_LDAPString(data
, mem_ctx
, &value
)) goto failed
;
899 if (!asn1_end_tag(data
)) goto failed
;
903 if (ret
->u
.substring
.chunks
!= NULL
) {
904 /* initial value found in the middle */
908 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
909 if (ret
->u
.substring
.chunks
== NULL
) {
913 ret
->u
.substring
.start_with_wildcard
= 0;
918 if (ret
->u
.substring
.end_with_wildcard
== 0) {
919 /* "any" value found after a "final" value */
923 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
924 ret
->u
.substring
.chunks
,
927 if (ret
->u
.substring
.chunks
== NULL
) {
935 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
936 ret
->u
.substring
.chunks
,
939 if (ret
->u
.substring
.chunks
== NULL
) {
943 ret
->u
.substring
.end_with_wildcard
= 0;
952 if (!asn1_end_tag(data
)) { /* SEQUENCE */
956 if (!asn1_end_tag(data
)) {
966 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
967 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
968 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
969 if (!asn1_end_tag(data
)) goto failed
;
970 if (asn1_has_error(data
) || (attrib
== NULL
) ||
971 (value
.data
== NULL
)) {
975 ret
->operation
= LDB_OP_GREATER
;
976 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
977 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
978 ret
->u
.comparison
.value
.length
= value
.length
;
986 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
987 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
988 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
989 if (!asn1_end_tag(data
)) goto failed
;
990 if (asn1_has_error(data
) || (attrib
== NULL
) ||
991 (value
.data
== NULL
)) {
995 ret
->operation
= LDB_OP_LESS
;
996 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
997 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
998 ret
->u
.comparison
.value
.length
= value
.length
;
1002 /* Normal presence, "attribute=*" */
1005 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
1008 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
1012 ret
->operation
= LDB_OP_PRESENT
;
1013 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
1015 if (!asn1_end_tag(data
)) {
1025 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
1026 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
1027 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
1028 if (!asn1_end_tag(data
)) goto failed
;
1029 if (asn1_has_error(data
) || (attrib
== NULL
) ||
1030 (value
.data
== NULL
)) {
1034 ret
->operation
= LDB_OP_APPROX
;
1035 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
1036 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
1037 ret
->u
.comparison
.value
.length
= value
.length
;
1041 char *oid
= NULL
, *attr
= NULL
, *value
;
1042 uint8_t dnAttributes
;
1043 /* an extended search */
1044 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
1048 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1049 we need to check we properly implement --SSS */
1050 /* either oid or type must be defined */
1051 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1052 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1))) goto failed
;
1053 if (!asn1_read_LDAPString(data
, ret
, &oid
)) goto failed
;
1054 if (!asn1_end_tag(data
)) goto failed
;
1056 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1057 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2))) goto failed
;
1058 if (!asn1_read_LDAPString(data
, ret
, &attr
)) goto failed
;
1059 if (!asn1_end_tag(data
)) goto failed
;
1061 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3))) goto failed
;
1062 if (!asn1_read_LDAPString(data
, ret
, &value
)) goto failed
;
1063 if (!asn1_end_tag(data
)) goto failed
;
1064 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1065 it is not marked as OPTIONAL but openldap tools
1066 do not set this unless it is to be set as TRUE
1067 NOTE: openldap tools do not work with AD as it
1068 seems that AD always requires the dnAttributes
1069 boolean value to be set */
1070 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
1071 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4))) goto failed
;
1072 if (!asn1_read_uint8(data
, &dnAttributes
)) goto failed
;
1073 if (!asn1_end_tag(data
)) goto failed
;
1077 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
1082 ret
->operation
= LDB_OP_EXTENDED
;
1084 /* From the RFC2251: If the type field is
1085 absent and matchingRule is present, the matchValue is compared
1086 against all attributes in an entry which support that matchingRule
1089 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
1091 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
1092 if (ret
->u
.extended
.attr
== NULL
) {
1096 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
1097 ret
->u
.extended
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1098 ret
->u
.extended
.value
.length
= strlen(value
);
1099 ret
->u
.extended
.dnAttributes
= dnAttributes
;
1101 ret
->operation
= LDB_OP_EQUALITY
;
1102 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
1103 ret
->u
.equality
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1104 ret
->u
.equality
.value
.length
= strlen(value
);
1106 if (!asn1_end_tag(data
)) {
1123 /* Decode a single LDAP attribute, possibly containing multiple values */
1124 static bool ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1125 struct ldb_message_element
*attrib
)
1127 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) return false;
1128 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
)) return false;
1129 if (!asn1_start_tag(data
, ASN1_SET
)) return false;
1130 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
1132 if (!asn1_read_OctetString(data
, mem_ctx
, &blob
)) return false;
1133 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
1135 if (!asn1_end_tag(data
)) return false;
1136 return asn1_end_tag(data
);
1139 /* Decode a set of LDAP attributes, as found in the dereference control */
1140 bool ldap_decode_attribs_bare(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1141 struct ldb_message_element
**attributes
,
1142 int *num_attributes
)
1144 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1145 struct ldb_message_element attrib
;
1146 ZERO_STRUCT(attrib
);
1147 if (!ldap_decode_attrib(mem_ctx
, data
, &attrib
)) return false;
1148 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
1149 attributes
, num_attributes
);
1154 /* Decode a set of LDAP attributes, as found in a search entry */
1155 static bool ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1156 struct ldb_message_element
**attributes
,
1157 int *num_attributes
)
1159 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) return false;
1160 if (!ldap_decode_attribs_bare(mem_ctx
, data
,
1161 attributes
, num_attributes
)) return false;
1162 return asn1_end_tag(data
);
1165 /* This routine returns LDAP status codes */
1167 _PUBLIC_ NTSTATUS
ldap_decode(struct asn1_data
*data
,
1168 const struct ldap_request_limits
*limits
,
1169 const struct ldap_control_handler
*control_handlers
,
1170 struct ldap_message
*msg
)
1174 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1175 if (!asn1_read_Integer(data
, &msg
->messageid
)) goto prot_err
;
1177 if (!asn1_peek_uint8(data
, &tag
)) goto prot_err
;
1181 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
1182 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
1183 msg
->type
= LDAP_TAG_BindRequest
;
1184 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1185 if (!asn1_read_Integer(data
, &r
->version
)) goto prot_err
;
1186 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1187 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
1189 r
->creds
.password
= "";
1190 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
1191 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto prot_err
;
1192 pwlen
= asn1_tag_remaining(data
);
1197 char *pw
= talloc_array(msg
, char, pwlen
+1);
1199 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1201 if (!asn1_read(data
, pw
, pwlen
)) goto prot_err
;
1203 r
->creds
.password
= pw
;
1205 if (!asn1_end_tag(data
)) goto prot_err
;
1206 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
1207 if (!asn1_start_tag(data
, ASN1_CONTEXT(3))) goto prot_err
;
1208 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
1209 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
)) goto prot_err
;
1210 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
1211 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1212 if (!asn1_read_OctetString(data
, msg
, &tmp_blob
)) goto prot_err
;
1213 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1214 if (!r
->creds
.SASL
.secblob
) {
1215 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1217 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
1218 tmp_blob
.data
, tmp_blob
.length
);
1219 data_blob_free(&tmp_blob
);
1221 r
->creds
.SASL
.secblob
= NULL
;
1223 if (!asn1_end_tag(data
)) goto prot_err
;
1225 /* Neither Simple nor SASL bind */
1228 if (!asn1_end_tag(data
)) goto prot_err
;
1232 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
1233 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
1234 msg
->type
= LDAP_TAG_BindResponse
;
1235 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1236 if (!ldap_decode_response(msg
, data
, &r
->response
)) goto prot_err
;
1237 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
1238 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1239 if (!asn1_read_ContextSimple(data
, msg
, 7, &tmp_blob
)) goto prot_err
;
1240 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1241 if (!r
->SASL
.secblob
) {
1242 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1244 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1245 tmp_blob
.data
, tmp_blob
.length
);
1246 data_blob_free(&tmp_blob
);
1248 r
->SASL
.secblob
= NULL
;
1250 if (!asn1_end_tag(data
)) goto prot_err
;
1254 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1255 msg
->type
= LDAP_TAG_UnbindRequest
;
1256 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1257 if (!asn1_end_tag(data
)) goto prot_err
;
1261 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1262 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1263 int sizelimit
, timelimit
;
1264 const char **attrs
= NULL
;
1265 size_t request_size
= asn1_get_length(data
);
1266 msg
->type
= LDAP_TAG_SearchRequest
;
1267 if (request_size
> limits
->max_search_size
) {
1270 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1271 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
)) goto prot_err
;
1272 if (!asn1_read_enumerated(data
, (int *)(void *)&(r
->scope
))) goto prot_err
;
1273 if (!asn1_read_enumerated(data
, (int *)(void *)&(r
->deref
))) goto prot_err
;
1274 if (!asn1_read_Integer(data
, &sizelimit
)) goto prot_err
;
1275 r
->sizelimit
= sizelimit
;
1276 if (!asn1_read_Integer(data
, &timelimit
)) goto prot_err
;
1277 r
->timelimit
= timelimit
;
1278 if (!asn1_read_BOOLEAN(data
, &r
->attributesonly
)) goto prot_err
;
1280 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1281 if (r
->tree
== NULL
) {
1285 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1287 r
->num_attributes
= 0;
1288 r
->attributes
= NULL
;
1290 while (asn1_tag_remaining(data
) > 0) {
1293 if (!asn1_read_OctetString_talloc(msg
, data
,
1296 if (!add_string_to_array(msg
, attr
,
1298 &r
->num_attributes
))
1301 r
->attributes
= attrs
;
1303 if (!asn1_end_tag(data
)) goto prot_err
;
1304 if (!asn1_end_tag(data
)) goto prot_err
;
1308 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1309 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1310 msg
->type
= LDAP_TAG_SearchResultEntry
;
1311 r
->attributes
= NULL
;
1312 r
->num_attributes
= 0;
1313 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1314 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1315 if (!ldap_decode_attribs(msg
, data
, &r
->attributes
,
1316 &r
->num_attributes
)) goto prot_err
;
1317 if (!asn1_end_tag(data
)) goto prot_err
;
1321 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1322 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1323 msg
->type
= LDAP_TAG_SearchResultDone
;
1324 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1325 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1326 if (!asn1_end_tag(data
)) goto prot_err
;
1330 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1331 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1332 msg
->type
= LDAP_TAG_SearchResultReference
;
1333 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1334 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->referral
)) goto prot_err
;
1335 if (!asn1_end_tag(data
)) goto prot_err
;
1339 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1340 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1341 msg
->type
= LDAP_TAG_ModifyRequest
;
1342 if (!asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
))) goto prot_err
;
1343 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1344 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1349 while (asn1_tag_remaining(data
) > 0) {
1350 struct ldap_mod mod
;
1353 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1354 if (!asn1_read_enumerated(data
, &v
)) goto prot_err
;
1356 if (!ldap_decode_attrib(msg
, data
, &mod
.attrib
)) goto prot_err
;
1357 if (!asn1_end_tag(data
)) goto prot_err
;
1358 if (!add_mod_to_array_talloc(msg
, &mod
,
1359 &r
->mods
, &r
->num_mods
)) {
1360 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1364 if (!asn1_end_tag(data
)) goto prot_err
;
1365 if (!asn1_end_tag(data
)) goto prot_err
;
1369 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1370 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1371 msg
->type
= LDAP_TAG_ModifyResponse
;
1372 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1373 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1374 if (!asn1_end_tag(data
)) goto prot_err
;
1378 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1379 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1380 msg
->type
= LDAP_TAG_AddRequest
;
1381 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1382 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1384 r
->attributes
= NULL
;
1385 r
->num_attributes
= 0;
1386 if (!ldap_decode_attribs(msg
, data
, &r
->attributes
,
1387 &r
->num_attributes
)) goto prot_err
;
1389 if (!asn1_end_tag(data
)) goto prot_err
;
1393 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1394 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1395 msg
->type
= LDAP_TAG_AddResponse
;
1396 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1397 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1398 if (!asn1_end_tag(data
)) goto prot_err
;
1402 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1403 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1406 msg
->type
= LDAP_TAG_DelRequest
;
1407 if (!asn1_start_tag(data
,
1408 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
))) goto prot_err
;
1409 len
= asn1_tag_remaining(data
);
1413 dn
= talloc_array(msg
, char, len
+1);
1416 if (!asn1_read(data
, dn
, len
)) goto prot_err
;
1419 if (!asn1_end_tag(data
)) goto prot_err
;
1423 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1424 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1425 msg
->type
= LDAP_TAG_DelResponse
;
1426 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1427 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1428 if (!asn1_end_tag(data
)) goto prot_err
;
1432 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1433 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1434 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1435 if (!asn1_start_tag(data
,
1436 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
))) goto prot_err
;
1437 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1438 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
)) goto prot_err
;
1439 if (!asn1_read_BOOLEAN(data
, &r
->deleteolddn
)) goto prot_err
;
1440 r
->newsuperior
= NULL
;
1441 if (asn1_tag_remaining(data
) > 0) {
1444 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto prot_err
;
1445 len
= asn1_tag_remaining(data
);
1449 newsup
= talloc_array(msg
, char, len
+1);
1450 if (newsup
== NULL
) {
1451 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1453 if (!asn1_read(data
, newsup
, len
)) goto prot_err
;
1455 r
->newsuperior
= newsup
;
1456 if (!asn1_end_tag(data
)) goto prot_err
;
1458 if (!asn1_end_tag(data
)) goto prot_err
;
1462 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1463 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1464 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1465 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1466 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1467 if (!asn1_end_tag(data
)) goto prot_err
;
1471 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1472 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1473 msg
->type
= LDAP_TAG_CompareRequest
;
1474 if (!asn1_start_tag(data
,
1475 ASN1_APPLICATION(LDAP_TAG_CompareRequest
))) goto prot_err
;
1476 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1477 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1478 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
)) goto prot_err
;
1479 if (!asn1_read_OctetString(data
, msg
, &r
->value
)) goto prot_err
;
1480 if (r
->value
.data
) {
1481 talloc_steal(msg
, r
->value
.data
);
1483 if (!asn1_end_tag(data
)) goto prot_err
;
1484 if (!asn1_end_tag(data
)) goto prot_err
;
1488 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1489 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1490 msg
->type
= LDAP_TAG_CompareResponse
;
1491 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1492 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1493 if (!asn1_end_tag(data
)) goto prot_err
;
1497 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1498 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1499 msg
->type
= LDAP_TAG_AbandonRequest
;
1500 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1501 if (!asn1_read_implicit_Integer(data
, &r
->messageid
)) goto prot_err
;
1502 if (!asn1_end_tag(data
)) goto prot_err
;
1506 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1507 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1508 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1510 msg
->type
= LDAP_TAG_ExtendedRequest
;
1511 if (!asn1_start_tag(data
,tag
)) goto prot_err
;
1512 if (!asn1_read_ContextSimple(data
, msg
, 0, &tmp_blob
)) {
1515 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1516 data_blob_free(&tmp_blob
);
1518 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1521 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1522 if (!asn1_read_ContextSimple(data
, msg
, 1, &tmp_blob
)) goto prot_err
;
1523 r
->value
= talloc(msg
, DATA_BLOB
);
1525 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1527 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1528 data_blob_free(&tmp_blob
);
1533 if (!asn1_end_tag(data
)) goto prot_err
;
1537 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1538 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1539 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1541 msg
->type
= LDAP_TAG_ExtendedResponse
;
1542 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1543 if (!ldap_decode_response(msg
, data
, &r
->response
)) goto prot_err
;
1545 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1546 if (!asn1_read_ContextSimple(data
, msg
, 10, &tmp_blob
))
1548 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1549 data_blob_free(&tmp_blob
);
1551 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1557 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1558 if (!asn1_read_ContextSimple(data
, msg
, 11, &tmp_blob
))
1560 r
->value
= talloc(msg
, DATA_BLOB
);
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1564 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1565 data_blob_free(&tmp_blob
);
1570 if (!asn1_end_tag(data
)) goto prot_err
;
1577 msg
->controls
= NULL
;
1578 msg
->controls_decoded
= NULL
;
1580 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1582 struct ldb_control
**ctrl
= NULL
;
1583 bool *decoded
= NULL
;
1585 if (!asn1_start_tag(data
, ASN1_CONTEXT(0))) goto prot_err
;
1587 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1589 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1591 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1593 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1596 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1598 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1601 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1603 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1606 if (!ldap_decode_control_wrapper(ctrl
[i
], data
, ctrl
[i
], &value
)) {
1610 if (!ldap_decode_control_value(ctrl
[i
], value
,
1613 if (ctrl
[i
]->critical
) {
1614 ctrl
[i
]->data
= NULL
;
1618 talloc_free(ctrl
[i
]);
1631 msg
->controls
= ctrl
;
1632 msg
->controls_decoded
= decoded
;
1634 if (!asn1_end_tag(data
)) goto prot_err
;
1637 if (!asn1_end_tag(data
)) goto prot_err
;
1638 if (asn1_has_error(data
) || asn1_has_nesting(data
)) {
1639 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1641 return NT_STATUS_OK
;
1645 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1650 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1651 ldap packet. Set packet_size if true.
1653 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1657 if (blob
.length
< 6) {
1659 * We need at least 6 bytes to workout the length
1662 return STATUS_MORE_ENTRIES
;
1665 ret
= asn1_peek_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);
1667 return map_nt_error_from_unix_common(ret
);
1669 return NT_STATUS_OK
;