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 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 !data
->has_error
;
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 !data
->has_error
;
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
);
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 (!asn1_write_OctetString(data
, attrib
->name
,
550 strlen(attrib
->name
))) goto err
;
551 if (!asn1_push_tag(data
, ASN1_SET
)) goto err
;
552 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
553 if (!asn1_write_OctetString(data
,
554 attrib
->values
[j
].data
,
555 attrib
->values
[j
].length
)) goto err
;
557 if (!asn1_pop_tag(data
)) goto err
;
558 if (!asn1_pop_tag(data
)) goto err
;
560 if (!asn1_pop_tag(data
)) goto err
;
561 if (!asn1_pop_tag(data
)) goto err
;
564 case LDAP_TAG_AddResponse
: {
565 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
566 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
567 if (!ldap_encode_response(data
, r
)) goto err
;
568 if (!asn1_pop_tag(data
)) goto err
;
571 case LDAP_TAG_DelRequest
: {
572 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
573 if (!asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
))) goto err
;
574 if (!asn1_write(data
, r
->dn
, strlen(r
->dn
))) goto err
;
575 if (!asn1_pop_tag(data
)) goto err
;
578 case LDAP_TAG_DelResponse
: {
579 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
580 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
581 if (!ldap_encode_response(data
, r
)) goto err
;
582 if (!asn1_pop_tag(data
)) goto err
;
585 case LDAP_TAG_ModifyDNRequest
: {
586 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
587 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
588 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
589 if (!asn1_write_OctetString(data
, r
->newrdn
, strlen(r
->newrdn
))) goto err
;
590 if (!asn1_write_BOOLEAN(data
, r
->deleteolddn
)) goto err
;
591 if (r
->newsuperior
) {
592 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
593 if (!asn1_write(data
, r
->newsuperior
,
594 strlen(r
->newsuperior
))) goto err
;
595 if (!asn1_pop_tag(data
)) goto err
;
597 if (!asn1_pop_tag(data
)) goto err
;
600 case LDAP_TAG_ModifyDNResponse
: {
601 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
602 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
603 if (!ldap_encode_response(data
, r
)) goto err
;
604 if (!asn1_pop_tag(data
)) goto err
;
607 case LDAP_TAG_CompareRequest
: {
608 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
609 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
610 if (!asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
))) goto err
;
611 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) goto err
;
612 if (!asn1_write_OctetString(data
, r
->attribute
,
613 strlen(r
->attribute
))) goto err
;
614 if (!asn1_write_OctetString(data
, r
->value
.data
,
615 r
->value
.length
)) goto err
;
616 if (!asn1_pop_tag(data
)) goto err
;
617 if (!asn1_pop_tag(data
)) goto err
;
620 case LDAP_TAG_CompareResponse
: {
621 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
622 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
623 if (!ldap_encode_response(data
, r
)) goto err
;
624 if (!asn1_pop_tag(data
)) goto err
;
627 case LDAP_TAG_AbandonRequest
: {
628 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
629 if (!asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
))) goto err
;
630 if (!asn1_write_implicit_Integer(data
, r
->messageid
)) goto err
;
631 if (!asn1_pop_tag(data
)) goto err
;
634 case LDAP_TAG_SearchResultReference
: {
635 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
636 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
637 if (!asn1_write_OctetString(data
, r
->referral
, strlen(r
->referral
))) goto err
;
638 if (!asn1_pop_tag(data
)) goto err
;
641 case LDAP_TAG_ExtendedRequest
: {
642 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
643 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
644 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
645 if (!asn1_write(data
, r
->oid
, strlen(r
->oid
))) goto err
;
646 if (!asn1_pop_tag(data
)) goto err
;
648 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1))) goto err
;
649 if (!asn1_write(data
, r
->value
->data
, r
->value
->length
)) goto err
;
650 if (!asn1_pop_tag(data
)) goto err
;
652 if (!asn1_pop_tag(data
)) goto err
;
655 case LDAP_TAG_ExtendedResponse
: {
656 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
657 if (!asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
))) goto err
;
658 if (!ldap_encode_response(data
, &r
->response
)) goto err
;
660 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10))) goto err
;
661 if (!asn1_write(data
, r
->oid
, strlen(r
->oid
))) goto err
;
662 if (!asn1_pop_tag(data
)) goto err
;
665 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11))) goto err
;
666 if (!asn1_write(data
, r
->value
->data
, r
->value
->length
)) goto err
;
667 if (!asn1_pop_tag(data
)) goto err
;
669 if (!asn1_pop_tag(data
)) goto err
;
676 if (msg
->controls
!= NULL
) {
677 if (!asn1_push_tag(data
, ASN1_CONTEXT(0))) goto err
;
679 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
680 if (!ldap_encode_control(mem_ctx
, data
,
683 DEBUG(0,("Unable to encode control %s\n",
684 msg
->controls
[i
]->oid
));
689 if (!asn1_pop_tag(data
)) goto err
;
692 if (!asn1_pop_tag(data
)) goto err
;
694 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
705 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
708 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
709 if (result
== NULL
) {
712 memcpy(result
, blob
.data
, blob
.length
);
713 result
[blob
.length
] = '\0';
717 bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
718 struct asn1_data
*data
,
722 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
724 *result
= blob2string_talloc(mem_ctx
, string
);
725 data_blob_free(&string
);
726 return *result
? true : false;
729 static bool ldap_decode_response(TALLOC_CTX
*mem_ctx
,
730 struct asn1_data
*data
,
731 struct ldap_Result
*result
)
733 if (!asn1_read_enumerated(data
, &result
->resultcode
)) return false;
734 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
)) return false;
735 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
)) return false;
736 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
737 if (!asn1_start_tag(data
, ASN1_CONTEXT(3))) return false;
738 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
)) return false;
739 if (!asn1_end_tag(data
)) return false;
741 result
->referral
= NULL
;
746 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
749 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
750 if (chunks
== NULL
) {
754 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
755 if (chunks
[chunk_num
] == NULL
) {
759 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
760 if (chunks
[chunk_num
]->data
== NULL
) {
763 chunks
[chunk_num
]->length
= strlen(value
);
765 chunks
[chunk_num
+ 1] = '\0';
772 parse the ASN.1 formatted search string into a ldb_parse_tree
774 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
775 struct asn1_data
*data
)
778 struct ldb_parse_tree
*ret
;
780 if (!asn1_peek_uint8(data
, &filter_tag
)) {
784 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
786 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
787 if (ret
== NULL
) return NULL
;
792 /* AND or OR of one or more filters */
793 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
794 ret
->u
.list
.num_elements
= 0;
795 ret
->u
.list
.elements
= NULL
;
797 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
801 while (asn1_tag_remaining(data
) > 0) {
802 struct ldb_parse_tree
*subtree
;
803 subtree
= ldap_decode_filter_tree(ret
, data
);
804 if (subtree
== NULL
) {
807 ret
->u
.list
.elements
=
808 talloc_realloc(ret
, ret
->u
.list
.elements
,
809 struct ldb_parse_tree
*,
810 ret
->u
.list
.num_elements
+1);
811 if (ret
->u
.list
.elements
== NULL
) {
814 talloc_steal(ret
->u
.list
.elements
, subtree
);
815 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
816 ret
->u
.list
.num_elements
++;
818 if (!asn1_end_tag(data
)) {
824 /* 'not' operation */
825 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
829 ret
->operation
= LDB_OP_NOT
;
830 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
831 if (ret
->u
.isnot
.child
== NULL
) {
834 if (!asn1_end_tag(data
)) {
844 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
845 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
846 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
847 if (!asn1_end_tag(data
)) goto failed
;
848 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
852 ret
->operation
= LDB_OP_EQUALITY
;
853 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
854 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
855 ret
->u
.equality
.value
.length
= value
.length
;
865 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
868 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
872 ret
->operation
= LDB_OP_SUBSTRING
;
873 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
874 if (ret
->u
.substring
.attr
== NULL
) {
877 ret
->u
.substring
.chunks
= NULL
;
878 ret
->u
.substring
.start_with_wildcard
= 1;
879 ret
->u
.substring
.end_with_wildcard
= 1;
881 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
885 while (asn1_tag_remaining(data
)) {
886 if (!asn1_peek_uint8(data
, &subs_tag
)) goto failed
;
887 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
888 if (subs_tag
> 2) goto failed
;
890 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
))) goto failed
;
891 if (!asn1_read_LDAPString(data
, mem_ctx
, &value
)) goto failed
;
892 if (!asn1_end_tag(data
)) goto failed
;
896 if (ret
->u
.substring
.chunks
!= NULL
) {
897 /* initial value found in the middle */
901 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
902 if (ret
->u
.substring
.chunks
== NULL
) {
906 ret
->u
.substring
.start_with_wildcard
= 0;
911 if (ret
->u
.substring
.end_with_wildcard
== 0) {
912 /* "any" value found after a "final" value */
916 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
917 ret
->u
.substring
.chunks
,
920 if (ret
->u
.substring
.chunks
== NULL
) {
928 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
929 ret
->u
.substring
.chunks
,
932 if (ret
->u
.substring
.chunks
== NULL
) {
936 ret
->u
.substring
.end_with_wildcard
= 0;
945 if (!asn1_end_tag(data
)) { /* SEQUENCE */
949 if (!asn1_end_tag(data
)) {
959 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
960 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
961 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
962 if (!asn1_end_tag(data
)) goto failed
;
963 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
967 ret
->operation
= LDB_OP_GREATER
;
968 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
969 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
970 ret
->u
.comparison
.value
.length
= value
.length
;
978 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
979 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
980 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
981 if (!asn1_end_tag(data
)) goto failed
;
982 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
986 ret
->operation
= LDB_OP_LESS
;
987 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
988 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
989 ret
->u
.comparison
.value
.length
= value
.length
;
993 /* Normal presence, "attribute=*" */
996 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
999 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
1003 ret
->operation
= LDB_OP_PRESENT
;
1004 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
1006 if (!asn1_end_tag(data
)) {
1016 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) goto failed
;
1017 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
)) goto failed
;
1018 if (!asn1_read_OctetString(data
, mem_ctx
, &value
)) goto failed
;
1019 if (!asn1_end_tag(data
)) goto failed
;
1020 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
1024 ret
->operation
= LDB_OP_APPROX
;
1025 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
1026 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
1027 ret
->u
.comparison
.value
.length
= value
.length
;
1031 char *oid
= NULL
, *attr
= NULL
, *value
;
1032 uint8_t dnAttributes
;
1033 /* an extended search */
1034 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
1038 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1039 we need to check we properly implement --SSS */
1040 /* either oid or type must be defined */
1041 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1042 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1))) goto failed
;
1043 if (!asn1_read_LDAPString(data
, ret
, &oid
)) goto failed
;
1044 if (!asn1_end_tag(data
)) goto failed
;
1046 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1047 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2))) goto failed
;
1048 if (!asn1_read_LDAPString(data
, ret
, &attr
)) goto failed
;
1049 if (!asn1_end_tag(data
)) goto failed
;
1051 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3))) goto failed
;
1052 if (!asn1_read_LDAPString(data
, ret
, &value
)) goto failed
;
1053 if (!asn1_end_tag(data
)) goto failed
;
1054 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1055 it is not marked as OPTIONAL but openldap tools
1056 do not set this unless it is to be set as TRUE
1057 NOTE: openldap tools do not work with AD as it
1058 seems that AD always requires the dnAttributes
1059 boolean value to be set */
1060 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
1061 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4))) goto failed
;
1062 if (!asn1_read_uint8(data
, &dnAttributes
)) goto failed
;
1063 if (!asn1_end_tag(data
)) goto failed
;
1067 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
1072 ret
->operation
= LDB_OP_EXTENDED
;
1074 /* From the RFC2251: If the type field is
1075 absent and matchingRule is present, the matchValue is compared
1076 against all attributes in an entry which support that matchingRule
1079 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
1081 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
1082 if (ret
->u
.extended
.attr
== NULL
) {
1086 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
1087 ret
->u
.extended
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1088 ret
->u
.extended
.value
.length
= strlen(value
);
1089 ret
->u
.extended
.dnAttributes
= dnAttributes
;
1091 ret
->operation
= LDB_OP_EQUALITY
;
1092 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
1093 ret
->u
.equality
.value
.data
= (uint8_t *)talloc_steal(ret
, value
);
1094 ret
->u
.equality
.value
.length
= strlen(value
);
1096 if (!asn1_end_tag(data
)) {
1113 /* Decode a single LDAP attribute, possibly containing multiple values */
1114 static bool ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1115 struct ldb_message_element
*attrib
)
1117 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) return false;
1118 if (!asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
)) return false;
1119 if (!asn1_start_tag(data
, ASN1_SET
)) return false;
1120 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
1122 if (!asn1_read_OctetString(data
, mem_ctx
, &blob
)) return false;
1123 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
1125 if (!asn1_end_tag(data
)) return false;
1126 return asn1_end_tag(data
);
1129 /* Decode a set of LDAP attributes, as found in the dereference control */
1130 bool ldap_decode_attribs_bare(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1131 struct ldb_message_element
**attributes
,
1132 int *num_attributes
)
1134 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1135 struct ldb_message_element attrib
;
1136 ZERO_STRUCT(attrib
);
1137 if (!ldap_decode_attrib(mem_ctx
, data
, &attrib
)) return false;
1138 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
1139 attributes
, num_attributes
);
1144 /* Decode a set of LDAP attributes, as found in a search entry */
1145 static bool ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
1146 struct ldb_message_element
**attributes
,
1147 int *num_attributes
)
1149 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) return false;
1150 if (!ldap_decode_attribs_bare(mem_ctx
, data
,
1151 attributes
, num_attributes
)) return false;
1152 return asn1_end_tag(data
);
1155 /* This routine returns LDAP status codes */
1157 _PUBLIC_ NTSTATUS
ldap_decode(struct asn1_data
*data
,
1158 const struct ldap_control_handler
*control_handlers
,
1159 struct ldap_message
*msg
)
1163 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1164 if (!asn1_read_Integer(data
, &msg
->messageid
)) goto prot_err
;
1166 if (!asn1_peek_uint8(data
, &tag
)) goto prot_err
;
1170 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
1171 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
1172 msg
->type
= LDAP_TAG_BindRequest
;
1173 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1174 if (!asn1_read_Integer(data
, &r
->version
)) goto prot_err
;
1175 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1176 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
1178 r
->creds
.password
= "";
1179 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
1180 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto prot_err
;
1181 pwlen
= asn1_tag_remaining(data
);
1186 char *pw
= talloc_array(msg
, char, pwlen
+1);
1188 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1190 if (!asn1_read(data
, pw
, pwlen
)) goto prot_err
;
1192 r
->creds
.password
= pw
;
1194 if (!asn1_end_tag(data
)) goto prot_err
;
1195 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
1196 if (!asn1_start_tag(data
, ASN1_CONTEXT(3))) goto prot_err
;
1197 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
1198 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
)) goto prot_err
;
1199 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
1200 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1201 if (!asn1_read_OctetString(data
, msg
, &tmp_blob
)) goto prot_err
;
1202 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1203 if (!r
->creds
.SASL
.secblob
) {
1204 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1206 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
1207 tmp_blob
.data
, tmp_blob
.length
);
1208 data_blob_free(&tmp_blob
);
1210 r
->creds
.SASL
.secblob
= NULL
;
1212 if (!asn1_end_tag(data
)) goto prot_err
;
1214 /* Neither Simple nor SASL bind */
1217 if (!asn1_end_tag(data
)) goto prot_err
;
1221 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
1222 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
1223 msg
->type
= LDAP_TAG_BindResponse
;
1224 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1225 if (!ldap_decode_response(msg
, data
, &r
->response
)) goto prot_err
;
1226 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
1227 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1228 if (!asn1_read_ContextSimple(data
, 7, &tmp_blob
)) goto prot_err
;
1229 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1230 if (!r
->SASL
.secblob
) {
1231 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1233 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1234 tmp_blob
.data
, tmp_blob
.length
);
1235 data_blob_free(&tmp_blob
);
1237 r
->SASL
.secblob
= NULL
;
1239 if (!asn1_end_tag(data
)) goto prot_err
;
1243 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1244 msg
->type
= LDAP_TAG_UnbindRequest
;
1245 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1246 if (!asn1_end_tag(data
)) goto prot_err
;
1250 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1251 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1252 int sizelimit
, timelimit
;
1253 const char **attrs
= NULL
;
1254 msg
->type
= LDAP_TAG_SearchRequest
;
1255 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1256 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
)) goto prot_err
;
1257 if (!asn1_read_enumerated(data
, (int *)(void *)&(r
->scope
))) goto prot_err
;
1258 if (!asn1_read_enumerated(data
, (int *)(void *)&(r
->deref
))) goto prot_err
;
1259 if (!asn1_read_Integer(data
, &sizelimit
)) goto prot_err
;
1260 r
->sizelimit
= sizelimit
;
1261 if (!asn1_read_Integer(data
, &timelimit
)) goto prot_err
;
1262 r
->timelimit
= timelimit
;
1263 if (!asn1_read_BOOLEAN(data
, &r
->attributesonly
)) goto prot_err
;
1265 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1266 if (r
->tree
== NULL
) {
1270 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1272 r
->num_attributes
= 0;
1273 r
->attributes
= NULL
;
1275 while (asn1_tag_remaining(data
) > 0) {
1278 if (!asn1_read_OctetString_talloc(msg
, data
,
1281 if (!add_string_to_array(msg
, attr
,
1283 &r
->num_attributes
))
1286 r
->attributes
= attrs
;
1288 if (!asn1_end_tag(data
)) goto prot_err
;
1289 if (!asn1_end_tag(data
)) goto prot_err
;
1293 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1294 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1295 msg
->type
= LDAP_TAG_SearchResultEntry
;
1296 r
->attributes
= NULL
;
1297 r
->num_attributes
= 0;
1298 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1299 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1300 if (!ldap_decode_attribs(msg
, data
, &r
->attributes
,
1301 &r
->num_attributes
)) goto prot_err
;
1302 if (!asn1_end_tag(data
)) goto prot_err
;
1306 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1307 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1308 msg
->type
= LDAP_TAG_SearchResultDone
;
1309 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1310 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1311 if (!asn1_end_tag(data
)) goto prot_err
;
1315 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1316 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1317 msg
->type
= LDAP_TAG_SearchResultReference
;
1318 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1319 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->referral
)) goto prot_err
;
1320 if (!asn1_end_tag(data
)) goto prot_err
;
1324 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1325 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1326 msg
->type
= LDAP_TAG_ModifyRequest
;
1327 if (!asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
))) goto prot_err
;
1328 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1329 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1334 while (asn1_tag_remaining(data
) > 0) {
1335 struct ldap_mod mod
;
1338 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1339 if (!asn1_read_enumerated(data
, &v
)) goto prot_err
;
1341 if (!ldap_decode_attrib(msg
, data
, &mod
.attrib
)) goto prot_err
;
1342 if (!asn1_end_tag(data
)) goto prot_err
;
1343 if (!add_mod_to_array_talloc(msg
, &mod
,
1344 &r
->mods
, &r
->num_mods
)) {
1345 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1349 if (!asn1_end_tag(data
)) goto prot_err
;
1350 if (!asn1_end_tag(data
)) goto prot_err
;
1354 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1355 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1356 msg
->type
= LDAP_TAG_ModifyResponse
;
1357 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1358 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1359 if (!asn1_end_tag(data
)) goto prot_err
;
1363 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1364 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1365 msg
->type
= LDAP_TAG_AddRequest
;
1366 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1367 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1369 r
->attributes
= NULL
;
1370 r
->num_attributes
= 0;
1371 if (!ldap_decode_attribs(msg
, data
, &r
->attributes
,
1372 &r
->num_attributes
)) goto prot_err
;
1374 if (!asn1_end_tag(data
)) goto prot_err
;
1378 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1379 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1380 msg
->type
= LDAP_TAG_AddResponse
;
1381 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1382 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1383 if (!asn1_end_tag(data
)) goto prot_err
;
1387 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1388 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1391 msg
->type
= LDAP_TAG_DelRequest
;
1392 if (!asn1_start_tag(data
,
1393 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
))) goto prot_err
;
1394 len
= asn1_tag_remaining(data
);
1398 dn
= talloc_array(msg
, char, len
+1);
1401 if (!asn1_read(data
, dn
, len
)) goto prot_err
;
1404 if (!asn1_end_tag(data
)) goto prot_err
;
1408 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1409 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1410 msg
->type
= LDAP_TAG_DelResponse
;
1411 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1412 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1413 if (!asn1_end_tag(data
)) goto prot_err
;
1417 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1418 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1419 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1420 if (!asn1_start_tag(data
,
1421 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
))) goto prot_err
;
1422 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1423 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
)) goto prot_err
;
1424 if (!asn1_read_BOOLEAN(data
, &r
->deleteolddn
)) goto prot_err
;
1425 r
->newsuperior
= NULL
;
1426 if (asn1_tag_remaining(data
) > 0) {
1429 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0))) goto prot_err
;
1430 len
= asn1_tag_remaining(data
);
1434 newsup
= talloc_array(msg
, char, len
+1);
1435 if (newsup
== NULL
) {
1436 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1438 if (!asn1_read(data
, newsup
, len
)) goto prot_err
;
1440 r
->newsuperior
= newsup
;
1441 if (!asn1_end_tag(data
)) goto prot_err
;
1443 if (!asn1_end_tag(data
)) goto prot_err
;
1447 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1448 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1449 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1450 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1451 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1452 if (!asn1_end_tag(data
)) goto prot_err
;
1456 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1457 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1458 msg
->type
= LDAP_TAG_CompareRequest
;
1459 if (!asn1_start_tag(data
,
1460 ASN1_APPLICATION(LDAP_TAG_CompareRequest
))) goto prot_err
;
1461 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->dn
)) goto prot_err
;
1462 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto prot_err
;
1463 if (!asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
)) goto prot_err
;
1464 if (!asn1_read_OctetString(data
, msg
, &r
->value
)) goto prot_err
;
1465 if (r
->value
.data
) {
1466 talloc_steal(msg
, r
->value
.data
);
1468 if (!asn1_end_tag(data
)) goto prot_err
;
1469 if (!asn1_end_tag(data
)) goto prot_err
;
1473 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1474 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1475 msg
->type
= LDAP_TAG_CompareResponse
;
1476 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1477 if (!ldap_decode_response(msg
, data
, r
)) goto prot_err
;
1478 if (!asn1_end_tag(data
)) goto prot_err
;
1482 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1483 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1484 msg
->type
= LDAP_TAG_AbandonRequest
;
1485 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1486 if (!asn1_read_implicit_Integer(data
, &r
->messageid
)) goto prot_err
;
1487 if (!asn1_end_tag(data
)) goto prot_err
;
1491 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1492 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1493 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1495 msg
->type
= LDAP_TAG_ExtendedRequest
;
1496 if (!asn1_start_tag(data
,tag
)) goto prot_err
;
1497 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1500 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1501 data_blob_free(&tmp_blob
);
1503 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1506 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1507 if (!asn1_read_ContextSimple(data
, 1, &tmp_blob
)) goto prot_err
;
1508 r
->value
= talloc(msg
, DATA_BLOB
);
1510 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1512 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1513 data_blob_free(&tmp_blob
);
1518 if (!asn1_end_tag(data
)) goto prot_err
;
1522 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1523 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1524 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1526 msg
->type
= LDAP_TAG_ExtendedResponse
;
1527 if (!asn1_start_tag(data
, tag
)) goto prot_err
;
1528 if (!ldap_decode_response(msg
, data
, &r
->response
)) goto prot_err
;
1530 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1531 if (!asn1_read_ContextSimple(data
, 1, &tmp_blob
)) goto prot_err
;
1532 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1533 data_blob_free(&tmp_blob
);
1535 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1541 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1542 if (!asn1_read_ContextSimple(data
, 1, &tmp_blob
)) goto prot_err
;
1543 r
->value
= talloc(msg
, DATA_BLOB
);
1545 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1547 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1548 data_blob_free(&tmp_blob
);
1553 if (!asn1_end_tag(data
)) goto prot_err
;
1560 msg
->controls
= NULL
;
1561 msg
->controls_decoded
= NULL
;
1563 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1565 struct ldb_control
**ctrl
= NULL
;
1566 bool *decoded
= NULL
;
1568 if (!asn1_start_tag(data
, ASN1_CONTEXT(0))) goto prot_err
;
1570 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1572 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1574 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1576 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1579 decoded
= talloc_realloc(msg
, decoded
, bool, i
+1);
1581 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1584 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1586 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1589 if (!ldap_decode_control_wrapper(ctrl
[i
], data
, ctrl
[i
], &value
)) {
1593 if (!ldap_decode_control_value(ctrl
[i
], value
,
1596 if (ctrl
[i
]->critical
) {
1597 ctrl
[i
]->data
= NULL
;
1601 talloc_free(ctrl
[i
]);
1614 msg
->controls
= ctrl
;
1615 msg
->controls_decoded
= decoded
;
1617 if (!asn1_end_tag(data
)) goto prot_err
;
1620 if (!asn1_end_tag(data
)) goto prot_err
;
1621 if ((data
->has_error
) || (data
->nesting
!= NULL
)) {
1622 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1624 return NT_STATUS_OK
;
1628 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1633 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1634 ldap packet. Set packet_size if true.
1636 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1638 if (blob
.length
< 6) {
1640 * We need at least 6 bytes to workout the length
1643 return STATUS_MORE_ENTRIES
;
1645 return asn1_peek_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);