lib: Make ctdb_watch_us return 0/errno
[Samba.git] / libcli / ldap / ldap_message.c
blob0c664b70101540d0ecba3fe969988471ebc10836
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 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 !data->has_error;
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 !data->has_error;
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);
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 *result = data_blob_talloc(mem_ctx, data->data, data->length);
695 asn1_free(data);
697 return true;
699 err:
701 asn1_free(data);
702 return false;
705 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
706 DATA_BLOB blob)
708 char *result = talloc_array(mem_ctx, char, blob.length+1);
709 if (result == NULL) {
710 return NULL;
712 memcpy(result, blob.data, blob.length);
713 result[blob.length] = '\0';
714 return result;
717 bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
718 struct asn1_data *data,
719 const char **result)
721 DATA_BLOB string;
722 if (!asn1_read_OctetString(data, mem_ctx, &string))
723 return false;
724 *result = blob2string_talloc(mem_ctx, string);
725 data_blob_free(&string);
726 return *result ? true : false;
729 static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
730 struct asn1_data *data,
731 struct ldap_Result *result)
733 if (!asn1_read_enumerated(data, &result->resultcode)) return false;
734 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
735 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
736 if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
737 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
738 if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
739 if (!asn1_end_tag(data)) return false;
740 } else {
741 result->referral = NULL;
743 return true;
746 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
749 chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
750 if (chunks == NULL) {
751 return NULL;
754 chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
755 if (chunks[chunk_num] == NULL) {
756 return NULL;
759 chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
760 if (chunks[chunk_num]->data == NULL) {
761 return NULL;
763 chunks[chunk_num]->length = strlen(value);
765 chunks[chunk_num + 1] = '\0';
767 return chunks;
772 parse the ASN.1 formatted search string into a ldb_parse_tree
774 static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
775 struct asn1_data *data)
777 uint8_t filter_tag;
778 struct ldb_parse_tree *ret;
780 if (!asn1_peek_uint8(data, &filter_tag)) {
781 return NULL;
784 filter_tag &= 0x1f; /* strip off the asn1 stuff */
786 ret = talloc(mem_ctx, struct ldb_parse_tree);
787 if (ret == NULL) return NULL;
789 switch(filter_tag) {
790 case 0:
791 case 1:
792 /* AND or OR of one or more filters */
793 ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
794 ret->u.list.num_elements = 0;
795 ret->u.list.elements = NULL;
797 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
798 goto failed;
801 while (asn1_tag_remaining(data) > 0) {
802 struct ldb_parse_tree *subtree;
803 subtree = ldap_decode_filter_tree(ret, data);
804 if (subtree == NULL) {
805 goto failed;
807 ret->u.list.elements =
808 talloc_realloc(ret, ret->u.list.elements,
809 struct ldb_parse_tree *,
810 ret->u.list.num_elements+1);
811 if (ret->u.list.elements == NULL) {
812 goto failed;
814 talloc_steal(ret->u.list.elements, subtree);
815 ret->u.list.elements[ret->u.list.num_elements] = subtree;
816 ret->u.list.num_elements++;
818 if (!asn1_end_tag(data)) {
819 goto failed;
821 break;
823 case 2:
824 /* 'not' operation */
825 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
826 goto failed;
829 ret->operation = LDB_OP_NOT;
830 ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
831 if (ret->u.isnot.child == NULL) {
832 goto failed;
834 if (!asn1_end_tag(data)) {
835 goto failed;
837 break;
839 case 3: {
840 /* equalityMatch */
841 const char *attrib;
842 DATA_BLOB value;
844 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
845 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
846 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
847 if (!asn1_end_tag(data)) goto failed;
848 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
849 goto failed;
852 ret->operation = LDB_OP_EQUALITY;
853 ret->u.equality.attr = talloc_steal(ret, attrib);
854 ret->u.equality.value.data = talloc_steal(ret, value.data);
855 ret->u.equality.value.length = value.length;
856 break;
858 case 4: {
859 /* substrings */
860 DATA_BLOB attr;
861 uint8_t subs_tag;
862 char *value;
863 int chunk_num = 0;
865 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
866 goto failed;
868 if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
869 goto failed;
872 ret->operation = LDB_OP_SUBSTRING;
873 ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
874 if (ret->u.substring.attr == NULL) {
875 goto failed;
877 ret->u.substring.chunks = NULL;
878 ret->u.substring.start_with_wildcard = 1;
879 ret->u.substring.end_with_wildcard = 1;
881 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
882 goto failed;
885 while (asn1_tag_remaining(data)) {
886 if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
887 subs_tag &= 0x1f; /* strip off the asn1 stuff */
888 if (subs_tag > 2) goto failed;
890 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
891 if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
892 if (!asn1_end_tag(data)) goto failed;
894 switch (subs_tag) {
895 case 0:
896 if (ret->u.substring.chunks != NULL) {
897 /* initial value found in the middle */
898 goto failed;
901 ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
902 if (ret->u.substring.chunks == NULL) {
903 goto failed;
906 ret->u.substring.start_with_wildcard = 0;
907 chunk_num = 1;
908 break;
910 case 1:
911 if (ret->u.substring.end_with_wildcard == 0) {
912 /* "any" value found after a "final" value */
913 goto failed;
916 ret->u.substring.chunks = ldap_decode_substring(ret,
917 ret->u.substring.chunks,
918 chunk_num,
919 value);
920 if (ret->u.substring.chunks == NULL) {
921 goto failed;
924 chunk_num++;
925 break;
927 case 2:
928 ret->u.substring.chunks = ldap_decode_substring(ret,
929 ret->u.substring.chunks,
930 chunk_num,
931 value);
932 if (ret->u.substring.chunks == NULL) {
933 goto failed;
936 ret->u.substring.end_with_wildcard = 0;
937 break;
939 default:
940 goto failed;
945 if (!asn1_end_tag(data)) { /* SEQUENCE */
946 goto failed;
949 if (!asn1_end_tag(data)) {
950 goto failed;
952 break;
954 case 5: {
955 /* greaterOrEqual */
956 const char *attrib;
957 DATA_BLOB value;
959 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
960 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
961 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
962 if (!asn1_end_tag(data)) goto failed;
963 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
964 goto failed;
967 ret->operation = LDB_OP_GREATER;
968 ret->u.comparison.attr = talloc_steal(ret, attrib);
969 ret->u.comparison.value.data = talloc_steal(ret, value.data);
970 ret->u.comparison.value.length = value.length;
971 break;
973 case 6: {
974 /* lessOrEqual */
975 const char *attrib;
976 DATA_BLOB value;
978 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
979 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
980 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
981 if (!asn1_end_tag(data)) goto failed;
982 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
983 goto failed;
986 ret->operation = LDB_OP_LESS;
987 ret->u.comparison.attr = talloc_steal(ret, attrib);
988 ret->u.comparison.value.data = talloc_steal(ret, value.data);
989 ret->u.comparison.value.length = value.length;
990 break;
992 case 7: {
993 /* Normal presence, "attribute=*" */
994 char *attr;
996 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
997 goto failed;
999 if (!asn1_read_LDAPString(data, ret, &attr)) {
1000 goto failed;
1003 ret->operation = LDB_OP_PRESENT;
1004 ret->u.present.attr = talloc_steal(ret, attr);
1006 if (!asn1_end_tag(data)) {
1007 goto failed;
1009 break;
1011 case 8: {
1012 /* approx */
1013 const char *attrib;
1014 DATA_BLOB value;
1016 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
1017 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
1018 if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
1019 if (!asn1_end_tag(data)) goto failed;
1020 if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
1021 goto failed;
1024 ret->operation = LDB_OP_APPROX;
1025 ret->u.comparison.attr = talloc_steal(ret, attrib);
1026 ret->u.comparison.value.data = talloc_steal(ret, value.data);
1027 ret->u.comparison.value.length = value.length;
1028 break;
1030 case 9: {
1031 char *oid = NULL, *attr = NULL, *value;
1032 uint8_t dnAttributes;
1033 /* an extended search */
1034 if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1035 goto failed;
1038 /* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1039 we need to check we properly implement --SSS */
1040 /* either oid or type must be defined */
1041 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1042 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
1043 if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
1044 if (!asn1_end_tag(data)) goto failed;
1046 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */
1047 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
1048 if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
1049 if (!asn1_end_tag(data)) goto failed;
1051 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
1052 if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
1053 if (!asn1_end_tag(data)) goto failed;
1054 /* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1055 it is not marked as OPTIONAL but openldap tools
1056 do not set this unless it is to be set as TRUE
1057 NOTE: openldap tools do not work with AD as it
1058 seems that AD always requires the dnAttributes
1059 boolean value to be set */
1060 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1061 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
1062 if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
1063 if (!asn1_end_tag(data)) goto failed;
1064 } else {
1065 dnAttributes = 0;
1067 if ((oid == NULL && attr == NULL) || (value == NULL)) {
1068 goto failed;
1071 if (oid) {
1072 ret->operation = LDB_OP_EXTENDED;
1074 /* From the RFC2251: If the type field is
1075 absent and matchingRule is present, the matchValue is compared
1076 against all attributes in an entry which support that matchingRule
1078 if (attr) {
1079 ret->u.extended.attr = talloc_steal(ret, attr);
1080 } else {
1081 ret->u.extended.attr = talloc_strdup(ret, "*");
1082 if (ret->u.extended.attr == NULL) {
1083 goto failed;
1086 ret->u.extended.rule_id = talloc_steal(ret, oid);
1087 ret->u.extended.value.data = (uint8_t *)talloc_steal(ret, value);
1088 ret->u.extended.value.length = strlen(value);
1089 ret->u.extended.dnAttributes = dnAttributes;
1090 } else {
1091 ret->operation = LDB_OP_EQUALITY;
1092 ret->u.equality.attr = talloc_steal(ret, attr);
1093 ret->u.equality.value.data = (uint8_t *)talloc_steal(ret, value);
1094 ret->u.equality.value.length = strlen(value);
1096 if (!asn1_end_tag(data)) {
1097 goto failed;
1099 break;
1102 default:
1103 goto failed;
1106 return ret;
1108 failed:
1109 talloc_free(ret);
1110 return NULL;
1113 /* Decode a single LDAP attribute, possibly containing multiple values */
1114 static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1115 struct ldb_message_element *attrib)
1117 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1118 if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
1119 if (!asn1_start_tag(data, ASN1_SET)) return false;
1120 while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1121 DATA_BLOB blob;
1122 if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
1123 add_value_to_attrib(mem_ctx, &blob, attrib);
1125 if (!asn1_end_tag(data)) return false;
1126 return asn1_end_tag(data);
1129 /* Decode a set of LDAP attributes, as found in the dereference control */
1130 bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1131 struct ldb_message_element **attributes,
1132 int *num_attributes)
1134 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1135 struct ldb_message_element attrib;
1136 ZERO_STRUCT(attrib);
1137 if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
1138 add_attrib_to_array_talloc(mem_ctx, &attrib,
1139 attributes, num_attributes);
1141 return true;
1144 /* Decode a set of LDAP attributes, as found in a search entry */
1145 static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1146 struct ldb_message_element **attributes,
1147 int *num_attributes)
1149 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
1150 if (!ldap_decode_attribs_bare(mem_ctx, data,
1151 attributes, num_attributes)) return false;
1152 return asn1_end_tag(data);
1155 /* This routine returns LDAP status codes */
1157 _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1158 const struct ldap_control_handler *control_handlers,
1159 struct ldap_message *msg)
1161 uint8_t tag;
1163 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1164 if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
1166 if (!asn1_peek_uint8(data, &tag)) goto prot_err;
1168 switch(tag) {
1170 case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1171 struct ldap_BindRequest *r = &msg->r.BindRequest;
1172 msg->type = LDAP_TAG_BindRequest;
1173 if (!asn1_start_tag(data, tag)) goto prot_err;
1174 if (!asn1_read_Integer(data, &r->version)) goto prot_err;
1175 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1176 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1177 int pwlen;
1178 r->creds.password = "";
1179 r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1180 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1181 pwlen = asn1_tag_remaining(data);
1182 if (pwlen == -1) {
1183 goto prot_err;
1185 if (pwlen != 0) {
1186 char *pw = talloc_array(msg, char, pwlen+1);
1187 if (!pw) {
1188 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1190 if (!asn1_read(data, pw, pwlen)) goto prot_err;
1191 pw[pwlen] = '\0';
1192 r->creds.password = pw;
1194 if (!asn1_end_tag(data)) goto prot_err;
1195 } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1196 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
1197 r->mechanism = LDAP_AUTH_MECH_SASL;
1198 if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
1199 if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1200 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1201 if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
1202 r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1203 if (!r->creds.SASL.secblob) {
1204 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1206 *r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1207 tmp_blob.data, tmp_blob.length);
1208 data_blob_free(&tmp_blob);
1209 } else {
1210 r->creds.SASL.secblob = NULL;
1212 if (!asn1_end_tag(data)) goto prot_err;
1213 } else {
1214 /* Neither Simple nor SASL bind */
1215 goto prot_err;
1217 if (!asn1_end_tag(data)) goto prot_err;
1218 break;
1221 case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1222 struct ldap_BindResponse *r = &msg->r.BindResponse;
1223 msg->type = LDAP_TAG_BindResponse;
1224 if (!asn1_start_tag(data, tag)) goto prot_err;
1225 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1226 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1227 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1228 if (!asn1_read_ContextSimple(data, 7, &tmp_blob)) goto prot_err;
1229 r->SASL.secblob = talloc(msg, DATA_BLOB);
1230 if (!r->SASL.secblob) {
1231 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1233 *r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1234 tmp_blob.data, tmp_blob.length);
1235 data_blob_free(&tmp_blob);
1236 } else {
1237 r->SASL.secblob = NULL;
1239 if (!asn1_end_tag(data)) goto prot_err;
1240 break;
1243 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1244 msg->type = LDAP_TAG_UnbindRequest;
1245 if (!asn1_start_tag(data, tag)) goto prot_err;
1246 if (!asn1_end_tag(data)) goto prot_err;
1247 break;
1250 case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1251 struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1252 int sizelimit, timelimit;
1253 const char **attrs = NULL;
1254 msg->type = LDAP_TAG_SearchRequest;
1255 if (!asn1_start_tag(data, tag)) goto prot_err;
1256 if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
1257 if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
1258 if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
1259 if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
1260 r->sizelimit = sizelimit;
1261 if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
1262 r->timelimit = timelimit;
1263 if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
1265 r->tree = ldap_decode_filter_tree(msg, data);
1266 if (r->tree == NULL) {
1267 goto prot_err;
1270 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1272 r->num_attributes = 0;
1273 r->attributes = NULL;
1275 while (asn1_tag_remaining(data) > 0) {
1277 const char *attr;
1278 if (!asn1_read_OctetString_talloc(msg, data,
1279 &attr))
1280 goto prot_err;
1281 if (!add_string_to_array(msg, attr,
1282 &attrs,
1283 &r->num_attributes))
1284 goto prot_err;
1286 r->attributes = attrs;
1288 if (!asn1_end_tag(data)) goto prot_err;
1289 if (!asn1_end_tag(data)) goto prot_err;
1290 break;
1293 case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1294 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1295 msg->type = LDAP_TAG_SearchResultEntry;
1296 r->attributes = NULL;
1297 r->num_attributes = 0;
1298 if (!asn1_start_tag(data, tag)) goto prot_err;
1299 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1300 if (!ldap_decode_attribs(msg, data, &r->attributes,
1301 &r->num_attributes)) goto prot_err;
1302 if (!asn1_end_tag(data)) goto prot_err;
1303 break;
1306 case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1307 struct ldap_Result *r = &msg->r.SearchResultDone;
1308 msg->type = LDAP_TAG_SearchResultDone;
1309 if (!asn1_start_tag(data, tag)) goto prot_err;
1310 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1311 if (!asn1_end_tag(data)) goto prot_err;
1312 break;
1315 case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1316 struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1317 msg->type = LDAP_TAG_SearchResultReference;
1318 if (!asn1_start_tag(data, tag)) goto prot_err;
1319 if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
1320 if (!asn1_end_tag(data)) goto prot_err;
1321 break;
1324 case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1325 struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1326 msg->type = LDAP_TAG_ModifyRequest;
1327 if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
1328 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1329 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1331 r->num_mods = 0;
1332 r->mods = NULL;
1334 while (asn1_tag_remaining(data) > 0) {
1335 struct ldap_mod mod;
1336 int v;
1337 ZERO_STRUCT(mod);
1338 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1339 if (!asn1_read_enumerated(data, &v)) goto prot_err;
1340 mod.type = v;
1341 if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
1342 if (!asn1_end_tag(data)) goto prot_err;
1343 if (!add_mod_to_array_talloc(msg, &mod,
1344 &r->mods, &r->num_mods)) {
1345 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1349 if (!asn1_end_tag(data)) goto prot_err;
1350 if (!asn1_end_tag(data)) goto prot_err;
1351 break;
1354 case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1355 struct ldap_Result *r = &msg->r.ModifyResponse;
1356 msg->type = LDAP_TAG_ModifyResponse;
1357 if (!asn1_start_tag(data, tag)) goto prot_err;
1358 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1359 if (!asn1_end_tag(data)) goto prot_err;
1360 break;
1363 case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1364 struct ldap_AddRequest *r = &msg->r.AddRequest;
1365 msg->type = LDAP_TAG_AddRequest;
1366 if (!asn1_start_tag(data, tag)) goto prot_err;
1367 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1369 r->attributes = NULL;
1370 r->num_attributes = 0;
1371 if (!ldap_decode_attribs(msg, data, &r->attributes,
1372 &r->num_attributes)) goto prot_err;
1374 if (!asn1_end_tag(data)) goto prot_err;
1375 break;
1378 case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1379 struct ldap_Result *r = &msg->r.AddResponse;
1380 msg->type = LDAP_TAG_AddResponse;
1381 if (!asn1_start_tag(data, tag)) goto prot_err;
1382 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1383 if (!asn1_end_tag(data)) goto prot_err;
1384 break;
1387 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1388 struct ldap_DelRequest *r = &msg->r.DelRequest;
1389 int len;
1390 char *dn;
1391 msg->type = LDAP_TAG_DelRequest;
1392 if (!asn1_start_tag(data,
1393 ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
1394 len = asn1_tag_remaining(data);
1395 if (len == -1) {
1396 goto prot_err;
1398 dn = talloc_array(msg, char, len+1);
1399 if (dn == NULL)
1400 break;
1401 if (!asn1_read(data, dn, len)) goto prot_err;
1402 dn[len] = '\0';
1403 r->dn = dn;
1404 if (!asn1_end_tag(data)) goto prot_err;
1405 break;
1408 case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1409 struct ldap_Result *r = &msg->r.DelResponse;
1410 msg->type = LDAP_TAG_DelResponse;
1411 if (!asn1_start_tag(data, tag)) goto prot_err;
1412 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1413 if (!asn1_end_tag(data)) goto prot_err;
1414 break;
1417 case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1418 struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1419 msg->type = LDAP_TAG_ModifyDNRequest;
1420 if (!asn1_start_tag(data,
1421 ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
1422 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1423 if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
1424 if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
1425 r->newsuperior = NULL;
1426 if (asn1_tag_remaining(data) > 0) {
1427 int len;
1428 char *newsup;
1429 if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
1430 len = asn1_tag_remaining(data);
1431 if (len == -1) {
1432 goto prot_err;
1434 newsup = talloc_array(msg, char, len+1);
1435 if (newsup == NULL) {
1436 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1438 if (!asn1_read(data, newsup, len)) goto prot_err;
1439 newsup[len] = '\0';
1440 r->newsuperior = newsup;
1441 if (!asn1_end_tag(data)) goto prot_err;
1443 if (!asn1_end_tag(data)) goto prot_err;
1444 break;
1447 case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1448 struct ldap_Result *r = &msg->r.ModifyDNResponse;
1449 msg->type = LDAP_TAG_ModifyDNResponse;
1450 if (!asn1_start_tag(data, tag)) goto prot_err;
1451 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1452 if (!asn1_end_tag(data)) goto prot_err;
1453 break;
1456 case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1457 struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1458 msg->type = LDAP_TAG_CompareRequest;
1459 if (!asn1_start_tag(data,
1460 ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
1461 if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
1462 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
1463 if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
1464 if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
1465 if (r->value.data) {
1466 talloc_steal(msg, r->value.data);
1468 if (!asn1_end_tag(data)) goto prot_err;
1469 if (!asn1_end_tag(data)) goto prot_err;
1470 break;
1473 case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1474 struct ldap_Result *r = &msg->r.CompareResponse;
1475 msg->type = LDAP_TAG_CompareResponse;
1476 if (!asn1_start_tag(data, tag)) goto prot_err;
1477 if (!ldap_decode_response(msg, data, r)) goto prot_err;
1478 if (!asn1_end_tag(data)) goto prot_err;
1479 break;
1482 case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1483 struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1484 msg->type = LDAP_TAG_AbandonRequest;
1485 if (!asn1_start_tag(data, tag)) goto prot_err;
1486 if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
1487 if (!asn1_end_tag(data)) goto prot_err;
1488 break;
1491 case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1492 struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1493 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1495 msg->type = LDAP_TAG_ExtendedRequest;
1496 if (!asn1_start_tag(data,tag)) goto prot_err;
1497 if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1498 goto prot_err;
1500 r->oid = blob2string_talloc(msg, tmp_blob);
1501 data_blob_free(&tmp_blob);
1502 if (!r->oid) {
1503 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1506 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1507 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1508 r->value = talloc(msg, DATA_BLOB);
1509 if (!r->value) {
1510 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1512 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1513 data_blob_free(&tmp_blob);
1514 } else {
1515 r->value = NULL;
1518 if (!asn1_end_tag(data)) goto prot_err;
1519 break;
1522 case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1523 struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1524 DATA_BLOB tmp_blob = data_blob(NULL, 0);
1526 msg->type = LDAP_TAG_ExtendedResponse;
1527 if (!asn1_start_tag(data, tag)) goto prot_err;
1528 if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
1530 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1531 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1532 r->oid = blob2string_talloc(msg, tmp_blob);
1533 data_blob_free(&tmp_blob);
1534 if (!r->oid) {
1535 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1537 } else {
1538 r->oid = NULL;
1541 if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1542 if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
1543 r->value = talloc(msg, DATA_BLOB);
1544 if (!r->value) {
1545 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1547 *r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1548 data_blob_free(&tmp_blob);
1549 } else {
1550 r->value = NULL;
1553 if (!asn1_end_tag(data)) goto prot_err;
1554 break;
1556 default:
1557 goto prot_err;
1560 msg->controls = NULL;
1561 msg->controls_decoded = NULL;
1563 if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1564 int i = 0;
1565 struct ldb_control **ctrl = NULL;
1566 bool *decoded = NULL;
1568 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
1570 while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1571 DATA_BLOB value;
1572 /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1574 ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1575 if (!ctrl) {
1576 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1579 decoded = talloc_realloc(msg, decoded, bool, i+1);
1580 if (!decoded) {
1581 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1584 ctrl[i] = talloc(ctrl, struct ldb_control);
1585 if (!ctrl[i]) {
1586 return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1589 if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
1590 goto prot_err;
1593 if (!ldap_decode_control_value(ctrl[i], value,
1594 control_handlers,
1595 ctrl[i])) {
1596 if (ctrl[i]->critical) {
1597 ctrl[i]->data = NULL;
1598 decoded[i] = false;
1599 i++;
1600 } else {
1601 talloc_free(ctrl[i]);
1602 ctrl[i] = NULL;
1604 } else {
1605 decoded[i] = true;
1606 i++;
1610 if (ctrl != NULL) {
1611 ctrl[i] = NULL;
1614 msg->controls = ctrl;
1615 msg->controls_decoded = decoded;
1617 if (!asn1_end_tag(data)) goto prot_err;
1620 if (!asn1_end_tag(data)) goto prot_err;
1621 if ((data->has_error) || (data->nesting != NULL)) {
1622 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1624 return NT_STATUS_OK;
1626 prot_err:
1628 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1633 return NT_STATUS_OK if a blob has enough bytes in it to be a full
1634 ldap packet. Set packet_size if true.
1636 NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1638 if (blob.length < 6) {
1640 * We need at least 6 bytes to workout the length
1641 * of the pdu.
1643 return STATUS_MORE_ENTRIES;
1645 return asn1_peek_full_tag(blob, ASN1_SEQUENCE(0), packet_size);