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
= asn1_init(mem_ctx
);
196 asn1_push_tag(data
, ASN1_SEQUENCE(0));
197 asn1_write_Integer(data
, msg
->messageid
);
200 case LDAP_TAG_BindRequest
: {
201 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
202 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
203 asn1_write_Integer(data
, r
->version
);
204 asn1_write_OctetString(data
, r
->dn
,
205 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0);
207 switch (r
->mechanism
) {
208 case LDAP_AUTH_MECH_SIMPLE
:
209 /* context, primitive */
210 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
211 asn1_write(data
, r
->creds
.password
,
212 strlen(r
->creds
.password
));
215 case LDAP_AUTH_MECH_SASL
:
216 /* context, constructed */
217 asn1_push_tag(data
, ASN1_CONTEXT(3));
218 asn1_write_OctetString(data
, r
->creds
.SASL
.mechanism
,
219 strlen(r
->creds
.SASL
.mechanism
));
220 if (r
->creds
.SASL
.secblob
) {
221 asn1_write_OctetString(data
, r
->creds
.SASL
.secblob
->data
,
222 r
->creds
.SASL
.secblob
->length
);
233 case LDAP_TAG_BindResponse
: {
234 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
235 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
236 ldap_encode_response(data
, &r
->response
);
237 if (r
->SASL
.secblob
) {
238 asn1_write_ContextSimple(data
, 7, r
->SASL
.secblob
);
243 case LDAP_TAG_UnbindRequest
: {
244 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
247 case LDAP_TAG_SearchRequest
: {
248 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
249 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
250 asn1_write_OctetString(data
, r
->basedn
, strlen(r
->basedn
));
251 asn1_write_enumerated(data
, r
->scope
);
252 asn1_write_enumerated(data
, r
->deref
);
253 asn1_write_Integer(data
, r
->sizelimit
);
254 asn1_write_Integer(data
, r
->timelimit
);
255 asn1_write_BOOLEAN(data
, r
->attributesonly
);
257 if (!ldap_push_filter(data
, r
->tree
)) {
261 asn1_push_tag(data
, ASN1_SEQUENCE(0));
262 for (i
=0; i
<r
->num_attributes
; i
++) {
263 asn1_write_OctetString(data
, r
->attributes
[i
],
264 strlen(r
->attributes
[i
]));
270 case LDAP_TAG_SearchResultEntry
: {
271 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
272 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
273 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
274 asn1_push_tag(data
, ASN1_SEQUENCE(0));
275 for (i
=0; i
<r
->num_attributes
; i
++) {
276 struct ldb_message_element
*attr
= &r
->attributes
[i
];
277 asn1_push_tag(data
, ASN1_SEQUENCE(0));
278 asn1_write_OctetString(data
, attr
->name
,
280 asn1_push_tag(data
, ASN1_SEQUENCE(1));
281 for (j
=0; j
<attr
->num_values
; j
++) {
282 asn1_write_OctetString(data
,
283 attr
->values
[j
].data
,
284 attr
->values
[j
].length
);
293 case LDAP_TAG_SearchResultDone
: {
294 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
295 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
296 ldap_encode_response(data
, r
);
300 case LDAP_TAG_ModifyRequest
: {
301 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
302 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
303 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
304 asn1_push_tag(data
, ASN1_SEQUENCE(0));
306 for (i
=0; i
<r
->num_mods
; i
++) {
307 struct ldb_message_element
*attrib
= &r
->mods
[i
].attrib
;
308 asn1_push_tag(data
, ASN1_SEQUENCE(0));
309 asn1_write_enumerated(data
, r
->mods
[i
].type
);
310 asn1_push_tag(data
, ASN1_SEQUENCE(0));
311 asn1_write_OctetString(data
, attrib
->name
,
312 strlen(attrib
->name
));
313 asn1_push_tag(data
, ASN1_SET
);
314 for (j
=0; j
<attrib
->num_values
; j
++) {
315 asn1_write_OctetString(data
,
316 attrib
->values
[j
].data
,
317 attrib
->values
[j
].length
);
329 case LDAP_TAG_ModifyResponse
: {
330 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
331 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
332 ldap_encode_response(data
, r
);
336 case LDAP_TAG_AddRequest
: {
337 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
338 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
339 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
340 asn1_push_tag(data
, ASN1_SEQUENCE(0));
342 for (i
=0; i
<r
->num_attributes
; i
++) {
343 struct ldb_message_element
*attrib
= &r
->attributes
[i
];
344 asn1_push_tag(data
, ASN1_SEQUENCE(0));
345 asn1_write_OctetString(data
, attrib
->name
,
346 strlen(attrib
->name
));
347 asn1_push_tag(data
, ASN1_SET
);
348 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
349 asn1_write_OctetString(data
,
350 attrib
->values
[j
].data
,
351 attrib
->values
[j
].length
);
360 case LDAP_TAG_AddResponse
: {
361 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
362 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
363 ldap_encode_response(data
, r
);
367 case LDAP_TAG_DelRequest
: {
368 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
369 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
370 asn1_write(data
, r
->dn
, strlen(r
->dn
));
374 case LDAP_TAG_DelResponse
: {
375 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
376 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
377 ldap_encode_response(data
, r
);
381 case LDAP_TAG_ModifyDNRequest
: {
382 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
383 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
384 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
385 asn1_write_OctetString(data
, r
->newrdn
, strlen(r
->newrdn
));
386 asn1_write_BOOLEAN(data
, r
->deleteolddn
);
387 if (r
->newsuperior
) {
388 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
389 asn1_write(data
, r
->newsuperior
,
390 strlen(r
->newsuperior
));
396 case LDAP_TAG_ModifyDNResponse
: {
397 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
398 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
399 ldap_encode_response(data
, r
);
403 case LDAP_TAG_CompareRequest
: {
404 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
405 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
406 asn1_write_OctetString(data
, r
->dn
, strlen(r
->dn
));
407 asn1_push_tag(data
, ASN1_SEQUENCE(0));
408 asn1_write_OctetString(data
, r
->attribute
,
409 strlen(r
->attribute
));
410 asn1_write_OctetString(data
, r
->value
.data
,
416 case LDAP_TAG_CompareResponse
: {
417 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
418 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
419 ldap_encode_response(data
, r
);
423 case LDAP_TAG_AbandonRequest
: {
424 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
425 asn1_push_tag(data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
426 asn1_write_implicit_Integer(data
, r
->messageid
);
430 case LDAP_TAG_SearchResultReference
: {
431 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
432 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
433 asn1_write_OctetString(data
, r
->referral
, strlen(r
->referral
));
437 case LDAP_TAG_ExtendedRequest
: {
438 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
439 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
440 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(0));
441 asn1_write(data
, r
->oid
, strlen(r
->oid
));
444 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1));
445 asn1_write(data
, r
->value
->data
, r
->value
->length
);
451 case LDAP_TAG_ExtendedResponse
: {
452 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
453 asn1_push_tag(data
, ASN1_APPLICATION(msg
->type
));
454 ldap_encode_response(data
, &r
->response
);
456 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(10));
457 asn1_write(data
, r
->oid
, strlen(r
->oid
));
461 asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(11));
462 asn1_write(data
, r
->value
->data
, r
->value
->length
);
472 if (msg
->controls
!= NULL
) {
473 asn1_push_tag(data
, ASN1_CONTEXT(0));
475 for (i
= 0; msg
->controls
[i
] != NULL
; i
++) {
476 if (!ldap_encode_control(mem_ctx
, data
, msg
->controls
[i
])) {
486 if (data
->has_error
) {
491 *result
= data_blob_talloc(mem_ctx
, data
->data
, data
->length
);
496 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
499 char *result
= talloc_size(mem_ctx
, blob
.length
+1);
500 memcpy(result
, blob
.data
, blob
.length
);
501 result
[blob
.length
] = '\0';
505 static BOOL
asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
506 struct asn1_data
*data
,
510 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
512 *result
= blob2string_talloc(mem_ctx
, string
);
513 data_blob_free(&string
);
517 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
518 struct asn1_data
*data
,
519 struct ldap_Result
*result
)
521 asn1_read_enumerated(data
, &result
->resultcode
);
522 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
523 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
524 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
525 asn1_start_tag(data
, ASN1_CONTEXT(3));
526 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
529 result
->referral
= NULL
;
533 static struct ldb_val
**ldap_decode_substring(TALLOC_CTX
*mem_ctx
, struct ldb_val
**chunks
, int chunk_num
, char *value
)
536 chunks
= talloc_realloc(mem_ctx
, chunks
, struct ldb_val
*, chunk_num
+ 2);
537 if (chunks
== NULL
) {
541 chunks
[chunk_num
] = talloc(mem_ctx
, struct ldb_val
);
542 if (chunks
[chunk_num
] == NULL
) {
546 chunks
[chunk_num
]->data
= (uint8_t *)talloc_strdup(mem_ctx
, value
);
547 if (chunks
[chunk_num
]->data
== NULL
) {
550 chunks
[chunk_num
]->length
= strlen(value
);
552 chunks
[chunk_num
+ 1] = '\0';
559 parse the ASN.1 formatted search string into a ldb_parse_tree
561 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
562 struct asn1_data
*data
)
565 struct ldb_parse_tree
*ret
;
567 if (!asn1_peek_uint8(data
, &filter_tag
)) {
571 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
573 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
574 if (ret
== NULL
) return NULL
;
579 /* AND or OR of one or more filters */
580 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
581 ret
->u
.list
.num_elements
= 0;
582 ret
->u
.list
.elements
= NULL
;
584 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
588 while (asn1_tag_remaining(data
) > 0) {
589 struct ldb_parse_tree
*subtree
;
590 subtree
= ldap_decode_filter_tree(ret
, data
);
591 if (subtree
== NULL
) {
594 ret
->u
.list
.elements
=
595 talloc_realloc(ret
, ret
->u
.list
.elements
,
596 struct ldb_parse_tree
*,
597 ret
->u
.list
.num_elements
+1);
598 if (ret
->u
.list
.elements
== NULL
) {
601 talloc_steal(ret
->u
.list
.elements
, subtree
);
602 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
603 ret
->u
.list
.num_elements
++;
605 if (!asn1_end_tag(data
)) {
611 /* 'not' operation */
612 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
616 ret
->operation
= LDB_OP_NOT
;
617 ret
->u
.isnot
.child
= ldap_decode_filter_tree(ret
, data
);
618 if (ret
->u
.isnot
.child
== NULL
) {
621 if (!asn1_end_tag(data
)) {
631 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
632 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
633 asn1_read_OctetString(data
, mem_ctx
, &value
);
635 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
639 ret
->operation
= LDB_OP_EQUALITY
;
640 ret
->u
.equality
.attr
= talloc_steal(ret
, attrib
);
641 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
.data
);
642 ret
->u
.equality
.value
.length
= value
.length
;
652 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
655 if (!asn1_read_OctetString(data
, mem_ctx
, &attr
)) {
659 ret
->operation
= LDB_OP_SUBSTRING
;
660 ret
->u
.substring
.attr
= talloc_strndup(ret
, (char *)attr
.data
, attr
.length
);
661 ret
->u
.substring
.chunks
= NULL
;
662 ret
->u
.substring
.start_with_wildcard
= 1;
663 ret
->u
.substring
.end_with_wildcard
= 1;
665 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) {
669 while (asn1_tag_remaining(data
)) {
670 asn1_peek_uint8(data
, &subs_tag
);
671 subs_tag
&= 0x1f; /* strip off the asn1 stuff */
672 if (subs_tag
> 2) goto failed
;
674 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(subs_tag
));
675 asn1_read_LDAPString(data
, mem_ctx
, &value
);
680 if (ret
->u
.substring
.chunks
!= NULL
) {
681 /* initial value found in the middle */
685 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
, NULL
, 0, value
);
686 if (ret
->u
.substring
.chunks
== NULL
) {
690 ret
->u
.substring
.start_with_wildcard
= 0;
695 if (ret
->u
.substring
.end_with_wildcard
== 0) {
696 /* "any" value found after a "final" value */
700 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
701 ret
->u
.substring
.chunks
,
704 if (ret
->u
.substring
.chunks
== NULL
) {
712 ret
->u
.substring
.chunks
= ldap_decode_substring(ret
,
713 ret
->u
.substring
.chunks
,
716 if (ret
->u
.substring
.chunks
== NULL
) {
720 ret
->u
.substring
.end_with_wildcard
= 0;
729 if (!asn1_end_tag(data
)) { /* SEQUENCE */
733 if (!asn1_end_tag(data
)) {
743 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
744 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
745 asn1_read_OctetString(data
, mem_ctx
, &value
);
747 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
751 ret
->operation
= LDB_OP_GREATER
;
752 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
753 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
754 ret
->u
.comparison
.value
.length
= value
.length
;
762 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
763 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
764 asn1_read_OctetString(data
, mem_ctx
, &value
);
766 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
770 ret
->operation
= LDB_OP_LESS
;
771 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
772 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
773 ret
->u
.comparison
.value
.length
= value
.length
;
777 /* Normal presence, "attribute=*" */
780 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(filter_tag
))) {
783 if (!asn1_read_LDAPString(data
, ret
, &attr
)) {
787 ret
->operation
= LDB_OP_PRESENT
;
788 ret
->u
.present
.attr
= talloc_steal(ret
, attr
);
790 if (!asn1_end_tag(data
)) {
800 asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
));
801 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
802 asn1_read_OctetString(data
, mem_ctx
, &value
);
804 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
808 ret
->operation
= LDB_OP_APPROX
;
809 ret
->u
.comparison
.attr
= talloc_steal(ret
, attrib
);
810 ret
->u
.comparison
.value
.data
= talloc_steal(ret
, value
.data
);
811 ret
->u
.comparison
.value
.length
= value
.length
;
815 char *oid
= NULL
, *attr
= NULL
, *value
;
816 uint8_t dnAttributes
;
817 /* an extended search */
818 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
822 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
823 we need to check we properly implement --SSS */
824 /* either oid or type must be defined */
825 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
826 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(1));
827 asn1_read_LDAPString(data
, ret
, &oid
);
830 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
831 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(2));
832 asn1_read_LDAPString(data
, ret
, &attr
);
835 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(3));
836 asn1_read_LDAPString(data
, ret
, &value
);
838 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
839 it is not marked as OPTIONAL but openldap tools
840 do not set this unless it is to be set as TRUE
841 NOTE: openldap tools do not work with AD as it
842 seems that AD always requires the dnAttributes
843 boolean value to be set */
844 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(4))) {
845 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(4));
846 asn1_read_uint8(data
, &dnAttributes
);
851 if ((oid
== NULL
&& attr
== NULL
) || (value
== NULL
)) {
856 ret
->operation
= LDB_OP_EXTENDED
;
858 /* From the RFC2251: If the type field is
859 absent and matchingRule is present, the matchValue is compared
860 against all attributes in an entry which support that matchingRule
863 ret
->u
.extended
.attr
= talloc_steal(ret
, attr
);
865 ret
->u
.extended
.attr
= talloc_strdup(ret
, "*");
867 ret
->u
.extended
.rule_id
= talloc_steal(ret
, oid
);
868 ret
->u
.extended
.value
.data
= talloc_steal(ret
, value
);
869 ret
->u
.extended
.value
.length
= strlen(value
);
870 ret
->u
.extended
.dnAttributes
= dnAttributes
;
872 ret
->operation
= LDB_OP_EQUALITY
;
873 ret
->u
.equality
.attr
= talloc_steal(ret
, attr
);
874 ret
->u
.equality
.value
.data
= talloc_steal(ret
, value
);
875 ret
->u
.equality
.value
.length
= strlen(value
);
877 if (!asn1_end_tag(data
)) {
884 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag
));
896 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
897 struct ldb_message_element
*attrib
)
899 asn1_start_tag(data
, ASN1_SEQUENCE(0));
900 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
901 asn1_start_tag(data
, ASN1_SET
);
902 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
904 asn1_read_OctetString(data
, mem_ctx
, &blob
);
905 add_value_to_attrib(mem_ctx
, &blob
, attrib
);
912 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
913 struct ldb_message_element
**attributes
,
916 asn1_start_tag(data
, ASN1_SEQUENCE(0));
917 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
918 struct ldb_message_element attrib
;
920 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
921 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
922 attributes
, num_attributes
);
927 /* This routine returns LDAP status codes */
929 NTSTATUS
ldap_decode(struct asn1_data
*data
, struct ldap_message
*msg
)
933 asn1_start_tag(data
, ASN1_SEQUENCE(0));
934 asn1_read_Integer(data
, &msg
->messageid
);
936 if (!asn1_peek_uint8(data
, &tag
))
937 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
941 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
942 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
943 msg
->type
= LDAP_TAG_BindRequest
;
944 asn1_start_tag(data
, tag
);
945 asn1_read_Integer(data
, &r
->version
);
946 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
947 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
949 r
->creds
.password
= "";
950 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
951 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
952 pwlen
= asn1_tag_remaining(data
);
954 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
957 char *pw
= talloc_size(msg
, pwlen
+1);
959 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
961 asn1_read(data
, pw
, pwlen
);
963 r
->creds
.password
= pw
;
966 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
967 asn1_start_tag(data
, ASN1_CONTEXT(3));
968 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
969 asn1_read_OctetString_talloc(msg
, data
, &r
->creds
.SASL
.mechanism
);
970 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) { /* optional */
971 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
972 asn1_read_OctetString(data
, msg
, &tmp_blob
);
973 r
->creds
.SASL
.secblob
= talloc(msg
, DATA_BLOB
);
974 if (!r
->creds
.SASL
.secblob
) {
975 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
977 *r
->creds
.SASL
.secblob
= data_blob_talloc(r
->creds
.SASL
.secblob
,
978 tmp_blob
.data
, tmp_blob
.length
);
979 data_blob_free(&tmp_blob
);
981 r
->creds
.SASL
.secblob
= NULL
;
985 /* Neither Simple nor SASL bind */
986 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
992 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
993 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
994 msg
->type
= LDAP_TAG_BindResponse
;
995 asn1_start_tag(data
, tag
);
996 ldap_decode_response(msg
, data
, &r
->response
);
997 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
998 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
999 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
1000 r
->SASL
.secblob
= talloc(msg
, DATA_BLOB
);
1001 if (!r
->SASL
.secblob
) {
1002 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1004 *r
->SASL
.secblob
= data_blob_talloc(r
->SASL
.secblob
,
1005 tmp_blob
.data
, tmp_blob
.length
);
1006 data_blob_free(&tmp_blob
);
1008 r
->SASL
.secblob
= NULL
;
1014 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
1015 msg
->type
= LDAP_TAG_UnbindRequest
;
1016 asn1_start_tag(data
, tag
);
1021 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
1022 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
1023 msg
->type
= LDAP_TAG_SearchRequest
;
1024 asn1_start_tag(data
, tag
);
1025 asn1_read_OctetString_talloc(msg
, data
, &r
->basedn
);
1026 asn1_read_enumerated(data
, (int *)&(r
->scope
));
1027 asn1_read_enumerated(data
, (int *)&(r
->deref
));
1028 asn1_read_Integer(data
, &r
->sizelimit
);
1029 asn1_read_Integer(data
, &r
->timelimit
);
1030 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
1032 r
->tree
= ldap_decode_filter_tree(msg
, data
);
1033 if (r
->tree
== NULL
) {
1034 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1037 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1039 r
->num_attributes
= 0;
1040 r
->attributes
= NULL
;
1042 while (asn1_tag_remaining(data
) > 0) {
1045 if (!asn1_read_OctetString_talloc(msg
, data
,
1047 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1048 if (!add_string_to_array(msg
, attr
,
1050 &r
->num_attributes
))
1051 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1059 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
1060 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
1061 msg
->type
= LDAP_TAG_SearchResultEntry
;
1062 r
->attributes
= NULL
;
1063 r
->num_attributes
= 0;
1064 asn1_start_tag(data
, tag
);
1065 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1066 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1067 &r
->num_attributes
);
1072 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
1073 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
1074 msg
->type
= LDAP_TAG_SearchResultDone
;
1075 asn1_start_tag(data
, tag
);
1076 ldap_decode_response(msg
, data
, r
);
1081 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
1082 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
1083 msg
->type
= LDAP_TAG_SearchResultReference
;
1084 asn1_start_tag(data
, tag
);
1085 asn1_read_OctetString_talloc(msg
, data
, &r
->referral
);
1090 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
1091 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
1092 msg
->type
= LDAP_TAG_ModifyRequest
;
1093 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
1094 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1095 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1100 while (asn1_tag_remaining(data
) > 0) {
1101 struct ldap_mod mod
;
1104 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1105 asn1_read_enumerated(data
, &v
);
1107 ldap_decode_attrib(msg
, data
, &mod
.attrib
);
1109 if (!add_mod_to_array_talloc(msg
, &mod
,
1110 &r
->mods
, &r
->num_mods
)) {
1111 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1120 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
1121 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
1122 msg
->type
= LDAP_TAG_ModifyResponse
;
1123 asn1_start_tag(data
, tag
);
1124 ldap_decode_response(msg
, data
, r
);
1129 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
1130 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
1131 msg
->type
= LDAP_TAG_AddRequest
;
1132 asn1_start_tag(data
, tag
);
1133 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1135 r
->attributes
= NULL
;
1136 r
->num_attributes
= 0;
1137 ldap_decode_attribs(msg
, data
, &r
->attributes
,
1138 &r
->num_attributes
);
1144 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
1145 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
1146 msg
->type
= LDAP_TAG_AddResponse
;
1147 asn1_start_tag(data
, tag
);
1148 ldap_decode_response(msg
, data
, r
);
1153 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
1154 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
1157 msg
->type
= LDAP_TAG_DelRequest
;
1158 asn1_start_tag(data
,
1159 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
1160 len
= asn1_tag_remaining(data
);
1162 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1164 dn
= talloc_size(msg
, len
+1);
1167 asn1_read(data
, dn
, len
);
1174 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
1175 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
1176 msg
->type
= LDAP_TAG_DelResponse
;
1177 asn1_start_tag(data
, tag
);
1178 ldap_decode_response(msg
, data
, r
);
1183 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
1184 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
1185 msg
->type
= LDAP_TAG_ModifyDNRequest
;
1186 asn1_start_tag(data
,
1187 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
1188 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1189 asn1_read_OctetString_talloc(msg
, data
, &r
->newrdn
);
1190 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
1191 r
->newsuperior
= NULL
;
1192 if (asn1_tag_remaining(data
) > 0) {
1195 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
1196 len
= asn1_tag_remaining(data
);
1198 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1200 newsup
= talloc_size(msg
, len
+1);
1201 if (newsup
== NULL
) {
1202 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1204 asn1_read(data
, newsup
, len
);
1206 r
->newsuperior
= newsup
;
1213 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
1214 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
1215 msg
->type
= LDAP_TAG_ModifyDNResponse
;
1216 asn1_start_tag(data
, tag
);
1217 ldap_decode_response(msg
, data
, r
);
1222 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
1223 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
1224 msg
->type
= LDAP_TAG_CompareRequest
;
1225 asn1_start_tag(data
,
1226 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
1227 asn1_read_OctetString_talloc(msg
, data
, &r
->dn
);
1228 asn1_start_tag(data
, ASN1_SEQUENCE(0));
1229 asn1_read_OctetString_talloc(msg
, data
, &r
->attribute
);
1230 asn1_read_OctetString(data
, msg
, &r
->value
);
1231 if (r
->value
.data
) {
1232 talloc_steal(msg
, r
->value
.data
);
1239 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
1240 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
1241 msg
->type
= LDAP_TAG_CompareResponse
;
1242 asn1_start_tag(data
, tag
);
1243 ldap_decode_response(msg
, data
, r
);
1248 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
1249 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
1250 msg
->type
= LDAP_TAG_AbandonRequest
;
1251 asn1_start_tag(data
, tag
);
1252 asn1_read_implicit_Integer(data
, &r
->messageid
);
1257 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
1258 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
1259 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1261 msg
->type
= LDAP_TAG_ExtendedRequest
;
1262 asn1_start_tag(data
,tag
);
1263 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
1264 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1266 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1267 data_blob_free(&tmp_blob
);
1269 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1272 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
1273 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1274 r
->value
= talloc(msg
, DATA_BLOB
);
1276 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1278 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1279 data_blob_free(&tmp_blob
);
1288 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
1289 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
1290 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
1292 msg
->type
= LDAP_TAG_ExtendedResponse
;
1293 asn1_start_tag(data
, tag
);
1294 ldap_decode_response(msg
, data
, &r
->response
);
1296 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(10))) {
1297 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1298 r
->oid
= blob2string_talloc(msg
, tmp_blob
);
1299 data_blob_free(&tmp_blob
);
1301 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1307 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(11))) {
1308 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
1309 r
->value
= talloc(msg
, DATA_BLOB
);
1311 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1313 *r
->value
= data_blob_talloc(r
->value
, tmp_blob
.data
, tmp_blob
.length
);
1314 data_blob_free(&tmp_blob
);
1323 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1326 msg
->controls
= NULL
;
1328 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
1330 struct ldb_control
**ctrl
= NULL
;
1332 asn1_start_tag(data
, ASN1_CONTEXT(0));
1334 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
1336 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1338 ctrl
= talloc_realloc(msg
, ctrl
, struct ldb_control
*, i
+2);
1340 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1343 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
1345 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR
);
1348 if (!ldap_decode_control_wrapper(ctrl
, data
, ctrl
[i
], &value
)) {
1349 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1352 if (!ldap_decode_control_value(ctrl
, value
, ctrl
[i
])) {
1353 if (ctrl
[i
]->critical
) {
1354 return NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION
);
1356 talloc_free(ctrl
[i
]);
1368 msg
->controls
= ctrl
;
1374 if ((data
->has_error
) || (data
->nesting
!= NULL
)) {
1375 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR
);
1377 return NT_STATUS_OK
;
1382 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1383 ldap packet. Set packet_size if true.
1385 NTSTATUS
ldap_full_packet(void *private_data
, DATA_BLOB blob
, size_t *packet_size
)
1387 return asn1_full_tag(blob
, ASN1_SEQUENCE(0), packet_size
);