libsmb: Use reparse_data_buffer_marshall() in py_reparse_symlink_put()
[Samba.git] / libcli / ldap / ldap_message.c
blob3099086b05bfb5727449e6c643ad0ba0541eb69e
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/util/asn1.h"
27 #include "../libcli/ldap/ldap_message.h"
29 _PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
31 return talloc_zero(mem_ctx, struct ldap_message);
35 static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36 struct ldb_message_element *attrib)
38 attrib->values = talloc_realloc(mem_ctx,
39 attrib->values,
40 DATA_BLOB,
41 attrib->num_values+1);
42 if (attrib->values == NULL)
43 return false;
45 attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
46 value->data);
47 attrib->values[attrib->num_values].length = value->length;
48 attrib->num_values += 1;
49 return true;
52 static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
53 const struct ldb_message_element *attrib,
54 struct ldb_message_element **attribs,
55 int *num_attribs)
57 *attribs = talloc_realloc(mem_ctx,
58 *attribs,
59 struct ldb_message_element,
60 *num_attribs+1);
62 if (*attribs == NULL)
63 return false;
65 (*attribs)[*num_attribs] = *attrib;
66 talloc_steal(*attribs, attrib->values);
67 talloc_steal(*attribs, attrib->name);
68 *num_attribs += 1;
69 return true;
72 static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
73 struct ldap_mod *mod,
74 struct ldap_mod **mods,
75 int *num_mods)
77 *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
79 if (*mods == NULL)
80 return false;
82 (*mods)[*num_mods] = *mod;
83 *num_mods += 1;
84 return true;
87 static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
88 const struct ldap_control_handler *handlers,
89 struct ldb_control *ctrl)
91 int i;
93 if (!handlers) {
94 return true;
97 for (i = 0; handlers[i].oid != NULL; i++) {
98 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
99 if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
100 return false;
102 break;
105 if (handlers[i].oid == NULL) {
106 return false;
109 return true;
112 static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113 struct ldb_control *ctrl, DATA_BLOB *value)
115 DATA_BLOB oid;
117 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
118 return false;
121 if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
122 return false;
124 ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
125 if (!ctrl->oid) {
126 return false;
129 if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
130 bool critical;
131 if (!asn1_read_BOOLEAN(data, &critical)) {
132 return false;
134 ctrl->critical = critical;
135 } else {
136 ctrl->critical = false;
139 ctrl->data = NULL;
141 if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142 *value = data_blob(NULL, 0);
143 goto end_tag;
146 if (!asn1_read_OctetString(data, mem_ctx, value)) {
147 return false;
150 end_tag:
151 if (!asn1_end_tag(data)) {
152 return false;
155 return true;
158 static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
159 const struct ldap_control_handler *handlers,
160 struct ldb_control *ctrl)
162 DATA_BLOB value;
163 int i;
165 if (!handlers) {
166 return false;
169 for (i = 0; handlers[i].oid != NULL; i++) {
170 if (!ctrl->oid) {
171 /* not encoding this control, the OID has been
172 * set to NULL indicating it isn't really
173 * here */
174 return true;
176 if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
177 if (!handlers[i].encode) {
178 if (ctrl->critical) {
179 return false;
180 } else {
181 /* not encoding this control */
182 return true;
185 if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
186 return false;
188 break;
191 if (handlers[i].oid == NULL) {
192 return false;
195 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
196 return false;
199 if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
200 return false;
203 if (ctrl->critical) {
204 if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
205 return false;
209 if (!ctrl->data) {
210 goto pop_tag;
213 if (!asn1_write_OctetString(data, value.data, value.length)) {
214 return false;
217 pop_tag:
218 if (!asn1_pop_tag(data)) {
219 return false;
222 return true;
225 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
227 int i;
229 switch (tree->operation) {
230 case LDB_OP_AND:
231 case LDB_OP_OR:
232 if (!asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1))) return false;
233 for (i=0; i<tree->u.list.num_elements; i++) {
234 if (!ldap_push_filter(data, tree->u.list.elements[i])) {
235 return false;
238 if (!asn1_pop_tag(data)) return false;
239 break;
241 case LDB_OP_NOT:
242 if (!asn1_push_tag(data, ASN1_CONTEXT(2))) return false;
243 if (!ldap_push_filter(data, tree->u.isnot.child)) {
244 return false;
246 if (!asn1_pop_tag(data)) return false;
247 break;
249 case LDB_OP_EQUALITY:
250 /* equality test */
251 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
252 if (!asn1_write_OctetString(data, tree->u.equality.attr,
253 strlen(tree->u.equality.attr))) return false;
254 if (!asn1_write_OctetString(data, tree->u.equality.value.data,
255 tree->u.equality.value.length)) return false;
256 if (!asn1_pop_tag(data)) return false;
257 break;
259 case LDB_OP_SUBSTRING:
261 SubstringFilter ::= SEQUENCE {
262 type AttributeDescription,
263 -- at least one must be present
264 substrings SEQUENCE OF CHOICE {
265 initial [0] LDAPString,
266 any [1] LDAPString,
267 final [2] LDAPString } }
269 if (!asn1_push_tag(data, ASN1_CONTEXT(4))) return false;
270 if (!asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr))) return false;
271 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
273 if (tree->u.substring.chunks && tree->u.substring.chunks[0]) {
274 i = 0;
275 if (!tree->u.substring.start_with_wildcard) {
276 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) return false;
277 if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
278 if (!asn1_pop_tag(data)) return false;
279 i++;
281 while (tree->u.substring.chunks[i]) {
282 int ctx;
284 if (( ! tree->u.substring.chunks[i + 1]) &&
285 (tree->u.substring.end_with_wildcard == 0)) {
286 ctx = 2;
287 } else {
288 ctx = 1;
290 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx))) return false;
291 if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
292 if (!asn1_pop_tag(data)) return false;
293 i++;
296 if (!asn1_pop_tag(data)) return false;
297 if (!asn1_pop_tag(data)) return false;
298 break;
300 case LDB_OP_GREATER:
301 /* greaterOrEqual test */
302 if (!asn1_push_tag(data, ASN1_CONTEXT(5))) return false;
303 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
304 strlen(tree->u.comparison.attr))) return false;
305 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
306 tree->u.comparison.value.length)) return false;
307 if (!asn1_pop_tag(data)) return false;
308 break;
310 case LDB_OP_LESS:
311 /* lessOrEqual test */
312 if (!asn1_push_tag(data, ASN1_CONTEXT(6))) return false;
313 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
314 strlen(tree->u.comparison.attr))) return false;
315 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
316 tree->u.comparison.value.length)) return false;
317 if (!asn1_pop_tag(data)) return false;
318 break;
320 case LDB_OP_PRESENT:
321 /* present test */
322 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false;
323 if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false;
324 if (!asn1_pop_tag(data)) return false;
325 return !asn1_has_error(data);
327 case LDB_OP_APPROX:
328 /* approx test */
329 if (!asn1_push_tag(data, ASN1_CONTEXT(8))) return false;
330 if (!asn1_write_OctetString(data, tree->u.comparison.attr,
331 strlen(tree->u.comparison.attr))) return false;
332 if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
333 tree->u.comparison.value.length)) return false;
334 if (!asn1_pop_tag(data)) return false;
335 break;
337 case LDB_OP_EXTENDED:
339 MatchingRuleAssertion ::= SEQUENCE {
340 matchingRule [1] MatchingRuleID OPTIONAL,
341 type [2] AttributeDescription OPTIONAL,
342 matchValue [3] AssertionValue,
343 dnAttributes [4] BOOLEAN DEFAULT FALSE
346 if (!asn1_push_tag(data, ASN1_CONTEXT(9))) return false;
347 if (tree->u.extended.rule_id) {
348 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
349 if (!asn1_write_LDAPString(data, tree->u.extended.rule_id)) return false;
350 if (!asn1_pop_tag(data)) return false;
352 if (tree->u.extended.attr) {
353 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
354 if (!asn1_write_LDAPString(data, tree->u.extended.attr)) return false;
355 if (!asn1_pop_tag(data)) return false;
357 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
358 if (!asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value)) return false;
359 if (!asn1_pop_tag(data)) return false;
360 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
361 if (!asn1_write_uint8(data, tree->u.extended.dnAttributes)) return false;
362 if (!asn1_pop_tag(data)) return false;
363 if (!asn1_pop_tag(data)) return false;
364 break;
366 default:
367 return false;
369 return !asn1_has_error(data);
372 static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
374 if (!asn1_write_enumerated(data, result->resultcode)) return false;
375 if (!asn1_write_OctetString(data, result->dn,
376 (result->dn) ? strlen(result->dn) : 0)) return false;
377 if (!asn1_write_OctetString(data, result->errormessage,
378 (result->errormessage) ?
379 strlen(result->errormessage) : 0)) return false;
380 if (result->referral) {
381 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
382 if (!asn1_write_OctetString(data, result->referral,
383 strlen(result->referral))) return false;
384 if (!asn1_pop_tag(data)) return false;
386 return true;
389 _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
390 const struct ldap_control_handler *control_handlers,
391 DATA_BLOB *result, TALLOC_CTX *mem_ctx)
393 struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
394 int i, j;
396 if (!data) return false;
398 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
399 if (!asn1_write_Integer(data, msg->messageid)) goto err;
401 switch (msg->type) {
402 case LDAP_TAG_BindRequest: {
403 struct ldap_BindRequest *r = &msg->r.BindRequest;
404 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
405 if (!asn1_write_Integer(data, r->version)) goto err;
406 if (!asn1_write_OctetString(data, r->dn,
407 (r->dn != NULL) ? strlen(r->dn) : 0)) goto err;
409 switch (r->mechanism) {
410 case LDAP_AUTH_MECH_SIMPLE:
411 /* context, primitive */
412 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
413 if (!asn1_write(data, r->creds.password,
414 strlen(r->creds.password))) goto err;
415 if (!asn1_pop_tag(data)) goto err;
416 break;
417 case LDAP_AUTH_MECH_SASL:
418 /* context, constructed */
419 if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
420 if (!asn1_write_OctetString(data, r->creds.SASL.mechanism,
421 strlen(r->creds.SASL.mechanism))) goto err;
422 if (r->creds.SASL.secblob) {
423 if (!asn1_write_OctetString(data, r->creds.SASL.secblob->data,
424 r->creds.SASL.secblob->length)) goto err;
426 if (!asn1_pop_tag(data)) goto err;
427 break;
428 default:
429 goto err;
432 if (!asn1_pop_tag(data)) goto err;
433 break;
435 case LDAP_TAG_BindResponse: {
436 struct ldap_BindResponse *r = &msg->r.BindResponse;
437 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
438 if (!ldap_encode_response(data, &r->response)) goto err;
439 if (r->SASL.secblob) {
440 if (!asn1_write_ContextSimple(data, 7, r->SASL.secblob)) goto err;
442 if (!asn1_pop_tag(data)) goto err;
443 break;
445 case LDAP_TAG_UnbindRequest: {
446 /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
447 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
448 if (!asn1_pop_tag(data)) goto err;
449 break;
451 case LDAP_TAG_SearchRequest: {
452 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
453 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
454 if (!asn1_write_OctetString(data, r->basedn, strlen(r->basedn))) goto err;
455 if (!asn1_write_enumerated(data, r->scope)) goto err;
456 if (!asn1_write_enumerated(data, r->deref)) goto err;
457 if (!asn1_write_Integer(data, r->sizelimit)) goto err;
458 if (!asn1_write_Integer(data, r->timelimit)) goto err;
459 if (!asn1_write_BOOLEAN(data, r->attributesonly)) goto err;
461 if (!ldap_push_filter(data, r->tree)) {
462 goto err;
465 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
466 for (i=0; i<r->num_attributes; i++) {
467 if (!asn1_write_OctetString(data, r->attributes[i],
468 strlen(r->attributes[i]))) goto err;
470 if (!asn1_pop_tag(data)) goto err;
471 if (!asn1_pop_tag(data)) goto err;
472 break;
474 case LDAP_TAG_SearchResultEntry: {
475 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
476 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
477 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
478 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
479 for (i=0; i<r->num_attributes; i++) {
480 struct ldb_message_element *attr = &r->attributes[i];
481 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
482 if (!asn1_write_OctetString(data, attr->name,
483 strlen(attr->name))) goto err;
484 if (!asn1_push_tag(data, ASN1_SEQUENCE(1))) goto err;
485 for (j=0; j<attr->num_values; j++) {
486 if (!asn1_write_OctetString(data,
487 attr->values[j].data,
488 attr->values[j].length)) goto err;
490 if (!asn1_pop_tag(data)) goto err;
491 if (!asn1_pop_tag(data)) goto err;
493 if (!asn1_pop_tag(data)) goto err;
494 if (!asn1_pop_tag(data)) goto err;
495 break;
497 case LDAP_TAG_SearchResultDone: {
498 struct ldap_Result *r = &msg->r.SearchResultDone;
499 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
500 if (!ldap_encode_response(data, r)) goto err;
501 if (!asn1_pop_tag(data)) goto err;
502 break;
504 case LDAP_TAG_ModifyRequest: {
505 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
506 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
507 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
508 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
510 for (i=0; i<r->num_mods; i++) {
511 struct ldb_message_element *attrib = &r->mods[i].attrib;
512 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
513 if (!asn1_write_enumerated(data, r->mods[i].type)) goto err;
514 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
515 if (!asn1_write_OctetString(data, attrib->name,
516 strlen(attrib->name))) goto err;
517 if (!asn1_push_tag(data, ASN1_SET)) goto err;
518 for (j=0; j<attrib->num_values; j++) {
519 if (!asn1_write_OctetString(data,
520 attrib->values[j].data,
521 attrib->values[j].length)) goto err;
524 if (!asn1_pop_tag(data)) goto err;
525 if (!asn1_pop_tag(data)) goto err;
526 if (!asn1_pop_tag(data)) goto err;
529 if (!asn1_pop_tag(data)) goto err;
530 if (!asn1_pop_tag(data)) goto err;
531 break;
533 case LDAP_TAG_ModifyResponse: {
534 struct ldap_Result *r = &msg->r.ModifyResponse;
535 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
536 if (!ldap_encode_response(data, r)) goto err;
537 if (!asn1_pop_tag(data)) goto err;
538 break;
540 case LDAP_TAG_AddRequest: {
541 struct ldap_AddRequest *r = &msg->r.AddRequest;
542 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
543 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
544 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
546 for (i=0; i<r->num_attributes; i++) {
547 struct ldb_message_element *attrib = &r->attributes[i];
548 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
549 if (attrib->name == NULL) {
550 goto err;
552 if (!asn1_write_OctetString(data, attrib->name,
553 strlen(attrib->name))) goto err;
554 if (!asn1_push_tag(data, ASN1_SET)) goto err;
555 for (j=0; j<r->attributes[i].num_values; j++) {
556 if (!asn1_write_OctetString(data,
557 attrib->values[j].data,
558 attrib->values[j].length)) goto err;
560 if (!asn1_pop_tag(data)) goto err;
561 if (!asn1_pop_tag(data)) goto err;
563 if (!asn1_pop_tag(data)) goto err;
564 if (!asn1_pop_tag(data)) goto err;
565 break;
567 case LDAP_TAG_AddResponse: {
568 struct ldap_Result *r = &msg->r.AddResponse;
569 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
570 if (!ldap_encode_response(data, r)) goto err;
571 if (!asn1_pop_tag(data)) goto err;
572 break;
574 case LDAP_TAG_DelRequest: {
575 struct ldap_DelRequest *r = &msg->r.DelRequest;
576 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
577 if (!asn1_write(data, r->dn, strlen(r->dn))) goto err;
578 if (!asn1_pop_tag(data)) goto err;
579 break;
581 case LDAP_TAG_DelResponse: {
582 struct ldap_Result *r = &msg->r.DelResponse;
583 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
584 if (!ldap_encode_response(data, r)) goto err;
585 if (!asn1_pop_tag(data)) goto err;
586 break;
588 case LDAP_TAG_ModifyDNRequest: {
589 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
590 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
591 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
592 if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err;
593 if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err;
594 if (r->newsuperior) {
595 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
596 if (!asn1_write(data, r->newsuperior,
597 strlen(r->newsuperior))) goto err;
598 if (!asn1_pop_tag(data)) goto err;
600 if (!asn1_pop_tag(data)) goto err;
601 break;
603 case LDAP_TAG_ModifyDNResponse: {
604 struct ldap_Result *r = &msg->r.ModifyDNResponse;
605 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
606 if (!ldap_encode_response(data, r)) goto err;
607 if (!asn1_pop_tag(data)) goto err;
608 break;
610 case LDAP_TAG_CompareRequest: {
611 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
612 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
613 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
614 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
615 if (!asn1_write_OctetString(data, r->attribute,
616 strlen(r->attribute))) goto err;
617 if (!asn1_write_OctetString(data, r->value.data,
618 r->value.length)) goto err;
619 if (!asn1_pop_tag(data)) goto err;
620 if (!asn1_pop_tag(data)) goto err;
621 break;
623 case LDAP_TAG_CompareResponse: {
624 struct ldap_Result *r = &msg->r.ModifyDNResponse;
625 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
626 if (!ldap_encode_response(data, r)) goto err;
627 if (!asn1_pop_tag(data)) goto err;
628 break;
630 case LDAP_TAG_AbandonRequest: {
631 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
632 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
633 if (!asn1_write_implicit_Integer(data, r->messageid)) goto err;
634 if (!asn1_pop_tag(data)) goto err;
635 break;
637 case LDAP_TAG_SearchResultReference: {
638 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
639 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
640 if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err;
641 if (!asn1_pop_tag(data)) goto err;
642 break;
644 case LDAP_TAG_ExtendedRequest: {
645 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
646 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
647 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
648 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
649 if (!asn1_pop_tag(data)) goto err;
650 if (r->value) {
651 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err;
652 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
653 if (!asn1_pop_tag(data)) goto err;
655 if (!asn1_pop_tag(data)) goto err;
656 break;
658 case LDAP_TAG_ExtendedResponse: {
659 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
660 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
661 if (!ldap_encode_response(data, &r->response)) goto err;
662 if (r->oid) {
663 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err;
664 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
665 if (!asn1_pop_tag(data)) goto err;
667 if (r->value) {
668 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err;
669 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
670 if (!asn1_pop_tag(data)) goto err;
672 if (!asn1_pop_tag(data)) goto err;
673 break;
675 default:
676 goto err;
679 if (msg->controls != NULL) {
680 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
682 for (i = 0; msg->controls[i] != NULL; i++) {
683 if (!ldap_encode_control(mem_ctx, data,
684 control_handlers,
685 msg->controls[i])) {
686 DEBUG(0,("Unable to encode control %s\n",
687 msg->controls[i]->oid));
688 goto err;
692 if (!asn1_pop_tag(data)) goto err;
695 if (!asn1_pop_tag(data)) goto err;
697 if (!asn1_extract_blob(data, mem_ctx, result)) {
698 goto err;
701 asn1_free(data);
703 return true;
705 err:
707 asn1_free(data);
708 return false;
711 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
712 DATA_BLOB blob)
714 char *result = talloc_array(mem_ctx, char, blob.length+1);
715 if (result == NULL) {
716 return NULL;
718 memcpy(result, blob.data, blob.length);
719 result[blob.length] = '\0';
720 return result;
723 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
724 struct asn1_data *data,
725 const char **result)
727 DATA_BLOB string;
728 if (!asn1_read_OctetString(data, mem_ctx, &string))
729 return false;
730 *result = blob2string_talloc(mem_ctx, string);
731 data_blob_free(&string);
732 return *result ? true : false;
735 static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
736 struct asn1_data *data,
737 struct ldap_Result *result)
739 if (!asn1_read_enumerated(data, &result->resultcode)) return false;
740 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
741 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
742 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
743 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
744 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
745 if (!asn1_end_tag(data)) return false;
746 } else {
747 result->referral = NULL;
749 return true;
752 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
755 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
756 if (chunks == NULL) {
757 return NULL;
760 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
761 if (chunks[chunk_num] == NULL) {
762 return NULL;
765 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
766 if (chunks[chunk_num]->data == NULL) {
767 return NULL;
769 chunks[chunk_num]->length = strlen(value);
771 chunks[chunk_num + 1] = NULL;
773 return chunks;
778 parse the ASN.1 formatted search string into a ldb_parse_tree
780 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
781 struct asn1_data *data)
783 uint8_t filter_tag;
784 struct ldb_parse_tree *ret;
786 if (!asn1_peek_uint8(data, &filter_tag)) {
787 return NULL;
790 filter_tag &= 0x1f; /* strip off the asn1 stuff */
792 ret = talloc(mem_ctx, struct ldb_parse_tree);
793 if (ret == NULL) return NULL;
795 switch(filter_tag) {
796 case 0:
797 case 1:
798 /* AND or OR of one or more filters */
799 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
800 ret->u.list.num_elements = 0;
801 ret->u.list.elements = NULL;
803 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
804 goto failed;
807 while (asn1_tag_remaining(data) > 0) {
808 struct ldb_parse_tree *subtree;
809 subtree = ldap_decode_filter_tree(ret, data);
810 if (subtree == NULL) {
811 goto failed;
813 ret->u.list.elements =
814 talloc_realloc(ret, ret->u.list.elements,
815 struct ldb_parse_tree *,
816 ret->u.list.num_elements+1);
817 if (ret->u.list.elements == NULL) {
818 goto failed;
820 talloc_steal(ret->u.list.elements, subtree);
821 ret->u.list.elements[ret->u.list.num_elements] = subtree;
822 ret->u.list.num_elements++;
824 if (!asn1_end_tag(data)) {
825 goto failed;
827 break;
829 case 2:
830 /* 'not' operation */
831 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
832 goto failed;
835 ret->operation = LDB_OP_NOT;
836 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
837 if (ret->u.isnot.child == NULL) {
838 goto failed;
840 if (!asn1_end_tag(data)) {
841 goto failed;
843 break;
845 case 3: {
846 /* equalityMatch */
847 const char *attrib;
848 DATA_BLOB value;
850 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
851 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
852 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
853 if (!asn1_end_tag(data)) goto failed;
854 if (asn1_has_error(data) || (attrib == NULL) ||
855 (value.data == NULL)) {
856 goto failed;
859 ret->operation = LDB_OP_EQUALITY;
860 ret->u.equality.attr = talloc_steal(ret, attrib);
861 ret->u.equality.value.data = talloc_steal(ret, value.data);
862 ret->u.equality.value.length = value.length;
863 break;
865 case 4: {
866 /* substrings */
867 DATA_BLOB attr;
868 uint8_t subs_tag;
869 char *value;
870 int chunk_num = 0;
872 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
873 goto failed;
875 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
876 goto failed;
879 ret->operation = LDB_OP_SUBSTRING;
880 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
881 if (ret->u.substring.attr == NULL) {
882 goto failed;
884 ret->u.substring.chunks = NULL;
885 ret->u.substring.start_with_wildcard = 1;
886 ret->u.substring.end_with_wildcard = 1;
888 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
889 goto failed;
892 while (asn1_tag_remaining(data) > 0) {
893 if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
894 subs_tag &= 0x1f; /* strip off the asn1 stuff */
895 if (subs_tag > 2) goto failed;
897 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
898 if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
899 if (!asn1_end_tag(data)) goto failed;
901 switch (subs_tag) {
902 case 0:
903 if (ret->u.substring.chunks != NULL) {
904 /* initial value found in the middle */
905 goto failed;
908 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
909 if (ret->u.substring.chunks == NULL) {
910 goto failed;
913 ret->u.substring.start_with_wildcard = 0;
914 chunk_num = 1;
915 break;
917 case 1:
918 if (ret->u.substring.end_with_wildcard == 0) {
919 /* "any" value found after a "final" value */
920 goto failed;
923 ret->u.substring.chunks = ldap_decode_substring(ret,
924 ret->u.substring.chunks,
925 chunk_num,
926 value);
927 if (ret->u.substring.chunks == NULL) {
928 goto failed;
931 chunk_num++;
932 break;
934 case 2:
935 ret->u.substring.chunks = ldap_decode_substring(ret,
936 ret->u.substring.chunks,
937 chunk_num,
938 value);
939 if (ret->u.substring.chunks == NULL) {
940 goto failed;
943 ret->u.substring.end_with_wildcard = 0;
944 break;
946 default:
947 goto failed;
952 if (!asn1_end_tag(data)) { /* SEQUENCE */
953 goto failed;
956 if (!asn1_end_tag(data)) {
957 goto failed;
959 break;
961 case 5: {
962 /* greaterOrEqual */
963 const char *attrib;
964 DATA_BLOB value;
966 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
967 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
968 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
969 if (!asn1_end_tag(data)) goto failed;
970 if (asn1_has_error(data) || (attrib == NULL) ||
971 (value.data == NULL)) {
972 goto failed;
975 ret->operation = LDB_OP_GREATER;
976 ret->u.comparison.attr = talloc_steal(ret, attrib);
977 ret->u.comparison.value.data = talloc_steal(ret, value.data);
978 ret->u.comparison.value.length = value.length;
979 break;
981 case 6: {
982 /* lessOrEqual */
983 const char *attrib;
984 DATA_BLOB value;
986 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
987 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
988 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
989 if (!asn1_end_tag(data)) goto failed;
990 if (asn1_has_error(data) || (attrib == NULL) ||
991 (value.data == NULL)) {
992 goto failed;
995 ret->operation = LDB_OP_LESS;
996 ret->u.comparison.attr = talloc_steal(ret, attrib);
997 ret->u.comparison.value.data = talloc_steal(ret, value.data);
998 ret->u.comparison.value.length = value.length;
999 break;
1001 case 7: {
1002 /* Normal presence, "attribute=*" */
1003 char *attr;
1005 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
1006 goto failed;
1008 if (!asn1_read_LDAPString(data, ret, &attr)) {
1009 goto failed;
1012 ret->operation = LDB_OP_PRESENT;
1013 ret->u.present.attr = talloc_steal(ret, attr);
1015 if (!asn1_end_tag(data)) {
1016 goto failed;
1018 break;
1020 case 8: {
1021 /* approx */
1022 const char *attrib;
1023 DATA_BLOB value;
1025 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
1026 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
1027 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
1028 if (!asn1_end_tag(data)) goto failed;
1029 if (asn1_has_error(data) || (attrib == NULL) ||
1030 (value.data == NULL)) {
1031 goto failed;
1034 ret->operation = LDB_OP_APPROX;
1035 ret->u.comparison.attr = talloc_steal(ret, attrib);
1036 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1037 ret->u.comparison.value.length = value.length;
1038 break;
1040 case 9: {
1041 char *oid = NULL, *attr = NULL, *value;
1042 uint8_t dnAttributes;
1043 /* an extended search */
1044 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1045 goto failed;
1048 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1049 we need to check we properly implement --SSS */
1050 /* either oid or type must be defined */
1051 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1052 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
1053 if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
1054 if (!asn1_end_tag(data)) goto failed;
1056 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1057 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
1058 if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
1059 if (!asn1_end_tag(data)) goto failed;
1061 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
1062 if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
1063 if (!asn1_end_tag(data)) goto failed;
1064 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1065 it is not marked as OPTIONAL but openldap tools
1066 do not set this unless it is to be set as TRUE
1067 NOTE: openldap tools do not work with AD as it
1068 seems that AD always requires the dnAttributes
1069 boolean value to be set */
1070 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1071 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
1072 if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
1073 if (!asn1_end_tag(data)) goto failed;
1074 } else {
1075 dnAttributes = 0;
1077 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1078 goto failed;
1081 if (oid) {
1082 ret->operation = LDB_OP_EXTENDED;
1084 /* From the RFC2251: If the type field is
1085 absent and matchingRule is present, the matchValue is compared
1086 against all attributes in an entry which support that matchingRule
1088 if (attr) {
1089 ret->u.extended.attr = talloc_steal(ret, attr);
1090 } else {
1091 ret->u.extended.attr = talloc_strdup(ret, "*");
1092 if (ret->u.extended.attr == NULL) {
1093 goto failed;
1096 ret->u.extended.rule_id = talloc_steal(ret, oid);
1097 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1098 ret->u.extended.value.length = strlen(value);
1099 ret->u.extended.dnAttributes = dnAttributes;
1100 } else {
1101 ret->operation = LDB_OP_EQUALITY;
1102 ret->u.equality.attr = talloc_steal(ret, attr);
1103 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1104 ret->u.equality.value.length = strlen(value);
1106 if (!asn1_end_tag(data)) {
1107 goto failed;
1109 break;
1112 default:
1113 goto failed;
1116 return ret;
1118 failed:
1119 talloc_free(ret);
1120 return NULL;
1123 /* Decode a single LDAP attribute, possibly containing multiple values */
1124 static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1125 struct ldb_message_element *attrib)
1127 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1128 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
1129 if (!asn1_start_tag(data, ASN1_SET)) return false;
1130 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1131 DATA_BLOB blob;
1132 if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
1133 add_value_to_attrib(mem_ctx, &blob, attrib);
1135 if (!asn1_end_tag(data)) return false;
1136 return asn1_end_tag(data);
1139 /* Decode a set of LDAP attributes, as found in the dereference control */
1140 bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1141 struct ldb_message_element **attributes,
1142 int *num_attributes)
1144 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1145 struct ldb_message_element attrib;
1146 ZERO_STRUCT(attrib);
1147 if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
1148 add_attrib_to_array_talloc(mem_ctx, &attrib,
1149 attributes, num_attributes);
1151 return true;
1154 /* Decode a set of LDAP attributes, as found in a search entry */
1155 static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1156 struct ldb_message_element **attributes,
1157 int *num_attributes)
1159 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1160 if (!ldap_decode_attribs_bare(mem_ctx, data,
1161 attributes, num_attributes)) return false;
1162 return asn1_end_tag(data);
1165 /* This routine returns LDAP status codes */
1167 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1168 const struct ldap_request_limits *limits,
1169 const struct ldap_control_handler *control_handlers,
1170 struct ldap_message *msg)
1172 uint8_t tag;
1174 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1175 if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
1177 if (!asn1_peek_uint8(data, &tag)) goto prot_err;
1179 switch(tag) {
1181 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1182 struct ldap_BindRequest *r = &msg->r.BindRequest;
1183 msg->type = LDAP_TAG_BindRequest;
1184 if (!asn1_start_tag(data, tag)) goto prot_err;
1185 if (!asn1_read_Integer(data, &r->version)) goto prot_err;
1186 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1187 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1188 int pwlen;
1189 r->creds.password = "";
1190 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1191 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1192 pwlen = asn1_tag_remaining(data);
1193 if (pwlen == -1) {
1194 goto prot_err;
1196 if (pwlen != 0) {
1197 char *pw = talloc_array(msg, char, pwlen+1);
1198 if (!pw) {
1199 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1201 if (!asn1_read(data, pw, pwlen)) goto prot_err;
1202 pw[pwlen] = '\0';
1203 r->creds.password = pw;
1205 if (!asn1_end_tag(data)) goto prot_err;
1206 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1207 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
1208 r->mechanism = LDAP_AUTH_MECH_SASL;
1209 if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
1210 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1211 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1212 if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
1213 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1214 if (!r->creds.SASL.secblob) {
1215 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1217 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1218 tmp_blob.data, tmp_blob.length);
1219 data_blob_free(&tmp_blob);
1220 } else {
1221 r->creds.SASL.secblob = NULL;
1223 if (!asn1_end_tag(data)) goto prot_err;
1224 } else {
1225 /* Neither Simple nor SASL bind */
1226 goto prot_err;
1228 if (!asn1_end_tag(data)) goto prot_err;
1229 break;
1232 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1233 struct ldap_BindResponse *r = &msg->r.BindResponse;
1234 msg->type = LDAP_TAG_BindResponse;
1235 if (!asn1_start_tag(data, tag)) goto prot_err;
1236 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1237 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1238 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1239 if (!asn1_read_ContextSimple(data, msg, 7, &tmp_blob)) goto prot_err;
1240 r->SASL.secblob = talloc(msg, DATA_BLOB);
1241 if (!r->SASL.secblob) {
1242 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1244 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1245 tmp_blob.data, tmp_blob.length);
1246 data_blob_free(&tmp_blob);
1247 } else {
1248 r->SASL.secblob = NULL;
1250 if (!asn1_end_tag(data)) goto prot_err;
1251 break;
1254 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1255 msg->type = LDAP_TAG_UnbindRequest;
1256 if (!asn1_start_tag(data, tag)) goto prot_err;
1257 if (!asn1_end_tag(data)) goto prot_err;
1258 break;
1261 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1262 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1263 int sizelimit, timelimit;
1264 const char **attrs = NULL;
1265 size_t request_size = asn1_get_length(data);
1266 msg->type = LDAP_TAG_SearchRequest;
1267 if (request_size > limits->max_search_size) {
1268 goto prot_err;
1270 if (!asn1_start_tag(data, tag)) goto prot_err;
1271 if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
1272 if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
1273 if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
1274 if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
1275 r->sizelimit = sizelimit;
1276 if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
1277 r->timelimit = timelimit;
1278 if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
1280 r->tree = ldap_decode_filter_tree(msg, data);
1281 if (r->tree == NULL) {
1282 goto prot_err;
1285 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1287 r->num_attributes = 0;
1288 r->attributes = NULL;
1290 while (asn1_tag_remaining(data) > 0) {
1292 const char *attr;
1293 if (!asn1_read_OctetString_talloc(msg, data,
1294 &attr))
1295 goto prot_err;
1296 if (!add_string_to_array(msg, attr,
1297 &attrs,
1298 &r->num_attributes))
1299 goto prot_err;
1301 r->attributes = attrs;
1303 if (!asn1_end_tag(data)) goto prot_err;
1304 if (!asn1_end_tag(data)) goto prot_err;
1305 break;
1308 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1309 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1310 msg->type = LDAP_TAG_SearchResultEntry;
1311 r->attributes = NULL;
1312 r->num_attributes = 0;
1313 if (!asn1_start_tag(data, tag)) goto prot_err;
1314 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1315 if (!ldap_decode_attribs(msg, data, &r->attributes,
1316 &r->num_attributes)) goto prot_err;
1317 if (!asn1_end_tag(data)) goto prot_err;
1318 break;
1321 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1322 struct ldap_Result *r = &msg->r.SearchResultDone;
1323 msg->type = LDAP_TAG_SearchResultDone;
1324 if (!asn1_start_tag(data, tag)) goto prot_err;
1325 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1326 if (!asn1_end_tag(data)) goto prot_err;
1327 break;
1330 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1331 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1332 msg->type = LDAP_TAG_SearchResultReference;
1333 if (!asn1_start_tag(data, tag)) goto prot_err;
1334 if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
1335 if (!asn1_end_tag(data)) goto prot_err;
1336 break;
1339 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1340 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1341 msg->type = LDAP_TAG_ModifyRequest;
1342 if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
1343 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1344 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1346 r->num_mods = 0;
1347 r->mods = NULL;
1349 while (asn1_tag_remaining(data) > 0) {
1350 struct ldap_mod mod;
1351 int v;
1352 ZERO_STRUCT(mod);
1353 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1354 if (!asn1_read_enumerated(data, &v)) goto prot_err;
1355 mod.type = v;
1356 if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
1357 if (!asn1_end_tag(data)) goto prot_err;
1358 if (!add_mod_to_array_talloc(msg, &mod,
1359 &r->mods, &r->num_mods)) {
1360 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1364 if (!asn1_end_tag(data)) goto prot_err;
1365 if (!asn1_end_tag(data)) goto prot_err;
1366 break;
1369 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1370 struct ldap_Result *r = &msg->r.ModifyResponse;
1371 msg->type = LDAP_TAG_ModifyResponse;
1372 if (!asn1_start_tag(data, tag)) goto prot_err;
1373 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1374 if (!asn1_end_tag(data)) goto prot_err;
1375 break;
1378 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1379 struct ldap_AddRequest *r = &msg->r.AddRequest;
1380 msg->type = LDAP_TAG_AddRequest;
1381 if (!asn1_start_tag(data, tag)) goto prot_err;
1382 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1384 r->attributes = NULL;
1385 r->num_attributes = 0;
1386 if (!ldap_decode_attribs(msg, data, &r->attributes,
1387 &r->num_attributes)) goto prot_err;
1389 if (!asn1_end_tag(data)) goto prot_err;
1390 break;
1393 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1394 struct ldap_Result *r = &msg->r.AddResponse;
1395 msg->type = LDAP_TAG_AddResponse;
1396 if (!asn1_start_tag(data, tag)) goto prot_err;
1397 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1398 if (!asn1_end_tag(data)) goto prot_err;
1399 break;
1402 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1403 struct ldap_DelRequest *r = &msg->r.DelRequest;
1404 int len;
1405 char *dn;
1406 msg->type = LDAP_TAG_DelRequest;
1407 if (!asn1_start_tag(data,
1408 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
1409 len = asn1_tag_remaining(data);
1410 if (len == -1) {
1411 goto prot_err;
1413 dn = talloc_array(msg, char, len+1);
1414 if (dn == NULL)
1415 break;
1416 if (!asn1_read(data, dn, len)) goto prot_err;
1417 dn[len] = '\0';
1418 r->dn = dn;
1419 if (!asn1_end_tag(data)) goto prot_err;
1420 break;
1423 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1424 struct ldap_Result *r = &msg->r.DelResponse;
1425 msg->type = LDAP_TAG_DelResponse;
1426 if (!asn1_start_tag(data, tag)) goto prot_err;
1427 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1428 if (!asn1_end_tag(data)) goto prot_err;
1429 break;
1432 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1433 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1434 msg->type = LDAP_TAG_ModifyDNRequest;
1435 if (!asn1_start_tag(data,
1436 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
1437 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1438 if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
1439 if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
1440 r->newsuperior = NULL;
1441 if (asn1_tag_remaining(data) > 0) {
1442 int len;
1443 char *newsup;
1444 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1445 len = asn1_tag_remaining(data);
1446 if (len == -1) {
1447 goto prot_err;
1449 newsup = talloc_array(msg, char, len+1);
1450 if (newsup == NULL) {
1451 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1453 if (!asn1_read(data, newsup, len)) goto prot_err;
1454 newsup[len] = '\0';
1455 r->newsuperior = newsup;
1456 if (!asn1_end_tag(data)) goto prot_err;
1458 if (!asn1_end_tag(data)) goto prot_err;
1459 break;
1462 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1463 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1464 msg->type = LDAP_TAG_ModifyDNResponse;
1465 if (!asn1_start_tag(data, tag)) goto prot_err;
1466 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1467 if (!asn1_end_tag(data)) goto prot_err;
1468 break;
1471 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1472 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1473 msg->type = LDAP_TAG_CompareRequest;
1474 if (!asn1_start_tag(data,
1475 ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
1476 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1477 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1478 if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
1479 if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
1480 if (r->value.data) {
1481 talloc_steal(msg, r->value.data);
1483 if (!asn1_end_tag(data)) goto prot_err;
1484 if (!asn1_end_tag(data)) goto prot_err;
1485 break;
1488 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1489 struct ldap_Result *r = &msg->r.CompareResponse;
1490 msg->type = LDAP_TAG_CompareResponse;
1491 if (!asn1_start_tag(data, tag)) goto prot_err;
1492 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1493 if (!asn1_end_tag(data)) goto prot_err;
1494 break;
1497 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1498 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1499 msg->type = LDAP_TAG_AbandonRequest;
1500 if (!asn1_start_tag(data, tag)) goto prot_err;
1501 if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
1502 if (!asn1_end_tag(data)) goto prot_err;
1503 break;
1506 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1507 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1508 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1510 msg->type = LDAP_TAG_ExtendedRequest;
1511 if (!asn1_start_tag(data,tag)) goto prot_err;
1512 if (!asn1_read_ContextSimple(data, msg, 0, &tmp_blob)) {
1513 goto prot_err;
1515 r->oid = blob2string_talloc(msg, tmp_blob);
1516 data_blob_free(&tmp_blob);
1517 if (!r->oid) {
1518 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1521 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1522 if (!asn1_read_ContextSimple(data, msg, 1, &tmp_blob)) goto prot_err;
1523 r->value = talloc(msg, DATA_BLOB);
1524 if (!r->value) {
1525 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1527 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1528 data_blob_free(&tmp_blob);
1529 } else {
1530 r->value = NULL;
1533 if (!asn1_end_tag(data)) goto prot_err;
1534 break;
1537 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1538 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1539 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1541 msg->type = LDAP_TAG_ExtendedResponse;
1542 if (!asn1_start_tag(data, tag)) goto prot_err;
1543 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1545 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1546 if (!asn1_read_ContextSimple(data, msg, 10, &tmp_blob))
1547 goto prot_err;
1548 r->oid = blob2string_talloc(msg, tmp_blob);
1549 data_blob_free(&tmp_blob);
1550 if (!r->oid) {
1551 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1553 } else {
1554 r->oid = NULL;
1557 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1558 if (!asn1_read_ContextSimple(data, msg, 11, &tmp_blob))
1559 goto prot_err;
1560 r->value = talloc(msg, DATA_BLOB);
1561 if (!r->value) {
1562 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1564 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1565 data_blob_free(&tmp_blob);
1566 } else {
1567 r->value = NULL;
1570 if (!asn1_end_tag(data)) goto prot_err;
1571 break;
1573 default:
1574 goto prot_err;
1577 msg->controls = NULL;
1578 msg->controls_decoded = NULL;
1580 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1581 int i = 0;
1582 struct ldb_control **ctrl = NULL;
1583 bool *decoded = NULL;
1585 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
1587 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1588 DATA_BLOB value;
1589 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1591 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1592 if (!ctrl) {
1593 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1596 decoded = talloc_realloc(msg, decoded, bool, i+1);
1597 if (!decoded) {
1598 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1601 ctrl[i] = talloc(ctrl, struct ldb_control);
1602 if (!ctrl[i]) {
1603 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1606 if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1607 goto prot_err;
1610 if (!ldap_decode_control_value(ctrl[i], value,
1611 control_handlers,
1612 ctrl[i])) {
1613 if (ctrl[i]->critical) {
1614 ctrl[i]->data = NULL;
1615 decoded[i] = false;
1616 i++;
1617 } else {
1618 talloc_free(ctrl[i]);
1619 ctrl[i] = NULL;
1621 } else {
1622 decoded[i] = true;
1623 i++;
1627 if (ctrl != NULL) {
1628 ctrl[i] = NULL;
1631 msg->controls = ctrl;
1632 msg->controls_decoded = decoded;
1634 if (!asn1_end_tag(data)) goto prot_err;
1637 if (!asn1_end_tag(data)) goto prot_err;
1638 if (asn1_has_error(data) || asn1_has_nesting(data)) {
1639 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1641 return NT_STATUS_OK;
1643 prot_err:
1645 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1650 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1651 ldap packet. Set packet_size if true.
1653 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1655 int ret;
1657 if (blob.length < 6) {
1659 * We need at least 6 bytes to workout the length
1660 * of the pdu.
1662 return STATUS_MORE_ENTRIES;
1665 ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1666 if (ret != 0) {
1667 return map_nt_error_from_unix_common(ret);
1669 return NT_STATUS_OK;