1/*
2   Unix SMB/CIFS mplementation.
3   LDAP protocol helper functions for SAMBA
4
5   Copyright (C) Andrew Tridgell  2004
6   Copyright (C) Volker Lendecke 2004
7   Copyright (C) Stefan Metzmacher 2004
8   Copyright (C) Simo Sorce 2004
9
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.
14
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.
19
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/>.
22
23*/
24
25#include "includes.h"
26#include "../lib/util/asn1.h"
27#include "../libcli/ldap/ldap_message.h"
28
29_PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
30{
31	return talloc_zero(mem_ctx, struct ldap_message);
32}
33
34
35static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
36				struct ldb_message_element *attrib)
37{
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;
44
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;
50}
51
52static 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)
56{
57	*attribs = talloc_realloc(mem_ctx,
58				  *attribs,
59				  struct ldb_message_element,
60				  *num_attribs+1);
61
62	if (*attribs == NULL)
63		return false;
64
65	(*attribs)[*num_attribs] = *attrib;
66	talloc_steal(*attribs, attrib->values);
67	talloc_steal(*attribs, attrib->name);
68	*num_attribs += 1;
69	return true;
70}
71
72static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
73				    struct ldap_mod *mod,
74				    struct ldap_mod **mods,
75				    int *num_mods)
76{
77	*mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
78
79	if (*mods == NULL)
80		return false;
81
82	(*mods)[*num_mods] = *mod;
83	*num_mods += 1;
84	return true;
85}
86
87static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
88				      const struct ldap_control_handler *handlers,
89				      struct ldb_control *ctrl)
90{
91	int i;
92
93	if (!handlers) {
94		return true;
95	}
96
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;
101			}
102			break;
103		}
104	}
105	if (handlers[i].oid == NULL) {
106		return false;
107	}
108
109	return true;
110}
111
112static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
113					struct ldb_control *ctrl, DATA_BLOB *value)
114{
115	DATA_BLOB oid;
116
117	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
118		return false;
119	}
120
121	if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
122		return false;
123	}
124	ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
125	if (!ctrl->oid) {
126		return false;
127	}
128
129	if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
130		bool critical;
131		if (!asn1_read_BOOLEAN(data, &critical)) {
132			return false;
133		}
134		ctrl->critical = critical;
135	} else {
136		ctrl->critical = false;
137	}
138
139	ctrl->data = NULL;
140
141	if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
142		*value = data_blob(NULL, 0);
143		goto end_tag;
144	}
145
146	if (!asn1_read_OctetString(data, mem_ctx, value)) {
147		return false;
148	}
149
150end_tag:
151	if (!asn1_end_tag(data)) {
152		return false;
153	}
154
155	return true;
156}
157
158static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
159				const struct ldap_control_handler *handlers,
160				struct ldb_control *ctrl)
161{
162	DATA_BLOB value;
163	int i;
164
165	if (!handlers) {
166		return false;
167	}
168
169	for (i = 0; handlers[i].oid != NULL; i++) {
170		if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
171			if (!handlers[i].encode) {
172				if (ctrl->critical) {
173					return false;
174				} else {
175					/* not encoding this control */
176					return true;
177				}
178			}
179			if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
180				return false;
181			}
182			break;
183		}
184	}
185	if (handlers[i].oid == NULL) {
186		return false;
187	}
188
189	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
190		return false;
191	}
192
193	if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
194		return false;
195	}
196
197	if (ctrl->critical) {
198		if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
199			return false;
200		}
201	}
202
203	if (!ctrl->data) {
204		goto pop_tag;
205	}
206
207	if (!asn1_write_OctetString(data, value.data, value.length)) {
208		return false;
209	}
210
211pop_tag:
212	if (!asn1_pop_tag(data)) {
213		return false;
214	}
215
216	return true;
217}
218
219static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
220{
221	int i;
222
223	switch (tree->operation) {
224	case LDB_OP_AND:
225	case LDB_OP_OR:
226		asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
227		for (i=0; i<tree->u.list.num_elements; i++) {
228			if (!ldap_push_filter(data, tree->u.list.elements[i])) {
229				return false;
230			}
231		}
232		asn1_pop_tag(data);
233		break;
234
235	case LDB_OP_NOT:
236		asn1_push_tag(data, ASN1_CONTEXT(2));
237		if (!ldap_push_filter(data, tree->u.isnot.child)) {
238			return false;
239		}
240		asn1_pop_tag(data);
241		break;
242
243	case LDB_OP_EQUALITY:
244		/* equality test */
245		asn1_push_tag(data, ASN1_CONTEXT(3));
246		asn1_write_OctetString(data, tree->u.equality.attr,
247				      strlen(tree->u.equality.attr));
248		asn1_write_OctetString(data, tree->u.equality.value.data,
249				      tree->u.equality.value.length);
250		asn1_pop_tag(data);
251		break;
252
253	case LDB_OP_SUBSTRING:
254		/*
255		  SubstringFilter ::= SEQUENCE {
256			  type            AttributeDescription,
257			  -- at least one must be present
258			  substrings      SEQUENCE OF CHOICE {
259				  initial [0] LDAPString,
260				  any     [1] LDAPString,
261				  final   [2] LDAPString } }
262		*/
263		asn1_push_tag(data, ASN1_CONTEXT(4));
264		asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
265		asn1_push_tag(data, ASN1_SEQUENCE(0));
266		i = 0;
267		if ( ! tree->u.substring.start_with_wildcard) {
268			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
269			asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
270			asn1_pop_tag(data);
271			i++;
272		}
273		while (tree->u.substring.chunks[i]) {
274			int ctx;
275
276			if (( ! tree->u.substring.chunks[i + 1]) &&
277			    (tree->u.substring.end_with_wildcard == 0)) {
278				ctx = 2;
279			} else {
280				ctx = 1;
281			}
282			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
283			asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
284			asn1_pop_tag(data);
285			i++;
286		}
287		asn1_pop_tag(data);
288		asn1_pop_tag(data);
289		break;
290
291	case LDB_OP_GREATER:
292		/* greaterOrEqual test */
293		asn1_push_tag(data, ASN1_CONTEXT(5));
294		asn1_write_OctetString(data, tree->u.comparison.attr,
295				      strlen(tree->u.comparison.attr));
296		asn1_write_OctetString(data, tree->u.comparison.value.data,
297				      tree->u.comparison.value.length);
298		asn1_pop_tag(data);
299		break;
300
301	case LDB_OP_LESS:
302		/* lessOrEqual test */
303		asn1_push_tag(data, ASN1_CONTEXT(6));
304		asn1_write_OctetString(data, tree->u.comparison.attr,
305				      strlen(tree->u.comparison.attr));
306		asn1_write_OctetString(data, tree->u.comparison.value.data,
307				      tree->u.comparison.value.length);
308		asn1_pop_tag(data);
309		break;
310
311	case LDB_OP_PRESENT:
312		/* present test */
313		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
314		asn1_write_LDAPString(data, tree->u.present.attr);
315		asn1_pop_tag(data);
316		return !data->has_error;
317
318	case LDB_OP_APPROX:
319		/* approx test */
320		asn1_push_tag(data, ASN1_CONTEXT(8));
321		asn1_write_OctetString(data, tree->u.comparison.attr,
322				      strlen(tree->u.comparison.attr));
323		asn1_write_OctetString(data, tree->u.comparison.value.data,
324				      tree->u.comparison.value.length);
325		asn1_pop_tag(data);
326		break;
327
328	case LDB_OP_EXTENDED:
329		/*
330		  MatchingRuleAssertion ::= SEQUENCE {
331		  matchingRule    [1] MatchingRuleID OPTIONAL,
332		  type            [2] AttributeDescription OPTIONAL,
333		  matchValue      [3] AssertionValue,
334		  dnAttributes    [4] BOOLEAN DEFAULT FALSE
335		  }
336		*/
337		asn1_push_tag(data, ASN1_CONTEXT(9));
338		if (tree->u.extended.rule_id) {
339			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
340			asn1_write_LDAPString(data, tree->u.extended.rule_id);
341			asn1_pop_tag(data);
342		}
343		if (tree->u.extended.attr) {
344			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
345			asn1_write_LDAPString(data, tree->u.extended.attr);
346			asn1_pop_tag(data);
347		}
348		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
349		asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
350		asn1_pop_tag(data);
351		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
352		asn1_write_uint8(data, tree->u.extended.dnAttributes);
353		asn1_pop_tag(data);
354		asn1_pop_tag(data);
355		break;
356
357	default:
358		return false;
359	}
360	return !data->has_error;
361}
362
363static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
364{
365	asn1_write_enumerated(data, result->resultcode);
366	asn1_write_OctetString(data, result->dn,
367			       (result->dn) ? strlen(result->dn) : 0);
368	asn1_write_OctetString(data, result->errormessage,
369			       (result->errormessage) ?
370			       strlen(result->errormessage) : 0);
371	if (result->referral) {
372		asn1_push_tag(data, ASN1_CONTEXT(3));
373		asn1_write_OctetString(data, result->referral,
374				       strlen(result->referral));
375		asn1_pop_tag(data);
376	}
377}
378
379_PUBLIC_ bool ldap_encode(struct ldap_message *msg,
380			  const struct ldap_control_handler *control_handlers,
381			  DATA_BLOB *result, TALLOC_CTX *mem_ctx)
382{
383	struct asn1_data *data = asn1_init(mem_ctx);
384	int i, j;
385
386	if (!data) return false;
387
388	asn1_push_tag(data, ASN1_SEQUENCE(0));
389	asn1_write_Integer(data, msg->messageid);
390
391	switch (msg->type) {
392	case LDAP_TAG_BindRequest: {
393		struct ldap_BindRequest *r = &msg->r.BindRequest;
394		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
395		asn1_write_Integer(data, r->version);
396		asn1_write_OctetString(data, r->dn,
397				       (r->dn != NULL) ? strlen(r->dn) : 0);
398
399		switch (r->mechanism) {
400		case LDAP_AUTH_MECH_SIMPLE:
401			/* context, primitive */
402			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
403			asn1_write(data, r->creds.password,
404				   strlen(r->creds.password));
405			asn1_pop_tag(data);
406			break;
407		case LDAP_AUTH_MECH_SASL:
408			/* context, constructed */
409			asn1_push_tag(data, ASN1_CONTEXT(3));
410			asn1_write_OctetString(data, r->creds.SASL.mechanism,
411					       strlen(r->creds.SASL.mechanism));
412			if (r->creds.SASL.secblob) {
413				asn1_write_OctetString(data, r->creds.SASL.secblob->data,
414						       r->creds.SASL.secblob->length);
415			}
416			asn1_pop_tag(data);
417			break;
418		default:
419			return false;
420		}
421
422		asn1_pop_tag(data);
423		break;
424	}
425	case LDAP_TAG_BindResponse: {
426		struct ldap_BindResponse *r = &msg->r.BindResponse;
427		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
428		ldap_encode_response(data, &r->response);
429		if (r->SASL.secblob) {
430			asn1_write_ContextSimple(data, 7, r->SASL.secblob);
431		}
432		asn1_pop_tag(data);
433		break;
434	}
435	case LDAP_TAG_UnbindRequest: {
436/*		struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
437		break;
438	}
439	case LDAP_TAG_SearchRequest: {
440		struct ldap_SearchRequest *r = &msg->r.SearchRequest;
441		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
442		asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
443		asn1_write_enumerated(data, r->scope);
444		asn1_write_enumerated(data, r->deref);
445		asn1_write_Integer(data, r->sizelimit);
446		asn1_write_Integer(data, r->timelimit);
447		asn1_write_BOOLEAN(data, r->attributesonly);
448
449		if (!ldap_push_filter(data, r->tree)) {
450			return false;
451		}
452
453		asn1_push_tag(data, ASN1_SEQUENCE(0));
454		for (i=0; i<r->num_attributes; i++) {
455			asn1_write_OctetString(data, r->attributes[i],
456					       strlen(r->attributes[i]));
457		}
458		asn1_pop_tag(data);
459		asn1_pop_tag(data);
460		break;
461	}
462	case LDAP_TAG_SearchResultEntry: {
463		struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
464		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
465		asn1_write_OctetString(data, r->dn, strlen(r->dn));
466		asn1_push_tag(data, ASN1_SEQUENCE(0));
467		for (i=0; i<r->num_attributes; i++) {
468			struct ldb_message_element *attr = &r->attributes[i];
469			asn1_push_tag(data, ASN1_SEQUENCE(0));
470			asn1_write_OctetString(data, attr->name,
471					       strlen(attr->name));
472			asn1_push_tag(data, ASN1_SEQUENCE(1));
473			for (j=0; j<attr->num_values; j++) {
474				asn1_write_OctetString(data,
475						       attr->values[j].data,
476						       attr->values[j].length);
477			}
478			asn1_pop_tag(data);
479			asn1_pop_tag(data);
480		}
481		asn1_pop_tag(data);
482		asn1_pop_tag(data);
483		break;
484	}
485	case LDAP_TAG_SearchResultDone: {
486		struct ldap_Result *r = &msg->r.SearchResultDone;
487		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
488		ldap_encode_response(data, r);
489		asn1_pop_tag(data);
490		break;
491	}
492	case LDAP_TAG_ModifyRequest: {
493		struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
494		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
495		asn1_write_OctetString(data, r->dn, strlen(r->dn));
496		asn1_push_tag(data, ASN1_SEQUENCE(0));
497
498		for (i=0; i<r->num_mods; i++) {
499			struct ldb_message_element *attrib = &r->mods[i].attrib;
500			asn1_push_tag(data, ASN1_SEQUENCE(0));
501			asn1_write_enumerated(data, r->mods[i].type);
502			asn1_push_tag(data, ASN1_SEQUENCE(0));
503			asn1_write_OctetString(data, attrib->name,
504					       strlen(attrib->name));
505			asn1_push_tag(data, ASN1_SET);
506			for (j=0; j<attrib->num_values; j++) {
507				asn1_write_OctetString(data,
508						       attrib->values[j].data,
509						       attrib->values[j].length);
510
511			}
512			asn1_pop_tag(data);
513			asn1_pop_tag(data);
514			asn1_pop_tag(data);
515		}
516
517		asn1_pop_tag(data);
518		asn1_pop_tag(data);
519		break;
520	}
521	case LDAP_TAG_ModifyResponse: {
522		struct ldap_Result *r = &msg->r.ModifyResponse;
523		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
524		ldap_encode_response(data, r);
525		asn1_pop_tag(data);
526		break;
527	}
528	case LDAP_TAG_AddRequest: {
529		struct ldap_AddRequest *r = &msg->r.AddRequest;
530		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
531		asn1_write_OctetString(data, r->dn, strlen(r->dn));
532		asn1_push_tag(data, ASN1_SEQUENCE(0));
533
534		for (i=0; i<r->num_attributes; i++) {
535			struct ldb_message_element *attrib = &r->attributes[i];
536			asn1_push_tag(data, ASN1_SEQUENCE(0));
537			asn1_write_OctetString(data, attrib->name,
538					       strlen(attrib->name));
539			asn1_push_tag(data, ASN1_SET);
540			for (j=0; j<r->attributes[i].num_values; j++) {
541				asn1_write_OctetString(data,
542						       attrib->values[j].data,
543						       attrib->values[j].length);
544			}
545			asn1_pop_tag(data);
546			asn1_pop_tag(data);
547		}
548		asn1_pop_tag(data);
549		asn1_pop_tag(data);
550		break;
551	}
552	case LDAP_TAG_AddResponse: {
553		struct ldap_Result *r = &msg->r.AddResponse;
554		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
555		ldap_encode_response(data, r);
556		asn1_pop_tag(data);
557		break;
558	}
559	case LDAP_TAG_DelRequest: {
560		struct ldap_DelRequest *r = &msg->r.DelRequest;
561		asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
562		asn1_write(data, r->dn, strlen(r->dn));
563		asn1_pop_tag(data);
564		break;
565	}
566	case LDAP_TAG_DelResponse: {
567		struct ldap_Result *r = &msg->r.DelResponse;
568		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
569		ldap_encode_response(data, r);
570		asn1_pop_tag(data);
571		break;
572	}
573	case LDAP_TAG_ModifyDNRequest: {
574		struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
575		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
576		asn1_write_OctetString(data, r->dn, strlen(r->dn));
577		asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
578		asn1_write_BOOLEAN(data, r->deleteolddn);
579		if (r->newsuperior) {
580			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
581			asn1_write(data, r->newsuperior,
582				   strlen(r->newsuperior));
583			asn1_pop_tag(data);
584		}
585		asn1_pop_tag(data);
586		break;
587	}
588	case LDAP_TAG_ModifyDNResponse: {
589		struct ldap_Result *r = &msg->r.ModifyDNResponse;
590		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
591		ldap_encode_response(data, r);
592		asn1_pop_tag(data);
593		break;
594	}
595	case LDAP_TAG_CompareRequest: {
596		struct ldap_CompareRequest *r = &msg->r.CompareRequest;
597		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
598		asn1_write_OctetString(data, r->dn, strlen(r->dn));
599		asn1_push_tag(data, ASN1_SEQUENCE(0));
600		asn1_write_OctetString(data, r->attribute,
601				       strlen(r->attribute));
602		asn1_write_OctetString(data, r->value.data,
603				       r->value.length);
604		asn1_pop_tag(data);
605		asn1_pop_tag(data);
606		break;
607	}
608	case LDAP_TAG_CompareResponse: {
609		struct ldap_Result *r = &msg->r.ModifyDNResponse;
610		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
611		ldap_encode_response(data, r);
612		asn1_pop_tag(data);
613		break;
614	}
615	case LDAP_TAG_AbandonRequest: {
616		struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
617		asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
618		asn1_write_implicit_Integer(data, r->messageid);
619		asn1_pop_tag(data);
620		break;
621	}
622	case LDAP_TAG_SearchResultReference: {
623		struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
624		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
625		asn1_write_OctetString(data, r->referral, strlen(r->referral));
626		asn1_pop_tag(data);
627		break;
628	}
629	case LDAP_TAG_ExtendedRequest: {
630		struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
631		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
632		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
633		asn1_write(data, r->oid, strlen(r->oid));
634		asn1_pop_tag(data);
635		if (r->value) {
636			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
637			asn1_write(data, r->value->data, r->value->length);
638			asn1_pop_tag(data);
639		}
640		asn1_pop_tag(data);
641		break;
642	}
643	case LDAP_TAG_ExtendedResponse: {
644		struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
645		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
646		ldap_encode_response(data, &r->response);
647		if (r->oid) {
648			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
649			asn1_write(data, r->oid, strlen(r->oid));
650			asn1_pop_tag(data);
651		}
652		if (r->value) {
653			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
654			asn1_write(data, r->value->data, r->value->length);
655			asn1_pop_tag(data);
656		}
657		asn1_pop_tag(data);
658		break;
659	}
660	default:
661		return false;
662	}
663
664	if (msg->controls != NULL) {
665		asn1_push_tag(data, ASN1_CONTEXT(0));
666
667		for (i = 0; msg->controls[i] != NULL; i++) {
668			if (!ldap_encode_control(mem_ctx, data,
669						 control_handlers,
670						 msg->controls[i])) {
671				return false;
672			}
673		}
674
675		asn1_pop_tag(data);
676	}
677
678	asn1_pop_tag(data);
679
680	if (data->has_error) {
681		asn1_free(data);
682		return false;
683	}
684
685	*result = data_blob_talloc(mem_ctx, data->data, data->length);
686	asn1_free(data);
687	return true;
688}
689
690static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
691				      DATA_BLOB blob)
692{
693	char *result = talloc_array(mem_ctx, char, blob.length+1);
694	memcpy(result, blob.data, blob.length);
695	result[blob.length] = '\0';
696	return result;
697}
698
699bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
700				  struct asn1_data *data,
701				  const char **result)
702{
703	DATA_BLOB string;
704	if (!asn1_read_OctetString(data, mem_ctx, &string))
705		return false;
706	*result = blob2string_talloc(mem_ctx, string);
707	data_blob_free(&string);
708	return true;
709}
710
711static void ldap_decode_response(TALLOC_CTX *mem_ctx,
712				 struct asn1_data *data,
713				 struct ldap_Result *result)
714{
715	asn1_read_enumerated(data, &result->resultcode);
716	asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
717	asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
718	if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
719		asn1_start_tag(data, ASN1_CONTEXT(3));
720		asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
721		asn1_end_tag(data);
722	} else {
723		result->referral = NULL;
724	}
725}
726
727static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
728{
729
730	chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);
731	if (chunks == NULL) {
732		return NULL;
733	}
734
735	chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);
736	if (chunks[chunk_num] == NULL) {
737		return NULL;
738	}
739
740	chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);
741	if (chunks[chunk_num]->data == NULL) {
742		return NULL;
743	}
744	chunks[chunk_num]->length = strlen(value);
745
746	chunks[chunk_num + 1] = '\0';
747
748	return chunks;
749}
750
751
752/*
753  parse the ASN.1 formatted search string into a ldb_parse_tree
754*/
755static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
756						      struct asn1_data *data)
757{
758	uint8_t filter_tag;
759	struct ldb_parse_tree *ret;
760
761	if (!asn1_peek_uint8(data, &filter_tag)) {
762		return NULL;
763	}
764
765	filter_tag &= 0x1f;	/* strip off the asn1 stuff */
766
767	ret = talloc(mem_ctx, struct ldb_parse_tree);
768	if (ret == NULL) return NULL;
769
770	switch(filter_tag) {
771	case 0:
772	case 1:
773		/* AND or OR of one or more filters */
774		ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;
775		ret->u.list.num_elements = 0;
776		ret->u.list.elements = NULL;
777
778		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
779			goto failed;
780		}
781
782		while (asn1_tag_remaining(data) > 0) {
783			struct ldb_parse_tree *subtree;
784			subtree = ldap_decode_filter_tree(ret, data);
785			if (subtree == NULL) {
786				goto failed;
787			}
788			ret->u.list.elements =
789				talloc_realloc(ret, ret->u.list.elements,
790					       struct ldb_parse_tree *,
791					       ret->u.list.num_elements+1);
792			if (ret->u.list.elements == NULL) {
793				goto failed;
794			}
795			talloc_steal(ret->u.list.elements, subtree);
796			ret->u.list.elements[ret->u.list.num_elements] = subtree;
797			ret->u.list.num_elements++;
798		}
799		if (!asn1_end_tag(data)) {
800			goto failed;
801		}
802		break;
803
804	case 2:
805		/* 'not' operation */
806		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
807			goto failed;
808		}
809
810		ret->operation = LDB_OP_NOT;
811		ret->u.isnot.child = ldap_decode_filter_tree(ret, data);
812		if (ret->u.isnot.child == NULL) {
813			goto failed;
814		}
815		if (!asn1_end_tag(data)) {
816			goto failed;
817		}
818		break;
819
820	case 3: {
821		/* equalityMatch */
822		const char *attrib;
823		DATA_BLOB value;
824
825		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
826		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
827		asn1_read_OctetString(data, mem_ctx, &value);
828		asn1_end_tag(data);
829		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
830			goto failed;
831		}
832
833		ret->operation = LDB_OP_EQUALITY;
834		ret->u.equality.attr = talloc_steal(ret, attrib);
835		ret->u.equality.value.data = talloc_steal(ret, value.data);
836		ret->u.equality.value.length = value.length;
837		break;
838	}
839	case 4: {
840		/* substrings */
841		DATA_BLOB attr;
842		uint8_t subs_tag;
843		char *value;
844		int chunk_num = 0;
845
846		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
847			goto failed;
848		}
849		if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
850			goto failed;
851		}
852
853		ret->operation = LDB_OP_SUBSTRING;
854		ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);
855		ret->u.substring.chunks = NULL;
856		ret->u.substring.start_with_wildcard = 1;
857		ret->u.substring.end_with_wildcard = 1;
858
859		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
860			goto failed;
861		}
862
863		while (asn1_tag_remaining(data)) {
864			asn1_peek_uint8(data, &subs_tag);
865			subs_tag &= 0x1f;	/* strip off the asn1 stuff */
866			if (subs_tag > 2) goto failed;
867
868			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
869			asn1_read_LDAPString(data, mem_ctx, &value);
870			asn1_end_tag(data);
871
872			switch (subs_tag) {
873			case 0:
874				if (ret->u.substring.chunks != NULL) {
875					/* initial value found in the middle */
876					goto failed;
877				}
878
879				ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);
880				if (ret->u.substring.chunks == NULL) {
881					goto failed;
882				}
883
884				ret->u.substring.start_with_wildcard = 0;
885				chunk_num = 1;
886				break;
887
888			case 1:
889				if (ret->u.substring.end_with_wildcard == 0) {
890					/* "any" value found after a "final" value */
891					goto failed;
892				}
893
894				ret->u.substring.chunks = ldap_decode_substring(ret,
895										ret->u.substring.chunks,
896										chunk_num,
897										value);
898				if (ret->u.substring.chunks == NULL) {
899					goto failed;
900				}
901
902				chunk_num++;
903				break;
904
905			case 2:
906				ret->u.substring.chunks = ldap_decode_substring(ret,
907										ret->u.substring.chunks,
908										chunk_num,
909										value);
910				if (ret->u.substring.chunks == NULL) {
911					goto failed;
912				}
913
914				ret->u.substring.end_with_wildcard = 0;
915				break;
916
917			default:
918				goto failed;
919			}
920
921		}
922
923		if (!asn1_end_tag(data)) { /* SEQUENCE */
924			goto failed;
925		}
926
927		if (!asn1_end_tag(data)) {
928			goto failed;
929		}
930		break;
931	}
932	case 5: {
933		/* greaterOrEqual */
934		const char *attrib;
935		DATA_BLOB value;
936
937		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
938		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
939		asn1_read_OctetString(data, mem_ctx, &value);
940		asn1_end_tag(data);
941		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
942			goto failed;
943		}
944
945		ret->operation = LDB_OP_GREATER;
946		ret->u.comparison.attr = talloc_steal(ret, attrib);
947		ret->u.comparison.value.data = talloc_steal(ret, value.data);
948		ret->u.comparison.value.length = value.length;
949		break;
950	}
951	case 6: {
952		/* lessOrEqual */
953		const char *attrib;
954		DATA_BLOB value;
955
956		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
957		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
958		asn1_read_OctetString(data, mem_ctx, &value);
959		asn1_end_tag(data);
960		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
961			goto failed;
962		}
963
964		ret->operation = LDB_OP_LESS;
965		ret->u.comparison.attr = talloc_steal(ret, attrib);
966		ret->u.comparison.value.data = talloc_steal(ret, value.data);
967		ret->u.comparison.value.length = value.length;
968		break;
969	}
970	case 7: {
971		/* Normal presence, "attribute=*" */
972		char *attr;
973
974		if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {
975			goto failed;
976		}
977		if (!asn1_read_LDAPString(data, ret, &attr)) {
978			goto failed;
979		}
980
981		ret->operation = LDB_OP_PRESENT;
982		ret->u.present.attr = talloc_steal(ret, attr);
983
984		if (!asn1_end_tag(data)) {
985			goto failed;
986		}
987		break;
988	}
989	case 8: {
990		/* approx */
991		const char *attrib;
992		DATA_BLOB value;
993
994		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
995		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
996		asn1_read_OctetString(data, mem_ctx, &value);
997		asn1_end_tag(data);
998		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
999			goto failed;
1000		}
1001
1002		ret->operation = LDB_OP_APPROX;
1003		ret->u.comparison.attr = talloc_steal(ret, attrib);
1004		ret->u.comparison.value.data = talloc_steal(ret, value.data);
1005		ret->u.comparison.value.length = value.length;
1006		break;
1007	}
1008	case 9: {
1009		char *oid = NULL, *attr = NULL, *value;
1010		uint8_t dnAttributes;
1011		/* an extended search */
1012		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {
1013			goto failed;
1014		}
1015
1016		/* FIXME: read carefully rfc2251.txt there are a number of 'MUST's
1017		   we need to check we properly implement --SSS */
1018		/* either oid or type must be defined */
1019		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
1020			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
1021			asn1_read_LDAPString(data, ret, &oid);
1022			asn1_end_tag(data);
1023		}
1024		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) {	/* optional  */
1025			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
1026			asn1_read_LDAPString(data, ret, &attr);
1027			asn1_end_tag(data);
1028		}
1029		asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
1030		asn1_read_LDAPString(data, ret, &value);
1031		asn1_end_tag(data);
1032		/* dnAttributes is marked as BOOLEAN DEFAULT FALSE
1033		   it is not marked as OPTIONAL but openldap tools
1034		   do not set this unless it is to be set as TRUE
1035		   NOTE: openldap tools do not work with AD as it
1036		   seems that AD always requires the dnAttributes
1037		   boolean value to be set */
1038		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
1039			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
1040			asn1_read_uint8(data, &dnAttributes);
1041			asn1_end_tag(data);
1042		} else {
1043			dnAttributes = 0;
1044		}
1045		if ((oid == NULL && attr == NULL) || (value == NULL)) {
1046			goto failed;
1047		}
1048
1049		if (oid) {
1050			ret->operation               = LDB_OP_EXTENDED;
1051
1052			/* From the RFC2251: If the type field is
1053			   absent and matchingRule is present, the matchValue is compared
1054			   against all attributes in an entry which support that matchingRule
1055			*/
1056			if (attr) {
1057				ret->u.extended.attr = talloc_steal(ret, attr);
1058			} else {
1059				ret->u.extended.attr = talloc_strdup(ret, "*");
1060			}
1061			ret->u.extended.rule_id      = talloc_steal(ret, oid);
1062			ret->u.extended.value.data   = (uint8_t *)talloc_steal(ret, value);
1063			ret->u.extended.value.length = strlen(value);
1064			ret->u.extended.dnAttributes = dnAttributes;
1065		} else {
1066			ret->operation               = LDB_OP_EQUALITY;
1067			ret->u.equality.attr         = talloc_steal(ret, attr);
1068			ret->u.equality.value.data   = (uint8_t *)talloc_steal(ret, value);
1069			ret->u.equality.value.length = strlen(value);
1070		}
1071		if (!asn1_end_tag(data)) {
1072			goto failed;
1073		}
1074		break;
1075	}
1076
1077	default:
1078		goto failed;
1079	}
1080
1081	return ret;
1082
1083failed:
1084	talloc_free(ret);
1085	return NULL;
1086}
1087
1088/* Decode a single LDAP attribute, possibly containing multiple values */
1089static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1090			       struct ldb_message_element *attrib)
1091{
1092	asn1_start_tag(data, ASN1_SEQUENCE(0));
1093	asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
1094	asn1_start_tag(data, ASN1_SET);
1095	while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
1096		DATA_BLOB blob;
1097		asn1_read_OctetString(data, mem_ctx, &blob);
1098		add_value_to_attrib(mem_ctx, &blob, attrib);
1099	}
1100	asn1_end_tag(data);
1101	asn1_end_tag(data);
1102
1103}
1104
1105/* Decode a set of LDAP attributes, as found in the dereference control */
1106void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1107			      struct ldb_message_element **attributes,
1108			      int *num_attributes)
1109{
1110	while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1111		struct ldb_message_element attrib;
1112		ZERO_STRUCT(attrib);
1113		ldap_decode_attrib(mem_ctx, data, &attrib);
1114		add_attrib_to_array_talloc(mem_ctx, &attrib,
1115					   attributes, num_attributes);
1116	}
1117}
1118
1119/* Decode a set of LDAP attributes, as found in a search entry */
1120static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
1121				struct ldb_message_element **attributes,
1122				int *num_attributes)
1123{
1124	asn1_start_tag(data, ASN1_SEQUENCE(0));
1125	ldap_decode_attribs_bare(mem_ctx, data,
1126				 attributes, num_attributes);
1127	asn1_end_tag(data);
1128}
1129
1130/* This routine returns LDAP status codes */
1131
1132_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
1133			      const struct ldap_control_handler *control_handlers,
1134			      struct ldap_message *msg)
1135{
1136	uint8_t tag;
1137
1138	asn1_start_tag(data, ASN1_SEQUENCE(0));
1139	asn1_read_Integer(data, &msg->messageid);
1140
1141	if (!asn1_peek_uint8(data, &tag))
1142		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1143
1144	switch(tag) {
1145
1146	case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
1147		struct ldap_BindRequest *r = &msg->r.BindRequest;
1148		msg->type = LDAP_TAG_BindRequest;
1149		asn1_start_tag(data, tag);
1150		asn1_read_Integer(data, &r->version);
1151		asn1_read_OctetString_talloc(msg, data, &r->dn);
1152		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
1153			int pwlen;
1154			r->creds.password = "";
1155			r->mechanism = LDAP_AUTH_MECH_SIMPLE;
1156			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1157			pwlen = asn1_tag_remaining(data);
1158			if (pwlen == -1) {
1159				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1160			}
1161			if (pwlen != 0) {
1162				char *pw = talloc_array(msg, char, pwlen+1);
1163				if (!pw) {
1164					return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1165				}
1166				asn1_read(data, pw, pwlen);
1167				pw[pwlen] = '\0';
1168				r->creds.password = pw;
1169			}
1170			asn1_end_tag(data);
1171		} else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
1172			asn1_start_tag(data, ASN1_CONTEXT(3));
1173			r->mechanism = LDAP_AUTH_MECH_SASL;
1174			asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
1175			if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
1176				DATA_BLOB tmp_blob = data_blob(NULL, 0);
1177				asn1_read_OctetString(data, msg, &tmp_blob);
1178				r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
1179				if (!r->creds.SASL.secblob) {
1180					return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1181				}
1182				*r->creds.SASL.secblob = data_blob_talloc(r->creds.SASL.secblob,
1183									  tmp_blob.data, tmp_blob.length);
1184				data_blob_free(&tmp_blob);
1185			} else {
1186				r->creds.SASL.secblob = NULL;
1187			}
1188			asn1_end_tag(data);
1189		} else {
1190			/* Neither Simple nor SASL bind */
1191			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1192		}
1193		asn1_end_tag(data);
1194		break;
1195	}
1196
1197	case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
1198		struct ldap_BindResponse *r = &msg->r.BindResponse;
1199		msg->type = LDAP_TAG_BindResponse;
1200		asn1_start_tag(data, tag);
1201		ldap_decode_response(msg, data, &r->response);
1202		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
1203			DATA_BLOB tmp_blob = data_blob(NULL, 0);
1204			asn1_read_ContextSimple(data, 7, &tmp_blob);
1205			r->SASL.secblob = talloc(msg, DATA_BLOB);
1206			if (!r->SASL.secblob) {
1207				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1208			}
1209			*r->SASL.secblob = data_blob_talloc(r->SASL.secblob,
1210							    tmp_blob.data, tmp_blob.length);
1211			data_blob_free(&tmp_blob);
1212		} else {
1213			r->SASL.secblob = NULL;
1214		}
1215		asn1_end_tag(data);
1216		break;
1217	}
1218
1219	case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
1220		msg->type = LDAP_TAG_UnbindRequest;
1221		asn1_start_tag(data, tag);
1222		asn1_end_tag(data);
1223		break;
1224	}
1225
1226	case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
1227		struct ldap_SearchRequest *r = &msg->r.SearchRequest;
1228		int sizelimit, timelimit;
1229		const char **attrs = NULL;
1230		msg->type = LDAP_TAG_SearchRequest;
1231		asn1_start_tag(data, tag);
1232		asn1_read_OctetString_talloc(msg, data, &r->basedn);
1233		asn1_read_enumerated(data, (int *)(void *)&(r->scope));
1234		asn1_read_enumerated(data, (int *)(void *)&(r->deref));
1235		asn1_read_Integer(data, &sizelimit);
1236		r->sizelimit = sizelimit;
1237		asn1_read_Integer(data, &timelimit);
1238		r->timelimit = timelimit;
1239		asn1_read_BOOLEAN(data, &r->attributesonly);
1240
1241		r->tree = ldap_decode_filter_tree(msg, data);
1242		if (r->tree == NULL) {
1243			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1244		}
1245
1246		asn1_start_tag(data, ASN1_SEQUENCE(0));
1247
1248		r->num_attributes = 0;
1249		r->attributes = NULL;
1250
1251		while (asn1_tag_remaining(data) > 0) {
1252
1253			const char *attr;
1254			if (!asn1_read_OctetString_talloc(msg, data,
1255							  &attr))
1256				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1257			if (!add_string_to_array(msg, attr,
1258						 &attrs,
1259						 &r->num_attributes))
1260				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1261		}
1262		r->attributes = attrs;
1263
1264		asn1_end_tag(data);
1265		asn1_end_tag(data);
1266		break;
1267	}
1268
1269	case ASN1_APPLICATION(LDAP_TAG_SearchResultEntry): {
1270		struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
1271		msg->type = LDAP_TAG_SearchResultEntry;
1272		r->attributes = NULL;
1273		r->num_attributes = 0;
1274		asn1_start_tag(data, tag);
1275		asn1_read_OctetString_talloc(msg, data, &r->dn);
1276		ldap_decode_attribs(msg, data, &r->attributes,
1277				    &r->num_attributes);
1278		asn1_end_tag(data);
1279		break;
1280	}
1281
1282	case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
1283		struct ldap_Result *r = &msg->r.SearchResultDone;
1284		msg->type = LDAP_TAG_SearchResultDone;
1285		asn1_start_tag(data, tag);
1286		ldap_decode_response(msg, data, r);
1287		asn1_end_tag(data);
1288		break;
1289	}
1290
1291	case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
1292		struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
1293		msg->type = LDAP_TAG_SearchResultReference;
1294		asn1_start_tag(data, tag);
1295		asn1_read_OctetString_talloc(msg, data, &r->referral);
1296		asn1_end_tag(data);
1297		break;
1298	}
1299
1300	case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
1301		struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
1302		msg->type = LDAP_TAG_ModifyRequest;
1303		asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
1304		asn1_read_OctetString_talloc(msg, data, &r->dn);
1305		asn1_start_tag(data, ASN1_SEQUENCE(0));
1306
1307		r->num_mods = 0;
1308		r->mods = NULL;
1309
1310		while (asn1_tag_remaining(data) > 0) {
1311			struct ldap_mod mod;
1312			int v;
1313			ZERO_STRUCT(mod);
1314			asn1_start_tag(data, ASN1_SEQUENCE(0));
1315			asn1_read_enumerated(data, &v);
1316			mod.type = v;
1317			ldap_decode_attrib(msg, data, &mod.attrib);
1318			asn1_end_tag(data);
1319			if (!add_mod_to_array_talloc(msg, &mod,
1320						     &r->mods, &r->num_mods)) {
1321				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1322			}
1323		}
1324
1325		asn1_end_tag(data);
1326		asn1_end_tag(data);
1327		break;
1328	}
1329
1330	case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
1331		struct ldap_Result *r = &msg->r.ModifyResponse;
1332		msg->type = LDAP_TAG_ModifyResponse;
1333		asn1_start_tag(data, tag);
1334		ldap_decode_response(msg, data, r);
1335		asn1_end_tag(data);
1336		break;
1337	}
1338
1339	case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
1340		struct ldap_AddRequest *r = &msg->r.AddRequest;
1341		msg->type = LDAP_TAG_AddRequest;
1342		asn1_start_tag(data, tag);
1343		asn1_read_OctetString_talloc(msg, data, &r->dn);
1344
1345		r->attributes = NULL;
1346		r->num_attributes = 0;
1347		ldap_decode_attribs(msg, data, &r->attributes,
1348				    &r->num_attributes);
1349
1350		asn1_end_tag(data);
1351		break;
1352	}
1353
1354	case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
1355		struct ldap_Result *r = &msg->r.AddResponse;
1356		msg->type = LDAP_TAG_AddResponse;
1357		asn1_start_tag(data, tag);
1358		ldap_decode_response(msg, data, r);
1359		asn1_end_tag(data);
1360		break;
1361	}
1362
1363	case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
1364		struct ldap_DelRequest *r = &msg->r.DelRequest;
1365		int len;
1366		char *dn;
1367		msg->type = LDAP_TAG_DelRequest;
1368		asn1_start_tag(data,
1369			       ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
1370		len = asn1_tag_remaining(data);
1371		if (len == -1) {
1372			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1373		}
1374		dn = talloc_array(msg, char, len+1);
1375		if (dn == NULL)
1376			break;
1377		asn1_read(data, dn, len);
1378		dn[len] = '\0';
1379		r->dn = dn;
1380		asn1_end_tag(data);
1381		break;
1382	}
1383
1384	case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
1385		struct ldap_Result *r = &msg->r.DelResponse;
1386		msg->type = LDAP_TAG_DelResponse;
1387		asn1_start_tag(data, tag);
1388		ldap_decode_response(msg, data, r);
1389		asn1_end_tag(data);
1390		break;
1391	}
1392
1393	case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
1394		struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
1395		msg->type = LDAP_TAG_ModifyDNRequest;
1396		asn1_start_tag(data,
1397			       ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
1398		asn1_read_OctetString_talloc(msg, data, &r->dn);
1399		asn1_read_OctetString_talloc(msg, data, &r->newrdn);
1400		asn1_read_BOOLEAN(data, &r->deleteolddn);
1401		r->newsuperior = NULL;
1402		if (asn1_tag_remaining(data) > 0) {
1403			int len;
1404			char *newsup;
1405			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
1406			len = asn1_tag_remaining(data);
1407			if (len == -1) {
1408				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1409			}
1410			newsup = talloc_array(msg, char, len+1);
1411			if (newsup == NULL) {
1412				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1413			}
1414			asn1_read(data, newsup, len);
1415			newsup[len] = '\0';
1416			r->newsuperior = newsup;
1417			asn1_end_tag(data);
1418		}
1419		asn1_end_tag(data);
1420		break;
1421	}
1422
1423	case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
1424		struct ldap_Result *r = &msg->r.ModifyDNResponse;
1425		msg->type = LDAP_TAG_ModifyDNResponse;
1426		asn1_start_tag(data, tag);
1427		ldap_decode_response(msg, data, r);
1428		asn1_end_tag(data);
1429		break;
1430	}
1431
1432	case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
1433		struct ldap_CompareRequest *r = &msg->r.CompareRequest;
1434		msg->type = LDAP_TAG_CompareRequest;
1435		asn1_start_tag(data,
1436			       ASN1_APPLICATION(LDAP_TAG_CompareRequest));
1437		asn1_read_OctetString_talloc(msg, data, &r->dn);
1438		asn1_start_tag(data, ASN1_SEQUENCE(0));
1439		asn1_read_OctetString_talloc(msg, data, &r->attribute);
1440		asn1_read_OctetString(data, msg, &r->value);
1441		if (r->value.data) {
1442			talloc_steal(msg, r->value.data);
1443		}
1444		asn1_end_tag(data);
1445		asn1_end_tag(data);
1446		break;
1447	}
1448
1449	case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
1450		struct ldap_Result *r = &msg->r.CompareResponse;
1451		msg->type = LDAP_TAG_CompareResponse;
1452		asn1_start_tag(data, tag);
1453		ldap_decode_response(msg, data, r);
1454		asn1_end_tag(data);
1455		break;
1456	}
1457
1458	case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
1459		struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
1460		msg->type = LDAP_TAG_AbandonRequest;
1461		asn1_start_tag(data, tag);
1462		asn1_read_implicit_Integer(data, &r->messageid);
1463		asn1_end_tag(data);
1464		break;
1465	}
1466
1467	case ASN1_APPLICATION(LDAP_TAG_ExtendedRequest): {
1468		struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
1469		DATA_BLOB tmp_blob = data_blob(NULL, 0);
1470
1471		msg->type = LDAP_TAG_ExtendedRequest;
1472		asn1_start_tag(data,tag);
1473		if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
1474			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1475		}
1476		r->oid = blob2string_talloc(msg, tmp_blob);
1477		data_blob_free(&tmp_blob);
1478		if (!r->oid) {
1479			return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1480		}
1481
1482		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
1483			asn1_read_ContextSimple(data, 1, &tmp_blob);
1484			r->value = talloc(msg, DATA_BLOB);
1485			if (!r->value) {
1486				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1487			}
1488			*r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1489			data_blob_free(&tmp_blob);
1490		} else {
1491			r->value = NULL;
1492		}
1493
1494		asn1_end_tag(data);
1495		break;
1496	}
1497
1498	case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
1499		struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
1500		DATA_BLOB tmp_blob = data_blob(NULL, 0);
1501
1502		msg->type = LDAP_TAG_ExtendedResponse;
1503		asn1_start_tag(data, tag);
1504		ldap_decode_response(msg, data, &r->response);
1505
1506		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
1507			asn1_read_ContextSimple(data, 1, &tmp_blob);
1508			r->oid = blob2string_talloc(msg, tmp_blob);
1509			data_blob_free(&tmp_blob);
1510			if (!r->oid) {
1511				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1512			}
1513		} else {
1514			r->oid = NULL;
1515		}
1516
1517		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
1518			asn1_read_ContextSimple(data, 1, &tmp_blob);
1519			r->value = talloc(msg, DATA_BLOB);
1520			if (!r->value) {
1521				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1522			}
1523			*r->value = data_blob_talloc(r->value, tmp_blob.data, tmp_blob.length);
1524			data_blob_free(&tmp_blob);
1525		} else {
1526			r->value = NULL;
1527		}
1528
1529		asn1_end_tag(data);
1530		break;
1531	}
1532	default:
1533		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1534	}
1535
1536	msg->controls = NULL;
1537	msg->controls_decoded = NULL;
1538
1539	if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1540		int i = 0;
1541		struct ldb_control **ctrl = NULL;
1542		bool *decoded = NULL;
1543
1544		asn1_start_tag(data, ASN1_CONTEXT(0));
1545
1546		while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
1547			DATA_BLOB value;
1548			/* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
1549
1550			ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
1551			if (!ctrl) {
1552				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1553			}
1554
1555			decoded = talloc_realloc(msg, decoded, bool, i+1);
1556			if (!decoded) {
1557				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1558			}
1559
1560			ctrl[i] = talloc(ctrl, struct ldb_control);
1561			if (!ctrl[i]) {
1562				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
1563			}
1564
1565			if (!ldap_decode_control_wrapper(ctrl, data, ctrl[i], &value)) {
1566				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1567			}
1568
1569			if (!ldap_decode_control_value(ctrl, value,
1570						       control_handlers,
1571						       ctrl[i])) {
1572				if (ctrl[i]->critical) {
1573					ctrl[i]->data = NULL;
1574					decoded[i] = false;
1575					i++;
1576				} else {
1577					talloc_free(ctrl[i]);
1578					ctrl[i] = NULL;
1579				}
1580			} else {
1581				decoded[i] = true;
1582				i++;
1583			}
1584		}
1585
1586		if (ctrl != NULL) {
1587			ctrl[i] = NULL;
1588		}
1589
1590		msg->controls = ctrl;
1591		msg->controls_decoded = decoded;
1592
1593		asn1_end_tag(data);
1594	}
1595
1596	asn1_end_tag(data);
1597	if ((data->has_error) || (data->nesting != NULL)) {
1598		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
1599	}
1600	return NT_STATUS_OK;
1601}
1602
1603
1604/*
1605  return NT_STATUS_OK if a blob has enough bytes in it to be a full
1606  ldap packet. Set packet_size if true.
1607*/
1608NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
1609{
1610	return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
1611}
1612