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 "system/iconv.h"
29 #include "libcli/ldap/ldap.h"
32 static BOOL
ldap_push_filter(struct asn1_data
*data
, struct ldb_parse_tree
*tree
)
34 switch (tree
->operation
) {
36 if ((tree
->u
.simple
.value
.length
== 1) &&
37 (((char *)(tree
->u
.simple
.value
.data
))[0] == '*')) {
38 /* Just a presence test */
39 asn1_push_tag(data
, 0x87);
40 asn1_write(data
, tree
->u
.simple
.attr
,
41 strlen(tree
->u
.simple
.attr
));
43 return !data
->has_error
;
46 /* Equality is all we currently do... */
47 asn1_push_tag(data
, 0xa3);
48 asn1_write_OctetString(data
, tree
->u
.simple
.attr
,
49 strlen(tree
->u
.simple
.attr
));
50 asn1_write_OctetString(data
, tree
->u
.simple
.value
.data
,
51 tree
->u
.simple
.value
.length
);
59 asn1_push_tag(data
, 0xa0);
60 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
61 ldap_push_filter(data
, tree
->u
.list
.elements
[i
]);
70 asn1_push_tag(data
, 0xa1);
71 for (i
=0; i
<tree
->u
.list
.num_elements
; i
++) {
72 ldap_push_filter(data
, tree
->u
.list
.elements
[i
]);
80 return !data
->has_error
;
83 static void ldap_encode_response(struct asn1_data
*data
, struct ldap_Result
*result
)
85 asn1_write_enumerated(data
, result
->resultcode
);
86 asn1_write_OctetString(data
, result
->dn
,
87 (result
->dn
) ? strlen(result
->dn
) : 0);
88 asn1_write_OctetString(data
, result
->errormessage
,
89 (result
->errormessage
) ?
90 strlen(result
->errormessage
) : 0);
91 if (result
->referral
) {
92 asn1_push_tag(data
, ASN1_CONTEXT(3));
93 asn1_write_OctetString(data
, result
->referral
,
94 strlen(result
->referral
));
99 BOOL
ldap_encode(struct ldap_message
*msg
, DATA_BLOB
*result
)
101 struct asn1_data data
;
105 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
106 asn1_write_Integer(&data
, msg
->messageid
);
109 case LDAP_TAG_BindRequest
: {
110 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
111 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
112 asn1_write_Integer(&data
, r
->version
);
113 asn1_write_OctetString(&data
, r
->dn
,
114 (r
->dn
!= NULL
) ? strlen(r
->dn
) : 0);
116 switch (r
->mechanism
) {
117 case LDAP_AUTH_MECH_SIMPLE
:
118 /* context, primitive */
119 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
120 asn1_write(&data
, r
->creds
.password
,
121 strlen(r
->creds
.password
));
124 case LDAP_AUTH_MECH_SASL
:
125 /* context, constructed */
126 asn1_push_tag(&data
, ASN1_CONTEXT(3));
127 asn1_write_OctetString(&data
, r
->creds
.SASL
.mechanism
,
128 strlen(r
->creds
.SASL
.mechanism
));
129 asn1_write_OctetString(&data
, r
->creds
.SASL
.secblob
.data
,
130 r
->creds
.SASL
.secblob
.length
);
141 case LDAP_TAG_BindResponse
: {
142 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
143 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
144 ldap_encode_response(&data
, &r
->response
);
145 asn1_write_ContextSimple(&data
, 7, &r
->SASL
.secblob
);
149 case LDAP_TAG_UnbindRequest
: {
150 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
153 case LDAP_TAG_SearchRequest
: {
154 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
155 struct ldb_parse_tree
*tree
;
156 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
157 asn1_write_OctetString(&data
, r
->basedn
, strlen(r
->basedn
));
158 asn1_write_enumerated(&data
, r
->scope
);
159 asn1_write_enumerated(&data
, r
->deref
);
160 asn1_write_Integer(&data
, r
->sizelimit
);
161 asn1_write_Integer(&data
, r
->timelimit
);
162 asn1_write_BOOLEAN(&data
, r
->attributesonly
);
164 tree
= ldb_parse_tree(NULL
, r
->filter
);
169 ldap_push_filter(&data
, tree
);
173 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
174 for (i
=0; i
<r
->num_attributes
; i
++) {
175 asn1_write_OctetString(&data
, r
->attributes
[i
],
176 strlen(r
->attributes
[i
]));
183 case LDAP_TAG_SearchResultEntry
: {
184 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
185 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
186 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
187 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
188 for (i
=0; i
<r
->num_attributes
; i
++) {
189 struct ldap_attribute
*attr
= &r
->attributes
[i
];
190 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
191 asn1_write_OctetString(&data
, attr
->name
,
193 asn1_push_tag(&data
, ASN1_SEQUENCE(1));
194 for (j
=0; j
<attr
->num_values
; j
++) {
195 asn1_write_OctetString(&data
,
196 attr
->values
[j
].data
,
197 attr
->values
[j
].length
);
206 case LDAP_TAG_SearchResultDone
: {
207 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
208 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
209 ldap_encode_response(&data
, r
);
213 case LDAP_TAG_ModifyRequest
: {
214 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
215 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
216 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
217 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
219 for (i
=0; i
<r
->num_mods
; i
++) {
220 struct ldap_attribute
*attrib
= &r
->mods
[i
].attrib
;
221 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
222 asn1_write_enumerated(&data
, r
->mods
[i
].type
);
223 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
224 asn1_write_OctetString(&data
, attrib
->name
,
225 strlen(attrib
->name
));
226 asn1_push_tag(&data
, ASN1_SET
);
227 for (j
=0; j
<attrib
->num_values
; j
++) {
228 asn1_write_OctetString(&data
,
229 attrib
->values
[j
].data
,
230 attrib
->values
[j
].length
);
242 case LDAP_TAG_ModifyResponse
: {
243 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
244 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
245 ldap_encode_response(&data
, r
);
249 case LDAP_TAG_AddRequest
: {
250 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
251 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
252 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
253 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
255 for (i
=0; i
<r
->num_attributes
; i
++) {
256 struct ldap_attribute
*attrib
= &r
->attributes
[i
];
257 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
258 asn1_write_OctetString(&data
, attrib
->name
,
259 strlen(attrib
->name
));
260 asn1_push_tag(&data
, ASN1_SET
);
261 for (j
=0; j
<r
->attributes
[i
].num_values
; j
++) {
262 asn1_write_OctetString(&data
,
263 attrib
->values
[j
].data
,
264 attrib
->values
[j
].length
);
273 case LDAP_TAG_AddResponse
: {
274 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
275 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
276 ldap_encode_response(&data
, r
);
280 case LDAP_TAG_DelRequest
: {
281 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
282 asn1_push_tag(&data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
283 asn1_write(&data
, r
->dn
, strlen(r
->dn
));
287 case LDAP_TAG_DelResponse
: {
288 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
289 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
290 ldap_encode_response(&data
, r
);
294 case LDAP_TAG_ModifyDNRequest
: {
295 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
296 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
297 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
298 asn1_write_OctetString(&data
, r
->newrdn
, strlen(r
->newrdn
));
299 asn1_write_BOOLEAN(&data
, r
->deleteolddn
);
300 if (r
->newsuperior
!= NULL
) {
301 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
302 asn1_write(&data
, r
->newsuperior
,
303 strlen(r
->newsuperior
));
309 case LDAP_TAG_ModifyDNResponse
: {
310 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
311 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
312 ldap_encode_response(&data
, r
);
316 case LDAP_TAG_CompareRequest
: {
317 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
318 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
319 asn1_write_OctetString(&data
, r
->dn
, strlen(r
->dn
));
320 asn1_push_tag(&data
, ASN1_SEQUENCE(0));
321 asn1_write_OctetString(&data
, r
->attribute
,
322 strlen(r
->attribute
));
323 asn1_write_OctetString(&data
, r
->value
.data
,
329 case LDAP_TAG_CompareResponse
: {
330 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
331 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
332 ldap_encode_response(&data
, r
);
336 case LDAP_TAG_AbandonRequest
: {
337 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
338 asn1_push_tag(&data
, ASN1_APPLICATION_SIMPLE(msg
->type
));
339 asn1_write_implicit_Integer(&data
, r
->messageid
);
343 case LDAP_TAG_SearchResultReference
: {
344 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
345 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
346 asn1_write_OctetString(&data
, r
->referral
, strlen(r
->referral
));
350 case LDAP_TAG_ExtendedRequest
: {
351 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
352 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
353 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(0));
354 asn1_write(&data
, r
->oid
, strlen(r
->oid
));
356 asn1_push_tag(&data
, ASN1_CONTEXT_SIMPLE(1));
357 asn1_write(&data
, r
->value
.data
, r
->value
.length
);
362 case LDAP_TAG_ExtendedResponse
: {
363 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
364 asn1_push_tag(&data
, ASN1_APPLICATION(msg
->type
));
365 ldap_encode_response(&data
, &r
->response
);
374 *result
= data_blob(data
.data
, data
.length
);
379 static const char *blob2string_talloc(TALLOC_CTX
*mem_ctx
,
382 char *result
= talloc_size(mem_ctx
, blob
.length
+1);
383 memcpy(result
, blob
.data
, blob
.length
);
384 result
[blob
.length
] = '\0';
388 static BOOL
asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
389 struct asn1_data
*data
,
393 if (!asn1_read_OctetString(data
, &string
))
395 *result
= blob2string_talloc(mem_ctx
, string
);
396 data_blob_free(&string
);
400 static void ldap_decode_response(TALLOC_CTX
*mem_ctx
,
401 struct asn1_data
*data
,
402 struct ldap_Result
*result
)
404 asn1_read_enumerated(data
, &result
->resultcode
);
405 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->dn
);
406 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->errormessage
);
407 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
408 asn1_start_tag(data
, ASN1_CONTEXT(3));
409 asn1_read_OctetString_talloc(mem_ctx
, data
, &result
->referral
);
412 result
->referral
= NULL
;
416 static struct ldb_parse_tree
*ldap_decode_filter_tree(TALLOC_CTX
*mem_ctx
,
417 struct asn1_data
*data
)
419 uint8_t filter_tag
, tag_desc
;
420 struct ldb_parse_tree
*ret
;
422 if (!asn1_peek_uint8(data
, &filter_tag
)) {
426 tag_desc
= filter_tag
;
427 filter_tag
&= 0x1f; /* strip off the asn1 stuff */
430 ret
= talloc(mem_ctx
, struct ldb_parse_tree
);
431 if (ret
== NULL
) return NULL
;
436 /* AND or OR of one or more filters */
437 ret
->operation
= (filter_tag
== 0)?LDB_OP_AND
:LDB_OP_OR
;
438 ret
->u
.list
.num_elements
= 0;
439 ret
->u
.list
.elements
= NULL
;
441 if (tag_desc
!= 0xa0) {
442 /* context compount */
446 if (!asn1_start_tag(data
, ASN1_CONTEXT(filter_tag
))) {
450 while (asn1_tag_remaining(data
) > 0) {
451 struct ldb_parse_tree
*subtree
;
452 subtree
= ldap_decode_filter_tree(ret
, data
);
453 if (subtree
== NULL
) {
456 ret
->u
.list
.elements
=
457 talloc_realloc(ret
, ret
->u
.list
.elements
,
458 struct ldb_parse_tree
*,
459 ret
->u
.list
.num_elements
+1);
460 if (ret
->u
.list
.elements
== NULL
) {
463 talloc_steal(ret
->u
.list
.elements
, subtree
);
464 ret
->u
.list
.elements
[ret
->u
.list
.num_elements
] = subtree
;
465 ret
->u
.list
.num_elements
++;
467 if (!asn1_end_tag(data
)) {
477 ret
->operation
= LDB_OP_SIMPLE
;
479 if (tag_desc
!= 0xa0) {
480 /* context compound */
484 asn1_start_tag(data
, ASN1_CONTEXT(3));
485 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
);
486 asn1_read_OctetString(data
, &value
);
488 if ((data
->has_error
) || (attrib
== NULL
) || (value
.data
== NULL
)) {
491 ret
->u
.simple
.attr
= talloc_steal(ret
, attrib
);
492 ret
->u
.simple
.value
.data
= talloc_steal(ret
, value
.data
);
493 ret
->u
.simple
.value
.length
= value
.length
;
497 /* Normal presence, "attribute=*" */
499 if (tag_desc
!= 0x80) {
503 if (!asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
507 ret
->operation
= LDB_OP_SIMPLE
;
509 attr_len
= asn1_tag_remaining(data
);
511 ret
->u
.simple
.attr
= talloc_size(ret
, attr_len
+1);
512 if (ret
->u
.simple
.attr
== NULL
) {
515 if (!asn1_read(data
, ret
->u
.simple
.attr
, attr_len
)) {
518 ret
->u
.simple
.attr
[attr_len
] = 0;
519 ret
->u
.simple
.value
.data
= talloc_strdup(ret
, "*");
520 if (ret
->u
.simple
.value
.data
== NULL
) {
523 ret
->u
.simple
.value
.length
= 1;
524 if (!asn1_end_tag(data
)) {
530 DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag
));
538 DEBUG(0,("Failed to parse ASN.1 LDAP filter\n"));
543 static BOOL
ldap_decode_filter(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
544 const char **filterp
)
546 struct ldb_parse_tree
*tree
;
548 tree
= ldap_decode_filter_tree(mem_ctx
, data
);
552 *filterp
= ldb_filter_from_tree(mem_ctx
, tree
);
554 if (*filterp
== NULL
) {
562 static void ldap_decode_attrib(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
563 struct ldap_attribute
*attrib
)
565 asn1_start_tag(data
, ASN1_SEQUENCE(0));
566 asn1_read_OctetString_talloc(mem_ctx
, data
, &attrib
->name
);
567 asn1_start_tag(data
, ASN1_SET
);
568 while (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
570 struct ldb_val value
;
571 asn1_read_OctetString(data
, &blob
);
572 value
.data
= blob
.data
;
573 value
.length
= blob
.length
;
574 add_value_to_attrib(mem_ctx
, &value
, attrib
);
575 data_blob_free(&blob
);
582 static void ldap_decode_attribs(TALLOC_CTX
*mem_ctx
, struct asn1_data
*data
,
583 struct ldap_attribute
**attributes
,
586 asn1_start_tag(data
, ASN1_SEQUENCE(0));
587 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
588 struct ldap_attribute attrib
;
590 ldap_decode_attrib(mem_ctx
, data
, &attrib
);
591 add_attrib_to_array_talloc(mem_ctx
, &attrib
,
592 attributes
, num_attributes
);
597 BOOL
ldap_decode(struct asn1_data
*data
, struct ldap_message
*msg
)
601 asn1_start_tag(data
, ASN1_SEQUENCE(0));
602 asn1_read_Integer(data
, &msg
->messageid
);
604 if (!asn1_peek_uint8(data
, &tag
))
609 case ASN1_APPLICATION(LDAP_TAG_BindRequest
): {
610 struct ldap_BindRequest
*r
= &msg
->r
.BindRequest
;
611 msg
->type
= LDAP_TAG_BindRequest
;
612 asn1_start_tag(data
, tag
);
613 asn1_read_Integer(data
, &r
->version
);
614 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
615 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(0))) {
617 r
->creds
.password
= "";
618 r
->mechanism
= LDAP_AUTH_MECH_SIMPLE
;
619 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
620 pwlen
= asn1_tag_remaining(data
);
622 char *pw
= talloc_size(msg
->mem_ctx
, pwlen
+1);
623 asn1_read(data
, pw
, pwlen
);
625 r
->creds
.password
= pw
;
628 } else if (asn1_peek_tag(data
, ASN1_CONTEXT(3))){
629 asn1_start_tag(data
, ASN1_CONTEXT(3));
630 r
->mechanism
= LDAP_AUTH_MECH_SASL
;
631 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->creds
.SASL
.mechanism
);
632 asn1_read_OctetString(data
, &r
->creds
.SASL
.secblob
);
633 if (r
->creds
.SASL
.secblob
.data
) {
634 talloc_steal(msg
->mem_ctx
, r
->creds
.SASL
.secblob
.data
);
642 case ASN1_APPLICATION(LDAP_TAG_BindResponse
): {
643 struct ldap_BindResponse
*r
= &msg
->r
.BindResponse
;
644 msg
->type
= LDAP_TAG_BindResponse
;
645 asn1_start_tag(data
, tag
);
646 ldap_decode_response(msg
->mem_ctx
, data
, &r
->response
);
647 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(7))) {
648 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
649 asn1_read_ContextSimple(data
, 7, &tmp_blob
);
650 r
->SASL
.secblob
= data_blob_talloc(msg
->mem_ctx
, tmp_blob
.data
, tmp_blob
.length
);
651 data_blob_free(&tmp_blob
);
653 r
->SASL
.secblob
= data_blob(NULL
, 0);
659 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest
): {
660 msg
->type
= LDAP_TAG_UnbindRequest
;
661 asn1_start_tag(data
, tag
);
666 case ASN1_APPLICATION(LDAP_TAG_SearchRequest
): {
667 struct ldap_SearchRequest
*r
= &msg
->r
.SearchRequest
;
668 msg
->type
= LDAP_TAG_SearchRequest
;
669 asn1_start_tag(data
, tag
);
670 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->basedn
);
671 asn1_read_enumerated(data
, (int *)&(r
->scope
));
672 asn1_read_enumerated(data
, (int *)&(r
->deref
));
673 asn1_read_Integer(data
, &r
->sizelimit
);
674 asn1_read_Integer(data
, &r
->timelimit
);
675 asn1_read_BOOLEAN(data
, &r
->attributesonly
);
677 /* Maybe create a TALLOC_CTX for the filter? This can waste
678 * quite a bit of memory recursing down. */
679 ldap_decode_filter(msg
->mem_ctx
, data
, &r
->filter
);
681 asn1_start_tag(data
, ASN1_SEQUENCE(0));
683 r
->num_attributes
= 0;
684 r
->attributes
= NULL
;
686 while (asn1_tag_remaining(data
) > 0) {
688 if (!asn1_read_OctetString_talloc(msg
->mem_ctx
, data
,
691 if (!add_string_to_array(msg
->mem_ctx
, attr
,
702 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry
): {
703 struct ldap_SearchResEntry
*r
= &msg
->r
.SearchResultEntry
;
704 msg
->type
= LDAP_TAG_SearchResultEntry
;
705 r
->attributes
= NULL
;
706 r
->num_attributes
= 0;
707 asn1_start_tag(data
, tag
);
708 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
709 ldap_decode_attribs(msg
->mem_ctx
, data
, &r
->attributes
,
715 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone
): {
716 struct ldap_Result
*r
= &msg
->r
.SearchResultDone
;
717 msg
->type
= LDAP_TAG_SearchResultDone
;
718 asn1_start_tag(data
, tag
);
719 ldap_decode_response(msg
->mem_ctx
, data
, r
);
724 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference
): {
725 struct ldap_SearchResRef
*r
= &msg
->r
.SearchResultReference
;
726 msg
->type
= LDAP_TAG_SearchResultReference
;
727 asn1_start_tag(data
, tag
);
728 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->referral
);
733 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest
): {
734 struct ldap_ModifyRequest
*r
= &msg
->r
.ModifyRequest
;
735 msg
->type
= LDAP_TAG_ModifyRequest
;
736 asn1_start_tag(data
, ASN1_APPLICATION(LDAP_TAG_ModifyRequest
));
737 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
738 asn1_start_tag(data
, ASN1_SEQUENCE(0));
743 while (asn1_tag_remaining(data
) > 0) {
747 asn1_start_tag(data
, ASN1_SEQUENCE(0));
748 asn1_read_enumerated(data
, &v
);
750 ldap_decode_attrib(msg
->mem_ctx
, data
, &mod
.attrib
);
752 if (!add_mod_to_array_talloc(msg
->mem_ctx
, &mod
,
753 &r
->mods
, &r
->num_mods
))
762 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse
): {
763 struct ldap_Result
*r
= &msg
->r
.ModifyResponse
;
764 msg
->type
= LDAP_TAG_ModifyResponse
;
765 asn1_start_tag(data
, tag
);
766 ldap_decode_response(msg
->mem_ctx
, data
, r
);
771 case ASN1_APPLICATION(LDAP_TAG_AddRequest
): {
772 struct ldap_AddRequest
*r
= &msg
->r
.AddRequest
;
773 msg
->type
= LDAP_TAG_AddRequest
;
774 asn1_start_tag(data
, tag
);
775 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
777 r
->attributes
= NULL
;
778 r
->num_attributes
= 0;
779 ldap_decode_attribs(msg
->mem_ctx
, data
, &r
->attributes
,
786 case ASN1_APPLICATION(LDAP_TAG_AddResponse
): {
787 struct ldap_Result
*r
= &msg
->r
.AddResponse
;
788 msg
->type
= LDAP_TAG_AddResponse
;
789 asn1_start_tag(data
, tag
);
790 ldap_decode_response(msg
->mem_ctx
, data
, r
);
795 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
): {
796 struct ldap_DelRequest
*r
= &msg
->r
.DelRequest
;
799 msg
->type
= LDAP_TAG_DelRequest
;
801 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest
));
802 len
= asn1_tag_remaining(data
);
803 dn
= talloc_size(msg
->mem_ctx
, len
+1);
806 asn1_read(data
, dn
, len
);
813 case ASN1_APPLICATION(LDAP_TAG_DelResponse
): {
814 struct ldap_Result
*r
= &msg
->r
.DelResponse
;
815 msg
->type
= LDAP_TAG_DelResponse
;
816 asn1_start_tag(data
, tag
);
817 ldap_decode_response(msg
->mem_ctx
, data
, r
);
822 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
): {
823 struct ldap_ModifyDNRequest
*r
= &msg
->r
.ModifyDNRequest
;
824 msg
->type
= LDAP_TAG_ModifyDNRequest
;
826 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest
));
827 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
828 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->newrdn
);
829 asn1_read_BOOLEAN(data
, &r
->deleteolddn
);
830 r
->newsuperior
= NULL
;
831 if (asn1_tag_remaining(data
) > 0) {
834 asn1_start_tag(data
, ASN1_CONTEXT_SIMPLE(0));
835 len
= asn1_tag_remaining(data
);
836 newsup
= talloc_size(msg
->mem_ctx
, len
+1);
839 asn1_read(data
, newsup
, len
);
841 r
->newsuperior
= newsup
;
848 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse
): {
849 struct ldap_Result
*r
= &msg
->r
.ModifyDNResponse
;
850 msg
->type
= LDAP_TAG_ModifyDNResponse
;
851 asn1_start_tag(data
, tag
);
852 ldap_decode_response(msg
->mem_ctx
, data
, r
);
857 case ASN1_APPLICATION(LDAP_TAG_CompareRequest
): {
858 struct ldap_CompareRequest
*r
= &msg
->r
.CompareRequest
;
859 msg
->type
= LDAP_TAG_CompareRequest
;
861 ASN1_APPLICATION(LDAP_TAG_CompareRequest
));
862 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->dn
);
863 asn1_start_tag(data
, ASN1_SEQUENCE(0));
864 asn1_read_OctetString_talloc(msg
->mem_ctx
, data
, &r
->attribute
);
865 asn1_read_OctetString(data
, &r
->value
);
867 talloc_steal(msg
->mem_ctx
, r
->value
.data
);
874 case ASN1_APPLICATION(LDAP_TAG_CompareResponse
): {
875 struct ldap_Result
*r
= &msg
->r
.CompareResponse
;
876 msg
->type
= LDAP_TAG_CompareResponse
;
877 asn1_start_tag(data
, tag
);
878 ldap_decode_response(msg
->mem_ctx
, data
, r
);
883 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest
): {
884 struct ldap_AbandonRequest
*r
= &msg
->r
.AbandonRequest
;
885 msg
->type
= LDAP_TAG_AbandonRequest
;
886 asn1_start_tag(data
, tag
);
887 asn1_read_implicit_Integer(data
, &r
->messageid
);
892 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest
): {
893 struct ldap_ExtendedRequest
*r
= &msg
->r
.ExtendedRequest
;
894 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
896 msg
->type
= LDAP_TAG_ExtendedRequest
;
897 asn1_start_tag(data
,tag
);
898 if (!asn1_read_ContextSimple(data
, 0, &tmp_blob
)) {
901 r
->oid
= blob2string_talloc(msg
->mem_ctx
, tmp_blob
);
902 data_blob_free(&tmp_blob
);
907 if (asn1_peek_tag(data
, ASN1_CONTEXT_SIMPLE(1))) {
908 asn1_read_ContextSimple(data
, 1, &tmp_blob
);
909 r
->value
= data_blob_talloc(msg
->mem_ctx
, tmp_blob
.data
, tmp_blob
.length
);
910 data_blob_free(&tmp_blob
);
912 r
->value
= data_blob(NULL
, 0);
919 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse
): {
920 struct ldap_ExtendedResponse
*r
= &msg
->r
.ExtendedResponse
;
921 msg
->type
= LDAP_TAG_ExtendedResponse
;
922 asn1_start_tag(data
, tag
);
923 ldap_decode_response(msg
->mem_ctx
, data
, &r
->response
);
924 /* I have to come across an operation that actually sends
925 * something back to really see what's going on. The currently
926 * needed pwdchange does not send anything back. */
928 r
->value
.data
= NULL
;
937 msg
->num_controls
= 0;
938 msg
->controls
= NULL
;
940 if (asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
942 struct ldap_Control
*ctrl
= NULL
;
944 asn1_start_tag(data
, ASN1_CONTEXT(0));
946 for (i
=0; asn1_peek_tag(data
, ASN1_SEQUENCE(0)); i
++) {
947 asn1_start_tag(data
, ASN1_SEQUENCE(0));
949 ctrl
= talloc_realloc(msg
->mem_ctx
, ctrl
, struct ldap_Control
, i
+1);
954 ctrl
[i
].critical
= False
;
955 ctrl
[i
].value
= data_blob(NULL
, 0);
957 asn1_read_OctetString_talloc(ctrl
, data
, &ctrl
[i
].oid
);
959 if (asn1_peek_tag(data
, ASN1_BOOLEAN
)) {
960 asn1_read_BOOLEAN(data
, &ctrl
[i
].critical
);
963 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
)) {
964 asn1_read_OctetString(data
, &ctrl
[i
].value
);
965 if (ctrl
[i
].value
.data
) {
966 talloc_steal(msg
->mem_ctx
, ctrl
[i
].value
.data
);
972 msg
->num_controls
= i
;
973 msg
->controls
= ctrl
;
979 return ((!data
->has_error
) && (data
->nesting
== NULL
));
982 BOOL
ldap_parse_basic_url(TALLOC_CTX
*mem_ctx
, const char *url
,
983 char **host
, uint16_t *port
, BOOL
*ldaps
)
991 /* skip leading "URL:" (if any) */
992 if (strncasecmp( p
, "URL:", 4) == 0) {
997 SMB_ASSERT(sizeof(protocol
)>10 && sizeof(tmp_host
)>254);
999 ret
= sscanf(p
, "%10[^:]://%254[^:/]:%d", protocol
, tmp_host
, &tmp_port
);
1004 if (strequal(protocol
, "ldap")) {
1007 } else if (strequal(protocol
, "ldaps")) {
1011 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol
));
1018 *host
= talloc_strdup(mem_ctx
, tmp_host
);
1020 return (*host
!= NULL
);