docs-xml: Update smbtree manpage for new cmdline opition parser
[Samba.git] / libcli / ldap / ldap_message.c
blobc7d868449630a0e7da6748ef9064a3d2701b9df2
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 (!asn1_write_OctetString(data, attrib->name,
550 strlen(attrib->name))) goto err;
551 if (!asn1_push_tag(data, ASN1_SET)) goto err;
552 for (j=0; j<r->attributes[i].num_values; j++) {
553 if (!asn1_write_OctetString(data,
554 attrib->values[j].data,
555 attrib->values[j].length)) goto err;
557 if (!asn1_pop_tag(data)) goto err;
558 if (!asn1_pop_tag(data)) goto err;
560 if (!asn1_pop_tag(data)) goto err;
561 if (!asn1_pop_tag(data)) goto err;
562 break;
564 case LDAP_TAG_AddResponse: {
565 struct ldap_Result *r = &msg->r.AddResponse;
566 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
567 if (!ldap_encode_response(data, r)) goto err;
568 if (!asn1_pop_tag(data)) goto err;
569 break;
571 case LDAP_TAG_DelRequest: {
572 struct ldap_DelRequest *r = &msg->r.DelRequest;
573 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
574 if (!asn1_write(data, r->dn, strlen(r->dn))) goto err;
575 if (!asn1_pop_tag(data)) goto err;
576 break;
578 case LDAP_TAG_DelResponse: {
579 struct ldap_Result *r = &msg->r.DelResponse;
580 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
581 if (!ldap_encode_response(data, r)) goto err;
582 if (!asn1_pop_tag(data)) goto err;
583 break;
585 case LDAP_TAG_ModifyDNRequest: {
586 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
587 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
588 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
589 if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err;
590 if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err;
591 if (r->newsuperior) {
592 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
593 if (!asn1_write(data, r->newsuperior,
594 strlen(r->newsuperior))) goto err;
595 if (!asn1_pop_tag(data)) goto err;
597 if (!asn1_pop_tag(data)) goto err;
598 break;
600 case LDAP_TAG_ModifyDNResponse: {
601 struct ldap_Result *r = &msg->r.ModifyDNResponse;
602 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
603 if (!ldap_encode_response(data, r)) goto err;
604 if (!asn1_pop_tag(data)) goto err;
605 break;
607 case LDAP_TAG_CompareRequest: {
608 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
609 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
610 if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
611 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
612 if (!asn1_write_OctetString(data, r->attribute,
613 strlen(r->attribute))) goto err;
614 if (!asn1_write_OctetString(data, r->value.data,
615 r->value.length)) goto err;
616 if (!asn1_pop_tag(data)) goto err;
617 if (!asn1_pop_tag(data)) goto err;
618 break;
620 case LDAP_TAG_CompareResponse: {
621 struct ldap_Result *r = &msg->r.ModifyDNResponse;
622 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
623 if (!ldap_encode_response(data, r)) goto err;
624 if (!asn1_pop_tag(data)) goto err;
625 break;
627 case LDAP_TAG_AbandonRequest: {
628 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
629 if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
630 if (!asn1_write_implicit_Integer(data, r->messageid)) goto err;
631 if (!asn1_pop_tag(data)) goto err;
632 break;
634 case LDAP_TAG_SearchResultReference: {
635 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
636 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
637 if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err;
638 if (!asn1_pop_tag(data)) goto err;
639 break;
641 case LDAP_TAG_ExtendedRequest: {
642 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
643 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
644 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
645 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
646 if (!asn1_pop_tag(data)) goto err;
647 if (r->value) {
648 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err;
649 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
650 if (!asn1_pop_tag(data)) goto err;
652 if (!asn1_pop_tag(data)) goto err;
653 break;
655 case LDAP_TAG_ExtendedResponse: {
656 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
657 if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
658 if (!ldap_encode_response(data, &r->response)) goto err;
659 if (r->oid) {
660 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err;
661 if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
662 if (!asn1_pop_tag(data)) goto err;
664 if (r->value) {
665 if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err;
666 if (!asn1_write(data, r->value->data, r->value->length)) goto err;
667 if (!asn1_pop_tag(data)) goto err;
669 if (!asn1_pop_tag(data)) goto err;
670 break;
672 default:
673 goto err;
676 if (msg->controls != NULL) {
677 if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
679 for (i = 0; msg->controls[i] != NULL; i++) {
680 if (!ldap_encode_control(mem_ctx, data,
681 control_handlers,
682 msg->controls[i])) {
683 DEBUG(0,("Unable to encode control %s\n",
684 msg->controls[i]->oid));
685 goto err;
689 if (!asn1_pop_tag(data)) goto err;
692 if (!asn1_pop_tag(data)) goto err;
694 if (!asn1_extract_blob(data, mem_ctx, result)) {
695 goto err;
698 asn1_free(data);
700 return true;
702 err:
704 asn1_free(data);
705 return false;
708 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
709 DATA_BLOB blob)
711 char *result = talloc_array(mem_ctx, char, blob.length+1);
712 if (result == NULL) {
713 return NULL;
715 memcpy(result, blob.data, blob.length);
716 result[blob.length] = '\0';
717 return result;
720 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
721 struct asn1_data *data,
722 const char **result)
724 DATA_BLOB string;
725 if (!asn1_read_OctetString(data, mem_ctx, &string))
726 return false;
727 *result = blob2string_talloc(mem_ctx, string);
728 data_blob_free(&string);
729 return *result ? true : false;
732 static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
733 struct asn1_data *data,
734 struct ldap_Result *result)
736 if (!asn1_read_enumerated(data, &result->resultcode)) return false;
737 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
738 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
739 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
740 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
741 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
742 if (!asn1_end_tag(data)) return false;
743 } else {
744 result->referral = NULL;
746 return true;
749 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
752 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
753 if (chunks == NULL) {
754 return NULL;
757 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
758 if (chunks[chunk_num] == NULL) {
759 return NULL;
762 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
763 if (chunks[chunk_num]->data == NULL) {
764 return NULL;
766 chunks[chunk_num]->length = strlen(value);
768 chunks[chunk_num + 1] = NULL;
770 return chunks;
775 parse the ASN.1 formatted search string into a ldb_parse_tree
777 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
778 struct asn1_data *data)
780 uint8_t filter_tag;
781 struct ldb_parse_tree *ret;
783 if (!asn1_peek_uint8(data, &filter_tag)) {
784 return NULL;
787 filter_tag &= 0x1f; /* strip off the asn1 stuff */
789 ret = talloc(mem_ctx, struct ldb_parse_tree);
790 if (ret == NULL) return NULL;
792 switch(filter_tag) {
793 case 0:
794 case 1:
795 /* AND or OR of one or more filters */
796 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
797 ret->u.list.num_elements = 0;
798 ret->u.list.elements = NULL;
800 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
801 goto failed;
804 while (asn1_tag_remaining(data) > 0) {
805 struct ldb_parse_tree *subtree;
806 subtree = ldap_decode_filter_tree(ret, data);
807 if (subtree == NULL) {
808 goto failed;
810 ret->u.list.elements =
811 talloc_realloc(ret, ret->u.list.elements,
812 struct ldb_parse_tree *,
813 ret->u.list.num_elements+1);
814 if (ret->u.list.elements == NULL) {
815 goto failed;
817 talloc_steal(ret->u.list.elements, subtree);
818 ret->u.list.elements[ret->u.list.num_elements] = subtree;
819 ret->u.list.num_elements++;
821 if (!asn1_end_tag(data)) {
822 goto failed;
824 break;
826 case 2:
827 /* 'not' operation */
828 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
829 goto failed;
832 ret->operation = LDB_OP_NOT;
833 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
834 if (ret->u.isnot.child == NULL) {
835 goto failed;
837 if (!asn1_end_tag(data)) {
838 goto failed;
840 break;
842 case 3: {
843 /* equalityMatch */
844 const char *attrib;
845 DATA_BLOB value;
847 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
848 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
849 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
850 if (!asn1_end_tag(data)) goto failed;
851 if (asn1_has_error(data) || (attrib == NULL) ||
852 (value.data == NULL)) {
853 goto failed;
856 ret->operation = LDB_OP_EQUALITY;
857 ret->u.equality.attr = talloc_steal(ret, attrib);
858 ret->u.equality.value.data = talloc_steal(ret, value.data);
859 ret->u.equality.value.length = value.length;
860 break;
862 case 4: {
863 /* substrings */
864 DATA_BLOB attr;
865 uint8_t subs_tag;
866 char *value;
867 int chunk_num = 0;
869 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
870 goto failed;
872 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
873 goto failed;
876 ret->operation = LDB_OP_SUBSTRING;
877 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
878 if (ret->u.substring.attr == NULL) {
879 goto failed;
881 ret->u.substring.chunks = NULL;
882 ret->u.substring.start_with_wildcard = 1;
883 ret->u.substring.end_with_wildcard = 1;
885 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
886 goto failed;
889 while (asn1_tag_remaining(data) > 0) {
890 if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
891 subs_tag &= 0x1f; /* strip off the asn1 stuff */
892 if (subs_tag > 2) goto failed;
894 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
895 if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
896 if (!asn1_end_tag(data)) goto failed;
898 switch (subs_tag) {
899 case 0:
900 if (ret->u.substring.chunks != NULL) {
901 /* initial value found in the middle */
902 goto failed;
905 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
906 if (ret->u.substring.chunks == NULL) {
907 goto failed;
910 ret->u.substring.start_with_wildcard = 0;
911 chunk_num = 1;
912 break;
914 case 1:
915 if (ret->u.substring.end_with_wildcard == 0) {
916 /* "any" value found after a "final" value */
917 goto failed;
920 ret->u.substring.chunks = ldap_decode_substring(ret,
921 ret->u.substring.chunks,
922 chunk_num,
923 value);
924 if (ret->u.substring.chunks == NULL) {
925 goto failed;
928 chunk_num++;
929 break;
931 case 2:
932 ret->u.substring.chunks = ldap_decode_substring(ret,
933 ret->u.substring.chunks,
934 chunk_num,
935 value);
936 if (ret->u.substring.chunks == NULL) {
937 goto failed;
940 ret->u.substring.end_with_wildcard = 0;
941 break;
943 default:
944 goto failed;
949 if (!asn1_end_tag(data)) { /* SEQUENCE */
950 goto failed;
953 if (!asn1_end_tag(data)) {
954 goto failed;
956 break;
958 case 5: {
959 /* greaterOrEqual */
960 const char *attrib;
961 DATA_BLOB value;
963 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
964 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
965 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
966 if (!asn1_end_tag(data)) goto failed;
967 if (asn1_has_error(data) || (attrib == NULL) ||
968 (value.data == NULL)) {
969 goto failed;
972 ret->operation = LDB_OP_GREATER;
973 ret->u.comparison.attr = talloc_steal(ret, attrib);
974 ret->u.comparison.value.data = talloc_steal(ret, value.data);
975 ret->u.comparison.value.length = value.length;
976 break;
978 case 6: {
979 /* lessOrEqual */
980 const char *attrib;
981 DATA_BLOB value;
983 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
984 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
985 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
986 if (!asn1_end_tag(data)) goto failed;
987 if (asn1_has_error(data) || (attrib == NULL) ||
988 (value.data == NULL)) {
989 goto failed;
992 ret->operation = LDB_OP_LESS;
993 ret->u.comparison.attr = talloc_steal(ret, attrib);
994 ret->u.comparison.value.data = talloc_steal(ret, value.data);
995 ret->u.comparison.value.length = value.length;
996 break;
998 case 7: {
999 /* Normal presence, "attribute=*" */
1000 char *attr;
1002 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
1003 goto failed;
1005 if (!asn1_read_LDAPString(data, ret, &attr)) {
1006 goto failed;
1009 ret->operation = LDB_OP_PRESENT;
1010 ret->u.present.attr = talloc_steal(ret, attr);
1012 if (!asn1_end_tag(data)) {
1013 goto failed;
1015 break;
1017 case 8: {
1018 /* approx */
1019 const char *attrib;
1020 DATA_BLOB value;
1022 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
1023 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
1024 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
1025 if (!asn1_end_tag(data)) goto failed;
1026 if (asn1_has_error(data) || (attrib == NULL) ||
1027 (value.data == NULL)) {
1028 goto failed;
1031 ret->operation = LDB_OP_APPROX;
1032 ret->u.comparison.attr = talloc_steal(ret, attrib);
1033 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1034 ret->u.comparison.value.length = value.length;
1035 break;
1037 case 9: {
1038 char *oid = NULL, *attr = NULL, *value;
1039 uint8_t dnAttributes;
1040 /* an extended search */
1041 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1042 goto failed;
1045 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1046 we need to check we properly implement --SSS */
1047 /* either oid or type must be defined */
1048 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1049 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
1050 if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
1051 if (!asn1_end_tag(data)) goto failed;
1053 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1054 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
1055 if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
1056 if (!asn1_end_tag(data)) goto failed;
1058 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
1059 if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
1060 if (!asn1_end_tag(data)) goto failed;
1061 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1062 it is not marked as OPTIONAL but openldap tools
1063 do not set this unless it is to be set as TRUE
1064 NOTE: openldap tools do not work with AD as it
1065 seems that AD always requires the dnAttributes
1066 boolean value to be set */
1067 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1068 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
1069 if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
1070 if (!asn1_end_tag(data)) goto failed;
1071 } else {
1072 dnAttributes = 0;
1074 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1075 goto failed;
1078 if (oid) {
1079 ret->operation = LDB_OP_EXTENDED;
1081 /* From the RFC2251: If the type field is
1082 absent and matchingRule is present, the matchValue is compared
1083 against all attributes in an entry which support that matchingRule
1085 if (attr) {
1086 ret->u.extended.attr = talloc_steal(ret, attr);
1087 } else {
1088 ret->u.extended.attr = talloc_strdup(ret, "*");
1089 if (ret->u.extended.attr == NULL) {
1090 goto failed;
1093 ret->u.extended.rule_id = talloc_steal(ret, oid);
1094 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1095 ret->u.extended.value.length = strlen(value);
1096 ret->u.extended.dnAttributes = dnAttributes;
1097 } else {
1098 ret->operation = LDB_OP_EQUALITY;
1099 ret->u.equality.attr = talloc_steal(ret, attr);
1100 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1101 ret->u.equality.value.length = strlen(value);
1103 if (!asn1_end_tag(data)) {
1104 goto failed;
1106 break;
1109 default:
1110 goto failed;
1113 return ret;
1115 failed:
1116 talloc_free(ret);
1117 return NULL;
1120 /* Decode a single LDAP attribute, possibly containing multiple values */
1121 static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1122 struct ldb_message_element *attrib)
1124 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1125 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
1126 if (!asn1_start_tag(data, ASN1_SET)) return false;
1127 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1128 DATA_BLOB blob;
1129 if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
1130 add_value_to_attrib(mem_ctx, &blob, attrib);
1132 if (!asn1_end_tag(data)) return false;
1133 return asn1_end_tag(data);
1136 /* Decode a set of LDAP attributes, as found in the dereference control */
1137 bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1138 struct ldb_message_element **attributes,
1139 int *num_attributes)
1141 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1142 struct ldb_message_element attrib;
1143 ZERO_STRUCT(attrib);
1144 if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
1145 add_attrib_to_array_talloc(mem_ctx, &attrib,
1146 attributes, num_attributes);
1148 return true;
1151 /* Decode a set of LDAP attributes, as found in a search entry */
1152 static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1153 struct ldb_message_element **attributes,
1154 int *num_attributes)
1156 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1157 if (!ldap_decode_attribs_bare(mem_ctx, data,
1158 attributes, num_attributes)) return false;
1159 return asn1_end_tag(data);
1162 /* This routine returns LDAP status codes */
1164 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1165 const struct ldap_request_limits *limits,
1166 const struct ldap_control_handler *control_handlers,
1167 struct ldap_message *msg)
1169 uint8_t tag;
1171 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1172 if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
1174 if (!asn1_peek_uint8(data, &tag)) goto prot_err;
1176 switch(tag) {
1178 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1179 struct ldap_BindRequest *r = &msg->r.BindRequest;
1180 msg->type = LDAP_TAG_BindRequest;
1181 if (!asn1_start_tag(data, tag)) goto prot_err;
1182 if (!asn1_read_Integer(data, &r->version)) goto prot_err;
1183 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1184 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1185 int pwlen;
1186 r->creds.password = "";
1187 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1188 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1189 pwlen = asn1_tag_remaining(data);
1190 if (pwlen == -1) {
1191 goto prot_err;
1193 if (pwlen != 0) {
1194 char *pw = talloc_array(msg, char, pwlen+1);
1195 if (!pw) {
1196 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1198 if (!asn1_read(data, pw, pwlen)) goto prot_err;
1199 pw[pwlen] = '\0';
1200 r->creds.password = pw;
1202 if (!asn1_end_tag(data)) goto prot_err;
1203 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1204 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
1205 r->mechanism = LDAP_AUTH_MECH_SASL;
1206 if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
1207 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1208 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1209 if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
1210 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1211 if (!r->creds.SASL.secblob) {
1212 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1214 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1215 tmp_blob.data, tmp_blob.length);
1216 data_blob_free(&tmp_blob);
1217 } else {
1218 r->creds.SASL.secblob = NULL;
1220 if (!asn1_end_tag(data)) goto prot_err;
1221 } else {
1222 /* Neither Simple nor SASL bind */
1223 goto prot_err;
1225 if (!asn1_end_tag(data)) goto prot_err;
1226 break;
1229 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1230 struct ldap_BindResponse *r = &msg->r.BindResponse;
1231 msg->type = LDAP_TAG_BindResponse;
1232 if (!asn1_start_tag(data, tag)) goto prot_err;
1233 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1234 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1235 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1236 if (!asn1_read_ContextSimple(data, msg, 7, &tmp_blob)) goto prot_err;
1237 r->SASL.secblob = talloc(msg, DATA_BLOB);
1238 if (!r->SASL.secblob) {
1239 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1241 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1242 tmp_blob.data, tmp_blob.length);
1243 data_blob_free(&tmp_blob);
1244 } else {
1245 r->SASL.secblob = NULL;
1247 if (!asn1_end_tag(data)) goto prot_err;
1248 break;
1251 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1252 msg->type = LDAP_TAG_UnbindRequest;
1253 if (!asn1_start_tag(data, tag)) goto prot_err;
1254 if (!asn1_end_tag(data)) goto prot_err;
1255 break;
1258 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1259 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1260 int sizelimit, timelimit;
1261 const char **attrs = NULL;
1262 size_t request_size = asn1_get_length(data);
1263 msg->type = LDAP_TAG_SearchRequest;
1264 if (request_size > limits->max_search_size) {
1265 goto prot_err;
1267 if (!asn1_start_tag(data, tag)) goto prot_err;
1268 if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
1269 if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
1270 if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
1271 if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
1272 r->sizelimit = sizelimit;
1273 if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
1274 r->timelimit = timelimit;
1275 if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
1277 r->tree = ldap_decode_filter_tree(msg, data);
1278 if (r->tree == NULL) {
1279 goto prot_err;
1282 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1284 r->num_attributes = 0;
1285 r->attributes = NULL;
1287 while (asn1_tag_remaining(data) > 0) {
1289 const char *attr;
1290 if (!asn1_read_OctetString_talloc(msg, data,
1291 &attr))
1292 goto prot_err;
1293 if (!add_string_to_array(msg, attr,
1294 &attrs,
1295 &r->num_attributes))
1296 goto prot_err;
1298 r->attributes = attrs;
1300 if (!asn1_end_tag(data)) goto prot_err;
1301 if (!asn1_end_tag(data)) goto prot_err;
1302 break;
1305 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1306 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1307 msg->type = LDAP_TAG_SearchResultEntry;
1308 r->attributes = NULL;
1309 r->num_attributes = 0;
1310 if (!asn1_start_tag(data, tag)) goto prot_err;
1311 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1312 if (!ldap_decode_attribs(msg, data, &r->attributes,
1313 &r->num_attributes)) goto prot_err;
1314 if (!asn1_end_tag(data)) goto prot_err;
1315 break;
1318 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1319 struct ldap_Result *r = &msg->r.SearchResultDone;
1320 msg->type = LDAP_TAG_SearchResultDone;
1321 if (!asn1_start_tag(data, tag)) goto prot_err;
1322 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1323 if (!asn1_end_tag(data)) goto prot_err;
1324 break;
1327 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1328 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1329 msg->type = LDAP_TAG_SearchResultReference;
1330 if (!asn1_start_tag(data, tag)) goto prot_err;
1331 if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
1332 if (!asn1_end_tag(data)) goto prot_err;
1333 break;
1336 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1337 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1338 msg->type = LDAP_TAG_ModifyRequest;
1339 if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
1340 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1341 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1343 r->num_mods = 0;
1344 r->mods = NULL;
1346 while (asn1_tag_remaining(data) > 0) {
1347 struct ldap_mod mod;
1348 int v;
1349 ZERO_STRUCT(mod);
1350 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1351 if (!asn1_read_enumerated(data, &v)) goto prot_err;
1352 mod.type = v;
1353 if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
1354 if (!asn1_end_tag(data)) goto prot_err;
1355 if (!add_mod_to_array_talloc(msg, &mod,
1356 &r->mods, &r->num_mods)) {
1357 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1361 if (!asn1_end_tag(data)) goto prot_err;
1362 if (!asn1_end_tag(data)) goto prot_err;
1363 break;
1366 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1367 struct ldap_Result *r = &msg->r.ModifyResponse;
1368 msg->type = LDAP_TAG_ModifyResponse;
1369 if (!asn1_start_tag(data, tag)) goto prot_err;
1370 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1371 if (!asn1_end_tag(data)) goto prot_err;
1372 break;
1375 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1376 struct ldap_AddRequest *r = &msg->r.AddRequest;
1377 msg->type = LDAP_TAG_AddRequest;
1378 if (!asn1_start_tag(data, tag)) goto prot_err;
1379 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1381 r->attributes = NULL;
1382 r->num_attributes = 0;
1383 if (!ldap_decode_attribs(msg, data, &r->attributes,
1384 &r->num_attributes)) goto prot_err;
1386 if (!asn1_end_tag(data)) goto prot_err;
1387 break;
1390 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1391 struct ldap_Result *r = &msg->r.AddResponse;
1392 msg->type = LDAP_TAG_AddResponse;
1393 if (!asn1_start_tag(data, tag)) goto prot_err;
1394 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1395 if (!asn1_end_tag(data)) goto prot_err;
1396 break;
1399 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1400 struct ldap_DelRequest *r = &msg->r.DelRequest;
1401 int len;
1402 char *dn;
1403 msg->type = LDAP_TAG_DelRequest;
1404 if (!asn1_start_tag(data,
1405 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
1406 len = asn1_tag_remaining(data);
1407 if (len == -1) {
1408 goto prot_err;
1410 dn = talloc_array(msg, char, len+1);
1411 if (dn == NULL)
1412 break;
1413 if (!asn1_read(data, dn, len)) goto prot_err;
1414 dn[len] = '\0';
1415 r->dn = dn;
1416 if (!asn1_end_tag(data)) goto prot_err;
1417 break;
1420 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1421 struct ldap_Result *r = &msg->r.DelResponse;
1422 msg->type = LDAP_TAG_DelResponse;
1423 if (!asn1_start_tag(data, tag)) goto prot_err;
1424 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1425 if (!asn1_end_tag(data)) goto prot_err;
1426 break;
1429 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1430 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1431 msg->type = LDAP_TAG_ModifyDNRequest;
1432 if (!asn1_start_tag(data,
1433 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
1434 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1435 if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
1436 if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
1437 r->newsuperior = NULL;
1438 if (asn1_tag_remaining(data) > 0) {
1439 int len;
1440 char *newsup;
1441 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1442 len = asn1_tag_remaining(data);
1443 if (len == -1) {
1444 goto prot_err;
1446 newsup = talloc_array(msg, char, len+1);
1447 if (newsup == NULL) {
1448 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1450 if (!asn1_read(data, newsup, len)) goto prot_err;
1451 newsup[len] = '\0';
1452 r->newsuperior = newsup;
1453 if (!asn1_end_tag(data)) goto prot_err;
1455 if (!asn1_end_tag(data)) goto prot_err;
1456 break;
1459 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1460 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1461 msg->type = LDAP_TAG_ModifyDNResponse;
1462 if (!asn1_start_tag(data, tag)) goto prot_err;
1463 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1464 if (!asn1_end_tag(data)) goto prot_err;
1465 break;
1468 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1469 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1470 msg->type = LDAP_TAG_CompareRequest;
1471 if (!asn1_start_tag(data,
1472 ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
1473 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1474 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1475 if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
1476 if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
1477 if (r->value.data) {
1478 talloc_steal(msg, r->value.data);
1480 if (!asn1_end_tag(data)) goto prot_err;
1481 if (!asn1_end_tag(data)) goto prot_err;
1482 break;
1485 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1486 struct ldap_Result *r = &msg->r.CompareResponse;
1487 msg->type = LDAP_TAG_CompareResponse;
1488 if (!asn1_start_tag(data, tag)) goto prot_err;
1489 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1490 if (!asn1_end_tag(data)) goto prot_err;
1491 break;
1494 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1495 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1496 msg->type = LDAP_TAG_AbandonRequest;
1497 if (!asn1_start_tag(data, tag)) goto prot_err;
1498 if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
1499 if (!asn1_end_tag(data)) goto prot_err;
1500 break;
1503 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1504 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1505 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1507 msg->type = LDAP_TAG_ExtendedRequest;
1508 if (!asn1_start_tag(data,tag)) goto prot_err;
1509 if (!asn1_read_ContextSimple(data, msg, 0, &tmp_blob)) {
1510 goto prot_err;
1512 r->oid = blob2string_talloc(msg, tmp_blob);
1513 data_blob_free(&tmp_blob);
1514 if (!r->oid) {
1515 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1518 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1519 if (!asn1_read_ContextSimple(data, msg, 1, &tmp_blob)) goto prot_err;
1520 r->value = talloc(msg, DATA_BLOB);
1521 if (!r->value) {
1522 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1524 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1525 data_blob_free(&tmp_blob);
1526 } else {
1527 r->value = NULL;
1530 if (!asn1_end_tag(data)) goto prot_err;
1531 break;
1534 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1535 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1536 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1538 msg->type = LDAP_TAG_ExtendedResponse;
1539 if (!asn1_start_tag(data, tag)) goto prot_err;
1540 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1542 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1543 if (!asn1_read_ContextSimple(data, msg, 10, &tmp_blob))
1544 goto prot_err;
1545 r->oid = blob2string_talloc(msg, tmp_blob);
1546 data_blob_free(&tmp_blob);
1547 if (!r->oid) {
1548 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1550 } else {
1551 r->oid = NULL;
1554 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1555 if (!asn1_read_ContextSimple(data, msg, 11, &tmp_blob))
1556 goto prot_err;
1557 r->value = talloc(msg, DATA_BLOB);
1558 if (!r->value) {
1559 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1561 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1562 data_blob_free(&tmp_blob);
1563 } else {
1564 r->value = NULL;
1567 if (!asn1_end_tag(data)) goto prot_err;
1568 break;
1570 default:
1571 goto prot_err;
1574 msg->controls = NULL;
1575 msg->controls_decoded = NULL;
1577 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1578 int i = 0;
1579 struct ldb_control **ctrl = NULL;
1580 bool *decoded = NULL;
1582 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
1584 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1585 DATA_BLOB value;
1586 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1588 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1589 if (!ctrl) {
1590 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1593 decoded = talloc_realloc(msg, decoded, bool, i+1);
1594 if (!decoded) {
1595 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1598 ctrl[i] = talloc(ctrl, struct ldb_control);
1599 if (!ctrl[i]) {
1600 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1603 if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1604 goto prot_err;
1607 if (!ldap_decode_control_value(ctrl[i], value,
1608 control_handlers,
1609 ctrl[i])) {
1610 if (ctrl[i]->critical) {
1611 ctrl[i]->data = NULL;
1612 decoded[i] = false;
1613 i++;
1614 } else {
1615 talloc_free(ctrl[i]);
1616 ctrl[i] = NULL;
1618 } else {
1619 decoded[i] = true;
1620 i++;
1624 if (ctrl != NULL) {
1625 ctrl[i] = NULL;
1628 msg->controls = ctrl;
1629 msg->controls_decoded = decoded;
1631 if (!asn1_end_tag(data)) goto prot_err;
1634 if (!asn1_end_tag(data)) goto prot_err;
1635 if (asn1_has_error(data) || asn1_has_nesting(data)) {
1636 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1638 return NT_STATUS_OK;
1640 prot_err:
1642 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1647 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1648 ldap packet. Set packet_size if true.
1650 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1652 int ret;
1654 if (blob.length < 6) {
1656 * We need at least 6 bytes to workout the length
1657 * of the pdu.
1659 return STATUS_MORE_ENTRIES;
1662 ret = asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1663 if (ret != 0) {
1664 return map_nt_error_from_unix_common(ret);
1666 return NT_STATUS_OK;