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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "libcli/util/asn_1.h"
28 #include "libcli/ldap/ldap.h"
31 static BOOL
ldap_push_filter(struct asn1_data
*data
, struct ldb_parse_tree
*tree
)
35 switch (tree
->operation
) {
38 asn1_push_tag(data
, ASN1_CONTEXT(tree
->operation
==LDB_OP_AND
?0:1));
39 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
40 if (!ldap_push_filter(data
, tree
->u
.list
.elements
[i
])) {
48 asn1_push_tag(data
, ASN1_CONTEXT(2));
49 if (!ldap_push_filter(data
, tree
->u
.isnot
.child
)) {
57 asn1_push_tag(data
, ASN1_CONTEXT(3));
58 asn1_write_OctetString(data
, tree
->u
.equality
.attr
,
59 strlen(tree
->u
.equality
.attr
));
60 asn1_write_OctetString(data
, tree
->u
.equality
.value
.data
,
61 tree
->u
.equality
.value
.length
);
65 case LDB_OP_SUBSTRING
:
67 SubstringFilter ::= SEQUENCE {
68 type AttributeDescription,
69 -- at least one must be present
70 substrings SEQUENCE OF CHOICE {
71 initial [0] LDAPString,
73 final [2] LDAPString } }
75 asn1_push_tag(data
, ASN1_CONTEXT(4));
76 asn1_write_OctetString(data
, tree
->u
.substring
.attr
, strlen(tree
->u
.substring
.attr
));
77 asn1_push_tag(data
, ASN1_SEQUENCE(0));
79 if ( ! tree
->u
.substring
.start_with_wildcard
) {
80 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
81 asn1_write_LDAPString(data
, (char *)tree
->u
.substring
.chunks
[i
]->data
);
85 while (tree
->u
.substring
.chunks
[i
]) {
88 if (( ! tree
->u
.substring
.chunks
[i
+ 1]) &&
89 (tree
->u
.substring
.end_with_wildcard
== 0)) {
94 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(ctx
));
95 asn1_write_LDAPString(data
, (char *)tree
->u
.substring
.chunks
[i
]->data
);
104 /* greaterOrEqual test */
105 asn1_push_tag(data
, ASN1_CONTEXT(5));
106 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
107 strlen(tree
->u
.comparison
.attr
));
108 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
109 tree
->u
.comparison
.value
.length
);
114 /* lessOrEqual test */
115 asn1_push_tag(data
, ASN1_CONTEXT(6));
116 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
117 strlen(tree
->u
.comparison
.attr
));
118 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
119 tree
->u
.comparison
.value
.length
);
125 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(7));
126 asn1_write_LDAPString(data
, tree
->u
.present
.attr
);
128 return !data
->has_error
;
132 asn1_push_tag(data
, ASN1_CONTEXT(8));
133 asn1_write_OctetString(data
, tree
->u
.comparison
.attr
,
134 strlen(tree
->u
.comparison
.attr
));
135 asn1_write_OctetString(data
, tree
->u
.comparison
.value
.data
,
136 tree
->u
.comparison
.value
.length
);
140 case LDB_OP_EXTENDED
:
142 MatchingRuleAssertion ::= SEQUENCE {
143 matchingRule [1] MatchingRuleID OPTIONAL,
144 type [2] AttributeDescription OPTIONAL,
145 matchValue [3] AssertionValue,
146 dnAttributes [4] BOOLEAN DEFAULT FALSE
149 asn1_push_tag(data
, ASN1_CONTEXT(9));
150 if (tree
->u
.extended
.rule_id
) {
151 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
152 asn1_write_LDAPString(data
, tree
->u
.extended
.rule_id
);
155 if (tree
->u
.extended
.attr
) {
156 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2));
157 asn1_write_LDAPString(data
, tree
->u
.extended
.attr
);
160 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3));
161 asn1_write_LDAPString(data
, (char *)tree
->u
.extended
.value
.data
);
163 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4));
164 asn1_write_uint8(data
, tree
->u
.extended
.dnAttributes
);
172 return !data
->has_error
;
175 static void ldap_encode_response(struct asn1_data
*data
, struct ldap_Result
*result
)
177 asn1_write_enumerated(data
, result
->resultcode
);
178 asn1_write_OctetString(data
, result
->dn
,
179 (result
->dn
) ? strlen(result
->dn
) : 0);
180 asn1_write_OctetString(data
, result
->errormessage
,
181 (result
->errormessage
) ?
182 strlen(result
->errormessage
) : 0);
183 if (result
->referral
) {
184 asn1_push_tag(data
, ASN1_CONTEXT(3));
185 asn1_write_OctetString(data
, result
->referral
,
186 strlen(result
->referral
));
191 BOOL
ldap_encode(struct ldap_message
*msg
, DATA_BLOB
*result
, TALLOC_CTX
*mem_ctx
)
193 struct asn1_data data
;
197 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
198 asn1_write_Integer(&data
, msg
->messageid
);
201 case LDAP_TAG_BindRequest
: {
202 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
203 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
204 asn1_write_Integer(&data
, r
->version
);
205 asn1_write_OctetString(&data
, r
->dn
,
206 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0);
208 switch (r
->mechanism
) {
209 case LDAP_AUTH_MECH_SIMPLE
:
210 /* context, primitive */
211 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
212 asn1_write(&data
, r
->creds
.password
,
213 strlen(r
->creds
.password
));
216 case LDAP_AUTH_MECH_SASL
:
217 /* context, constructed */
218 asn1_push_tag(&data
, ASN1_CONTEXT(3));
219 asn1_write_OctetString(&data
, r
->creds
.SASL
.mechanism
,
220 strlen(r
->creds
.SASL
.mechanism
));
221 if (r
->creds
.SASL
.secblob
) {
222 asn1_write_OctetString(&data
, r
->creds
.SASL
.secblob
->data
,
223 r
->creds
.SASL
.secblob
->length
);
234 case LDAP_TAG_BindResponse
: {
235 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
236 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
237 ldap_encode_response(&data
, &r
->response
);
238 if (r
->SASL
.secblob
) {
239 asn1_write_ContextSimple(&data
, 7, r
->SASL
.secblob
);
244 case LDAP_TAG_UnbindRequest
: {
245 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
248 case LDAP_TAG_SearchRequest
: {
249 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
250 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
251 asn1_write_OctetString(&data
, r
->basedn
, strlen(r
->basedn
));
252 asn1_write_enumerated(&data
, r
->scope
);
253 asn1_write_enumerated(&data
, r
->deref
);
254 asn1_write_Integer(&data
, r
->sizelimit
);
255 asn1_write_Integer(&data
, r
->timelimit
);
256 asn1_write_BOOLEAN(&data
, r
->attributesonly
);
258 if (!ldap_push_filter(&data
, r
->tree
)) {
262 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
263 for (i
=0; i
<r
->num_attributes
; i
++) {
264 asn1_write_OctetString(&data
, r
->attributes
[i
],
265 strlen(r
->attributes
[i
]));
271 case LDAP_TAG_SearchResultEntry
: {
272 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
273 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
274 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
275 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
276 for (i
=0; i
<r
->num_attributes
; i
++) {
277 struct ldb_message_element
*attr
= &r
->attributes
[i
];
278 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
279 asn1_write_OctetString(&data
, attr
->name
,
281 asn1_push_tag(&data
, ASN1_SEQUENCE(1));
282 for (j
=0; j
<attr
->num_values
; j
++) {
283 asn1_write_OctetString(&data
,
284 attr
->values
[j
].data
,
285 attr
->values
[j
].length
);
294 case LDAP_TAG_SearchResultDone
: {
295 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
296 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
297 ldap_encode_response(&data
, r
);
301 case LDAP_TAG_ModifyRequest
: {
302 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
303 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
304 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
305 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
307 for (i
=0; i
<r
->num_mods
; i
++) {
308 struct ldb_message_element
*attrib
= &r
->mods
[i
].attrib
;
309 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
310 asn1_write_enumerated(&data
, r
->mods
[i
].type
);
311 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
312 asn1_write_OctetString(&data
, attrib
->name
,
313 strlen(attrib
->name
));
314 asn1_push_tag(&data
, ASN1_SET
);
315 for (j
=0; j
<attrib
->num_values
; j
++) {
316 asn1_write_OctetString(&data
,
317 attrib
->values
[j
].data
,
318 attrib
->values
[j
].length
);
330 case LDAP_TAG_ModifyResponse
: {
331 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
332 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
333 ldap_encode_response(&data
, r
);
337 case LDAP_TAG_AddRequest
: {
338 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
339 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
340 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
341 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
343 for (i
=0; i
<r
->num_attributes
; i
++) {
344 struct ldb_message_element
*attrib
= &r
->attributes
[i
];
345 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
346 asn1_write_OctetString(&data
, attrib
->name
,
347 strlen(attrib
->name
));
348 asn1_push_tag(&data
, ASN1_SET
);
349 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
350 asn1_write_OctetString(&data
,
351 attrib
->values
[j
].data
,
352 attrib
->values
[j
].length
);
361 case LDAP_TAG_AddResponse
: {
362 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
363 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
364 ldap_encode_response(&data
, r
);
368 case LDAP_TAG_DelRequest
: {
369 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
370 asn1_push_tag(&data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
371 asn1_write(&data
, r
->dn
, strlen(r
->dn
));
375 case LDAP_TAG_DelResponse
: {
376 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
377 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
378 ldap_encode_response(&data
, r
);
382 case LDAP_TAG_ModifyDNRequest
: {
383 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
384 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
385 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
386 asn1_write_OctetString(&data
, r
->newrdn
, strlen(r
->newrdn
));
387 asn1_write_BOOLEAN(&data
, r
->deleteolddn
);
388 if (r
->newsuperior
) {
389 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
390 asn1_write(&data
, r
->newsuperior
,
391 strlen(r
->newsuperior
));
397 case LDAP_TAG_ModifyDNResponse
: {
398 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
399 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
400 ldap_encode_response(&data
, r
);
404 case LDAP_TAG_CompareRequest
: {
405 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
406 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
407 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
408 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
409 asn1_write_OctetString(&data
, r
->attribute
,
410 strlen(r
->attribute
));
411 asn1_write_OctetString(&data
, r
->value
.data
,
417 case LDAP_TAG_CompareResponse
: {
418 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
419 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
420 ldap_encode_response(&data
, r
);
424 case LDAP_TAG_AbandonRequest
: {
425 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
426 asn1_push_tag(&data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
427 asn1_write_implicit_Integer(&data
, r
->messageid
);
431 case LDAP_TAG_SearchResultReference
: {
432 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
433 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
434 asn1_write_OctetString(&data
, r
->referral
, strlen(r
->referral
));
438 case LDAP_TAG_ExtendedRequest
: {
439 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
440 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
441 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
442 asn1_write(&data
, r
->oid
, strlen(r
->oid
));
445 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(1));
446 asn1_write(&data
, r
->value
->data
, r
->value
->length
);
452 case LDAP_TAG_ExtendedResponse
: {
453 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
454 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
455 ldap_encode_response(&data
, &r
->response
);
457 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(10));
458 asn1_write(&data
, r
->oid
, strlen(r
->oid
));
462 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(11));
463 asn1_write(&data
, r
->value
->data
, r
->value
->length
);
473 if (msg
->controls
!= NULL
) {
474 asn1_push_tag(&data
, ASN1_CONTEXT(0));
476 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
477 if (!ldap_encode_control(mem_ctx
, &data
, msg
->controls
[i
])) {
487 if (data
.has_error
) {
492 *result
= data_blob_talloc(mem_ctx
, data
.data
, data
.length
);
497 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
500 char *result
= talloc_size(mem_ctx
, blob
.length
+1);
501 memcpy(result
, blob
.data
, blob
.length
);
502 result
[blob
.length
] = '\0';
506 static BOOL
asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
507 struct asn1_data
*data
,
511 if (!asn1_read_OctetString(data
, &string
))
513 *result
= blob2string_talloc(mem_ctx
, string
);
514 data_blob_free(&string
);
518 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
519 struct asn1_data
*data
,
520 struct ldap_Result
*result
)
522 asn1_read_enumerated(data
, &result
->resultcode
);
523 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
524 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
525 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
526 asn1_start_tag(data
, ASN1_CONTEXT(3));
527 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
530 result
->referral
= NULL
;
534 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
537 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
538 if (chunks
== NULL
) {
542 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
543 if (chunks
[chunk_num
] == NULL
) {
547 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
548 if (chunks
[chunk_num
]->data
== NULL
) {
551 chunks
[chunk_num
]->length
= strlen(value
);
553 chunks
[chunk_num
+ 1] = '\0';
560 parse the ASN.1 formatted search string into a ldb_parse_tree
562 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
563 struct asn1_data
*data
)
566 struct ldb_parse_tree
*ret
;
568 if (!asn1_peek_uint8(data
, &filter_tag
)) {
572 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
574 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
575 if (ret
== NULL
) return NULL
;
580 /* AND or OR of one or more filters */
581 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
582 ret
->u
.list
.num_elements
= 0;
583 ret
->u
.list
.elements
= NULL
;
585 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
589 while (asn1_tag_remaining(data
) > 0) {
590 struct ldb_parse_tree
*subtree
;
591 subtree
= ldap_decode_filter_tree(ret
, data
);
592 if (subtree
== NULL
) {
595 ret
->u
.list
.elements
=
596 talloc_realloc(ret
, ret
->u
.list
.elements
,
597 struct ldb_parse_tree
*,
598 ret
->u
.list
.num_elements
+1);
599 if (ret
->u
.list
.elements
== NULL
) {
602 talloc_steal(ret
->u
.list
.elements
, subtree
);
603 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
604 ret
->u
.list
.num_elements
++;
606 if (!asn1_end_tag(data
)) {
612 /* 'not' operation */
613 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
617 ret
->operation
= LDB_OP_NOT
;
618 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
619 if (ret
->u
.isnot
.child
== NULL
) {
622 if (!asn1_end_tag(data
)) {
632 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
633 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
634 asn1_read_OctetString(data
, &value
);
636 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
640 ret
->operation
= LDB_OP_EQUALITY
;
641 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
642 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
643 ret
->u
.equality
.value
.length
= value
.length
;
653 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
656 if (!asn1_read_OctetString(data
, &attr
)) {
660 ret
->operation
= LDB_OP_SUBSTRING
;
661 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
662 ret
->u
.substring
.chunks
= NULL
;
663 ret
->u
.substring
.start_with_wildcard
= 1;
664 ret
->u
.substring
.end_with_wildcard
= 1;
666 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
670 while (asn1_tag_remaining(data
)) {
671 asn1_peek_uint8(data
, &subs_tag
);
672 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
673 if (subs_tag
> 2) goto failed
;
675 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
));
676 asn1_read_LDAPString(data
, &value
);
681 if (ret
->u
.substring
.chunks
!= NULL
) {
682 /* initial value found in the middle */
686 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
687 if (ret
->u
.substring
.chunks
== NULL
) {
691 ret
->u
.substring
.start_with_wildcard
= 0;
696 if (ret
->u
.substring
.end_with_wildcard
== 0) {
697 /* "any" value found after a "final" value */
701 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
702 ret
->u
.substring
.chunks
,
705 if (ret
->u
.substring
.chunks
== NULL
) {
713 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
714 ret
->u
.substring
.chunks
,
717 if (ret
->u
.substring
.chunks
== NULL
) {
721 ret
->u
.substring
.end_with_wildcard
= 0;
730 if (!asn1_end_tag(data
)) { /* SEQUENCE */
734 if (!asn1_end_tag(data
)) {
744 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
745 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
746 asn1_read_OctetString(data
, &value
);
748 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
752 ret
->operation
= LDB_OP_GREATER
;
753 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
754 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
755 ret
->u
.comparison
.value
.length
= value
.length
;
763 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
764 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
765 asn1_read_OctetString(data
, &value
);
767 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
771 ret
->operation
= LDB_OP_LESS
;
772 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
773 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
774 ret
->u
.comparison
.value
.length
= value
.length
;
778 /* Normal presence, "attribute=*" */
781 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
784 if (!asn1_read_LDAPString(data
, &attr
)) {
788 ret
->operation
= LDB_OP_PRESENT
;
789 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
791 if (!asn1_end_tag(data
)) {
801 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
802 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
803 asn1_read_OctetString(data
, &value
);
805 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
809 ret
->operation
= LDB_OP_APPROX
;
810 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
811 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
812 ret
->u
.comparison
.value
.length
= value
.length
;
816 char *oid
= NULL
, *attr
= NULL
, *value
;
817 uint8_t dnAttributes
;
818 /* an extended search */
819 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
823 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
824 we need to check we properly implement --SSS */
825 /* either oid or type must be defined */
826 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
827 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1));
828 asn1_read_LDAPString(data
, &oid
);
831 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
832 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2));
833 asn1_read_LDAPString(data
, &attr
);
836 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
837 asn1_read_LDAPString(data
, &value
);
839 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
840 it is not marked as OPTIONAL but openldap tools
841 do not set this unless it is to be set as TRUE
842 NOTE: openldap tools do not work with AD as it
843 seems that AD always requires the dnAttributes
844 boolean value to be set */
845 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
846 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4));
847 asn1_read_uint8(data
, &dnAttributes
);
852 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
857 ret
->operation
= LDB_OP_EXTENDED
;
859 /* From the RFC2251: If the type field is
860 absent and matchingRule is present, the matchValue is compared
861 against all attributes in an entry which support that matchingRule
864 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
866 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
868 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
869 ret
->u
.extended
.value
.data
= talloc_steal(ret
, value
);
870 ret
->u
.extended
.value
.length
= strlen(value
);
871 ret
->u
.extended
.dnAttributes
= dnAttributes
;
873 ret
->operation
= LDB_OP_EQUALITY
;
874 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
875 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
);
876 ret
->u
.equality
.value
.length
= strlen(value
);
878 if (!asn1_end_tag(data
)) {
885 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag
));
897 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
898 struct ldb_message_element
*attrib
)
900 asn1_start_tag(data
, ASN1_SEQUENCE(0));
901 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
902 asn1_start_tag(data
, ASN1_SET
);
903 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
905 asn1_read_OctetString(data
, &blob
);
906 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
913 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
914 struct ldb_message_element
**attributes
,
917 asn1_start_tag(data
, ASN1_SEQUENCE(0));
918 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
919 struct ldb_message_element attrib
;
921 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
922 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
923 attributes
, num_attributes
);
928 BOOL
ldap_decode(struct asn1_data
*data
, struct ldap_message
*msg
)
932 asn1_start_tag(data
, ASN1_SEQUENCE(0));
933 asn1_read_Integer(data
, &msg
->messageid
);
935 if (!asn1_peek_uint8(data
, &tag
))
940 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
941 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
942 msg
->type
= LDAP_TAG_BindRequest
;
943 asn1_start_tag(data
, tag
);
944 asn1_read_Integer(data
, &r
->version
);
945 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
946 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
948 r
->creds
.password
= "";
949 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
950 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
951 pwlen
= asn1_tag_remaining(data
);
956 char *pw
= talloc_size(msg
, pwlen
+1);
960 asn1_read(data
, pw
, pwlen
);
962 r
->creds
.password
= pw
;
965 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
966 asn1_start_tag(data
, ASN1_CONTEXT(3));
967 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
968 asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
);
969 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
970 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
971 asn1_read_OctetString(data
, &tmp_blob
);
972 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
973 if (!r
->creds
.SASL
.secblob
) {
976 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
977 tmp_blob
.data
, tmp_blob
.length
);
978 data_blob_free(&tmp_blob
);
980 r
->creds
.SASL
.secblob
= NULL
;
984 /* Neither Simple nor SASL bind */
991 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
992 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
993 msg
->type
= LDAP_TAG_BindResponse
;
994 asn1_start_tag(data
, tag
);
995 ldap_decode_response(msg
, data
, &r
->response
);
996 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
997 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
998 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
999 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1000 if (!r
->SASL
.secblob
) {
1003 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1004 tmp_blob
.data
, tmp_blob
.length
);
1005 data_blob_free(&tmp_blob
);
1007 r
->SASL
.secblob
= NULL
;
1013 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1014 msg
->type
= LDAP_TAG_UnbindRequest
;
1015 asn1_start_tag(data
, tag
);
1020 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1021 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1022 msg
->type
= LDAP_TAG_SearchRequest
;
1023 asn1_start_tag(data
, tag
);
1024 asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
);
1025 asn1_read_enumerated(data
, (int *)&(r
->scope
));
1026 asn1_read_enumerated(data
, (int *)&(r
->deref
));
1027 asn1_read_Integer(data
, &r
->sizelimit
);
1028 asn1_read_Integer(data
, &r
->timelimit
);
1029 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
1031 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1032 if (r
->tree
== NULL
) {
1036 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1038 r
->num_attributes
= 0;
1039 r
->attributes
= NULL
;
1041 while (asn1_tag_remaining(data
) > 0) {
1043 if (!asn1_read_OctetString_talloc(msg
, data
,
1046 if (!add_string_to_array(msg
, attr
,
1048 &r
->num_attributes
))
1057 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1058 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1059 msg
->type
= LDAP_TAG_SearchResultEntry
;
1060 r
->attributes
= NULL
;
1061 r
->num_attributes
= 0;
1062 asn1_start_tag(data
, tag
);
1063 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1064 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1065 &r
->num_attributes
);
1070 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1071 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1072 msg
->type
= LDAP_TAG_SearchResultDone
;
1073 asn1_start_tag(data
, tag
);
1074 ldap_decode_response(msg
, data
, r
);
1079 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1080 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1081 msg
->type
= LDAP_TAG_SearchResultReference
;
1082 asn1_start_tag(data
, tag
);
1083 asn1_read_OctetString_talloc(msg
, data
, &r
->referral
);
1088 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1089 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1090 msg
->type
= LDAP_TAG_ModifyRequest
;
1091 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
1092 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1093 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1098 while (asn1_tag_remaining(data
) > 0) {
1099 struct ldap_mod mod
;
1102 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1103 asn1_read_enumerated(data
, &v
);
1105 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1107 if (!add_mod_to_array_talloc(msg
, &mod
,
1108 &r
->mods
, &r
->num_mods
)) {
1118 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1119 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1120 msg
->type
= LDAP_TAG_ModifyResponse
;
1121 asn1_start_tag(data
, tag
);
1122 ldap_decode_response(msg
, data
, r
);
1127 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1128 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1129 msg
->type
= LDAP_TAG_AddRequest
;
1130 asn1_start_tag(data
, tag
);
1131 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1133 r
->attributes
= NULL
;
1134 r
->num_attributes
= 0;
1135 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1136 &r
->num_attributes
);
1142 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1143 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1144 msg
->type
= LDAP_TAG_AddResponse
;
1145 asn1_start_tag(data
, tag
);
1146 ldap_decode_response(msg
, data
, r
);
1151 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1152 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1155 msg
->type
= LDAP_TAG_DelRequest
;
1156 asn1_start_tag(data
,
1157 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1158 len
= asn1_tag_remaining(data
);
1162 dn
= talloc_size(msg
, len
+1);
1165 asn1_read(data
, dn
, len
);
1172 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1173 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1174 msg
->type
= LDAP_TAG_DelResponse
;
1175 asn1_start_tag(data
, tag
);
1176 ldap_decode_response(msg
, data
, r
);
1181 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1182 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1183 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1184 asn1_start_tag(data
,
1185 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
1186 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1187 asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
);
1188 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
1189 r
->newsuperior
= NULL
;
1190 if (asn1_tag_remaining(data
) > 0) {
1193 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1194 len
= asn1_tag_remaining(data
);
1198 newsup
= talloc_size(msg
, len
+1);
1199 if (newsup
== NULL
) {
1202 asn1_read(data
, newsup
, len
);
1204 r
->newsuperior
= newsup
;
1211 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1212 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1213 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1214 asn1_start_tag(data
, tag
);
1215 ldap_decode_response(msg
, data
, r
);
1220 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1221 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1222 msg
->type
= LDAP_TAG_CompareRequest
;
1223 asn1_start_tag(data
,
1224 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
1225 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1226 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1227 asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
);
1228 asn1_read_OctetString(data
, &r
->value
);
1229 if (r
->value
.data
) {
1230 talloc_steal(msg
, r
->value
.data
);
1237 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1238 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1239 msg
->type
= LDAP_TAG_CompareResponse
;
1240 asn1_start_tag(data
, tag
);
1241 ldap_decode_response(msg
, data
, r
);
1246 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1247 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1248 msg
->type
= LDAP_TAG_AbandonRequest
;
1249 asn1_start_tag(data
, tag
);
1250 asn1_read_implicit_Integer(data
, &r
->messageid
);
1255 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1256 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1257 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1259 msg
->type
= LDAP_TAG_ExtendedRequest
;
1260 asn1_start_tag(data
,tag
);
1261 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1264 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1265 data_blob_free(&tmp_blob
);
1270 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1271 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1272 r
->value
= talloc(msg
, DATA_BLOB
);
1276 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1277 data_blob_free(&tmp_blob
);
1286 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1287 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1288 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1290 msg
->type
= LDAP_TAG_ExtendedResponse
;
1291 asn1_start_tag(data
, tag
);
1292 ldap_decode_response(msg
, data
, &r
->response
);
1294 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1295 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1296 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1297 data_blob_free(&tmp_blob
);
1305 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1306 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1307 r
->value
= talloc(msg
, DATA_BLOB
);
1311 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1312 data_blob_free(&tmp_blob
);
1324 msg
->controls
= NULL
;
1326 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1328 struct ldb_control
**ctrl
= NULL
;
1330 asn1_start_tag(data
, ASN1_CONTEXT(0));
1332 for (i
=0; asn1_peek_tag(data
, ASN1_SEQUENCE(0)); i
++) {
1333 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1335 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1340 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1345 if (!ldap_decode_control(ctrl
, data
, ctrl
[i
])) {
1355 msg
->controls
= ctrl
;
1361 return ((!data
->has_error
) && (data
->nesting
== NULL
));
1366 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1367 ldap packet. Set packet_size if true.
1369 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1371 return asn1_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);