• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/libcli/ldap/
1/*
2   Unix SMB/CIFS mplementation.
3   LDAP protocol helper functions for SAMBA
4
5   Copyright (C) Simo Sorce 2005
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22#include "includes.h"
23#include "../lib/util/asn1.h"
24#include "libcli/ldap/ldap.h"
25#include "lib/ldb/include/ldb.h"
26#include "libcli/ldap/ldap_proto.h"
27#include "dsdb/samdb/samdb.h"
28
29static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
30{
31	void **out = (void **)_out;
32	DATA_BLOB attr;
33	struct asn1_data *data = asn1_init(mem_ctx);
34	struct ldb_sort_resp_control *lsrc;
35
36	if (!data) return false;
37
38	if (!asn1_load(data, in)) {
39		return false;
40	}
41
42	lsrc = talloc(mem_ctx, struct ldb_sort_resp_control);
43	if (!lsrc) {
44		return false;
45	}
46
47	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
48		return false;
49	}
50
51	if (!asn1_read_enumerated(data, &(lsrc->result))) {
52		return false;
53	}
54
55	lsrc->attr_desc = NULL;
56	if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
57		if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
58			return false;
59		}
60		lsrc->attr_desc = talloc_strndup(lsrc, (const char *)attr.data, attr.length);
61		if (!lsrc->attr_desc) {
62			return false;
63		}
64	}
65
66	if (!asn1_end_tag(data)) {
67		return false;
68	}
69
70	*out = lsrc;
71
72	return true;
73}
74
75static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
76{
77	void **out = (void **)_out;
78	DATA_BLOB attr;
79	DATA_BLOB rule;
80	struct asn1_data *data = asn1_init(mem_ctx);
81	struct ldb_server_sort_control **lssc;
82	int num;
83
84	if (!data) return false;
85
86	if (!asn1_load(data, in)) {
87		return false;
88	}
89
90	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
91		return false;
92	}
93
94	lssc = NULL;
95
96	for (num = 0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); num++) {
97		lssc = talloc_realloc(mem_ctx, lssc, struct ldb_server_sort_control *, num + 2);
98		if (!lssc) {
99			return false;
100		}
101		lssc[num] = talloc_zero(lssc, struct ldb_server_sort_control);
102		if (!lssc[num]) {
103			return false;
104		}
105
106		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
107			return false;
108		}
109
110		if (!asn1_read_OctetString(data, mem_ctx, &attr)) {
111			return false;
112		}
113
114		lssc[num]->attributeName = talloc_strndup(lssc[num], (const char *)attr.data, attr.length);
115		if (!lssc [num]->attributeName) {
116			return false;
117		}
118
119		if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
120			if (!asn1_read_OctetString(data, mem_ctx, &rule)) {
121				return false;
122			}
123			lssc[num]->orderingRule = talloc_strndup(lssc[num], (const char *)rule.data, rule.length);
124			if (!lssc[num]->orderingRule) {
125				return false;
126			}
127		}
128
129		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
130			bool reverse;
131			if (!asn1_read_BOOLEAN_context(data, &reverse, 1)) {
132			return false;
133			}
134			lssc[num]->reverse = reverse;
135		}
136
137		if (!asn1_end_tag(data)) {
138			return false;
139		}
140	}
141
142	if (lssc != NULL) {
143		lssc[num] = NULL;
144	}
145
146	if (!asn1_end_tag(data)) {
147		return false;
148	}
149
150	*out = lssc;
151
152	return true;
153}
154
155static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
156{
157	void **out = (void **)_out;
158	struct asn1_data *data;
159	struct ldb_extended_dn_control *ledc;
160
161	/* The content of this control is optional */
162	if (in.length == 0) {
163		*out = NULL;
164		return true;
165	}
166
167	data = asn1_init(mem_ctx);
168	if (!data) return false;
169
170	if (!asn1_load(data, in)) {
171		return false;
172	}
173
174	ledc = talloc(mem_ctx, struct ldb_extended_dn_control);
175	if (!ledc) {
176		return false;
177	}
178
179	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
180		return false;
181	}
182
183	if (!asn1_read_Integer(data, &(ledc->type))) {
184		return false;
185	}
186
187	if (!asn1_end_tag(data)) {
188		return false;
189	}
190
191	*out = ledc;
192
193	return true;
194}
195
196static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
197{
198	void **out = (void **)_out;
199	struct asn1_data *data = asn1_init(mem_ctx);
200	struct ldb_sd_flags_control *lsdfc;
201
202	if (!data) return false;
203
204	if (!asn1_load(data, in)) {
205		return false;
206	}
207
208	lsdfc = talloc(mem_ctx, struct ldb_sd_flags_control);
209	if (!lsdfc) {
210		return false;
211	}
212
213	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
214		return false;
215	}
216
217	if (!asn1_read_Integer(data, &(lsdfc->secinfo_flags))) {
218		return false;
219	}
220
221	if (!asn1_end_tag(data)) {
222		return false;
223	}
224
225	*out = lsdfc;
226
227	return true;
228}
229
230static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
231{
232	void **out = (void **)_out;
233	struct asn1_data *data = asn1_init(mem_ctx);
234	struct ldb_search_options_control *lsoc;
235
236	if (!data) return false;
237
238	if (!asn1_load(data, in)) {
239		return false;
240	}
241
242	lsoc = talloc(mem_ctx, struct ldb_search_options_control);
243	if (!lsoc) {
244		return false;
245	}
246
247	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
248		return false;
249	}
250
251	if (!asn1_read_Integer(data, &(lsoc->search_options))) {
252		return false;
253	}
254
255	if (!asn1_end_tag(data)) {
256		return false;
257	}
258
259	*out = lsoc;
260
261	return true;
262}
263
264static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
265{
266	void **out = (void **)_out;
267	DATA_BLOB cookie;
268	struct asn1_data *data = asn1_init(mem_ctx);
269	struct ldb_paged_control *lprc;
270
271	if (!data) return false;
272
273	if (!asn1_load(data, in)) {
274		return false;
275	}
276
277	lprc = talloc(mem_ctx, struct ldb_paged_control);
278	if (!lprc) {
279		return false;
280	}
281
282	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
283		return false;
284	}
285
286	if (!asn1_read_Integer(data, &(lprc->size))) {
287		return false;
288	}
289
290	if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
291		return false;
292	}
293	lprc->cookie_len = cookie.length;
294	if (lprc->cookie_len) {
295		lprc->cookie = talloc_memdup(lprc, cookie.data, cookie.length);
296
297		if (!(lprc->cookie)) {
298			return false;
299		}
300	} else {
301		lprc->cookie = NULL;
302	}
303
304	if (!asn1_end_tag(data)) {
305		return false;
306	}
307
308	*out = lprc;
309
310	return true;
311}
312
313static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
314{
315	void **out = (void **)_out;
316	DATA_BLOB cookie;
317	struct asn1_data *data = asn1_init(mem_ctx);
318	struct ldb_dirsync_control *ldc;
319
320	if (!data) return false;
321
322	if (!asn1_load(data, in)) {
323		return false;
324	}
325
326	ldc = talloc(mem_ctx, struct ldb_dirsync_control);
327	if (!ldc) {
328		return false;
329	}
330
331	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
332		return false;
333	}
334
335	if (!asn1_read_Integer(data, &(ldc->flags))) {
336		return false;
337	}
338
339	if (!asn1_read_Integer(data, &(ldc->max_attributes))) {
340		return false;
341	}
342
343	if (!asn1_read_OctetString(data, mem_ctx, &cookie)) {
344		return false;
345	}
346	ldc->cookie_len = cookie.length;
347	if (ldc->cookie_len) {
348		ldc->cookie = talloc_memdup(ldc, cookie.data, cookie.length);
349
350		if (!(ldc->cookie)) {
351			return false;
352		}
353	} else {
354		ldc->cookie = NULL;
355	}
356
357	if (!asn1_end_tag(data)) {
358		return false;
359	}
360
361	*out = ldc;
362
363	return true;
364}
365
366/* seem that this controls has 2 forms one in case it is used with
367 * a Search Request and another when used ina Search Response
368 */
369static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
370{
371	void **out = (void **)_out;
372	DATA_BLOB source_attribute;
373	struct asn1_data *data = asn1_init(mem_ctx);
374	struct ldb_asq_control *lac;
375
376	if (!data) return false;
377
378	if (!asn1_load(data, in)) {
379		return false;
380	}
381
382	lac = talloc(mem_ctx, struct ldb_asq_control);
383	if (!lac) {
384		return false;
385	}
386
387	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
388		return false;
389	}
390
391	if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
392
393		if (!asn1_read_OctetString(data, mem_ctx, &source_attribute)) {
394			return false;
395		}
396		lac->src_attr_len = source_attribute.length;
397		if (lac->src_attr_len) {
398			lac->source_attribute = talloc_strndup(lac, (const char *)source_attribute.data, source_attribute.length);
399
400			if (!(lac->source_attribute)) {
401				return false;
402			}
403		} else {
404			lac->source_attribute = NULL;
405		}
406
407		lac->request = 1;
408
409	} else if (asn1_peek_tag(data, ASN1_ENUMERATED)) {
410
411		if (!asn1_read_enumerated(data, &(lac->result))) {
412			return false;
413		}
414
415		lac->request = 0;
416
417	} else {
418		return false;
419	}
420
421	if (!asn1_end_tag(data)) {
422		return false;
423	}
424
425	*out = lac;
426
427	return true;
428}
429
430static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
431{
432	if (in.length != 0) {
433		return false;
434	}
435
436	return true;
437}
438
439static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
440{
441	if (in.length != 0) {
442		return false;
443	}
444
445	return true;
446}
447
448static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
449{
450	if (in.length != 0) {
451		return false;
452	}
453
454	return true;
455}
456
457static bool decode_show_recycled_request(void *mem_ctx, DATA_BLOB in, void *_out)
458{
459	if (in.length != 0) {
460		return false;
461	}
462
463	return true;
464}
465
466static bool decode_show_deactivated_link_request(void *mem_ctx, DATA_BLOB in, void *_out)
467{
468	if (in.length != 0) {
469		return false;
470	}
471
472	return true;
473}
474
475static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *_out)
476{
477	if (in.length != 0) {
478		return false;
479	}
480
481	return true;
482}
483
484static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void *_out)
485{
486	if (in.length != 0) {
487		return false;
488	}
489
490	return true;
491}
492
493static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
494{
495	void **out = (void **)_out;
496	DATA_BLOB assertion_value, context_id;
497	struct asn1_data *data = asn1_init(mem_ctx);
498	struct ldb_vlv_req_control *lvrc;
499
500	if (!data) return false;
501
502	if (!asn1_load(data, in)) {
503		return false;
504	}
505
506	lvrc = talloc(mem_ctx, struct ldb_vlv_req_control);
507	if (!lvrc) {
508		return false;
509	}
510
511	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
512		return false;
513	}
514
515	if (!asn1_read_Integer(data, &(lvrc->beforeCount))) {
516		return false;
517	}
518
519	if (!asn1_read_Integer(data, &(lvrc->afterCount))) {
520		return false;
521	}
522
523	if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
524
525		lvrc->type = 0;
526
527		if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
528			return false;
529		}
530
531		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
532			return false;
533		}
534
535		if (!asn1_read_Integer(data, &(lvrc->match.byOffset.offset))) {
536			return false;
537		}
538
539		if (!asn1_read_Integer(data, &(lvrc->match.byOffset.contentCount))) {
540			return false;
541		}
542
543		if (!asn1_end_tag(data)) { /*SEQUENCE*/
544			return false;
545		}
546
547		if (!asn1_end_tag(data)) { /*CONTEXT*/
548			return false;
549		}
550
551	} else {
552
553		lvrc->type = 1;
554
555		if (!asn1_start_tag(data, ASN1_CONTEXT(1))) {
556			return false;
557		}
558
559		if (!asn1_read_OctetString(data, mem_ctx, &assertion_value)) {
560			return false;
561		}
562		lvrc->match.gtOrEq.value_len = assertion_value.length;
563		if (lvrc->match.gtOrEq.value_len) {
564			lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length);
565
566			if (!(lvrc->match.gtOrEq.value)) {
567				return false;
568			}
569		} else {
570			lvrc->match.gtOrEq.value = NULL;
571		}
572
573		if (!asn1_end_tag(data)) { /*CONTEXT*/
574			return false;
575		}
576	}
577
578	if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
579		if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
580			return false;
581		}
582		lvrc->ctxid_len = context_id.length;
583		if (lvrc->ctxid_len) {
584			lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length);
585
586			if (!(lvrc->contextId)) {
587				return false;
588			}
589		} else {
590			lvrc->contextId = NULL;
591		}
592	} else {
593		lvrc->contextId = NULL;
594		lvrc->ctxid_len = 0;
595	}
596
597	if (!asn1_end_tag(data)) {
598		return false;
599	}
600
601	*out = lvrc;
602
603	return true;
604}
605
606static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
607{
608	void **out = (void **)_out;
609	DATA_BLOB context_id;
610	struct asn1_data *data = asn1_init(mem_ctx);
611	struct ldb_vlv_resp_control *lvrc;
612
613	if (!data) return false;
614
615	if (!asn1_load(data, in)) {
616		return false;
617	}
618
619	lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control);
620	if (!lvrc) {
621		return false;
622	}
623
624	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
625		return false;
626	}
627
628	if (!asn1_read_Integer(data, &(lvrc->targetPosition))) {
629		return false;
630	}
631
632	if (!asn1_read_Integer(data, &(lvrc->contentCount))) {
633		return false;
634	}
635
636	if (!asn1_read_enumerated(data, &(lvrc->vlv_result))) {
637		return false;
638	}
639
640	if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
641		if (!asn1_read_OctetString(data, mem_ctx, &context_id)) {
642			return false;
643		}
644		lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length);
645		if (!lvrc->contextId) {
646			return false;
647		}
648		lvrc->ctxid_len = context_id.length;
649	} else {
650		lvrc->contextId = NULL;
651		lvrc->ctxid_len = 0;
652	}
653
654	if (!asn1_end_tag(data)) {
655		return false;
656	}
657
658	*out = lvrc;
659
660	return true;
661}
662
663static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
664{
665	struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
666	struct asn1_data *data = asn1_init(mem_ctx);
667
668	if (!data) return false;
669
670	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
671		return false;
672	}
673
674	if (!asn1_write_enumerated(data, lsrc->result)) {
675		return false;
676	}
677
678	if (lsrc->attr_desc) {
679		if (!asn1_write_OctetString(data, lsrc->attr_desc, strlen(lsrc->attr_desc))) {
680			return false;
681		}
682	}
683
684	if (!asn1_pop_tag(data)) {
685		return false;
686	}
687
688	*out = data_blob_talloc(mem_ctx, data->data, data->length);
689	if (out->data == NULL) {
690		return false;
691	}
692	talloc_free(data);
693
694	return true;
695}
696
697static bool encode_server_sort_request(void *mem_ctx, void *in, DATA_BLOB *out)
698{
699	struct ldb_server_sort_control **lssc = talloc_get_type(in, struct ldb_server_sort_control *);
700	struct asn1_data *data = asn1_init(mem_ctx);
701	int num;
702
703	if (!data) return false;
704
705	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
706		return false;
707	}
708
709	/*
710	  RFC2891 section 1.1:
711	    SortKeyList ::= SEQUENCE OF SEQUENCE {
712	      attributeType   AttributeDescription,
713	      orderingRule    [0] MatchingRuleId OPTIONAL,
714	      reverseOrder    [1] BOOLEAN DEFAULT FALSE }
715	*/
716	for (num = 0; lssc[num]; num++) {
717		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
718			return false;
719		}
720
721		if (!asn1_write_OctetString(data, lssc[num]->attributeName, strlen(lssc[num]->attributeName))) {
722			return false;
723		}
724
725		if (lssc[num]->orderingRule) {
726			if (!asn1_write_OctetString(data, lssc[num]->orderingRule, strlen(lssc[num]->orderingRule))) {
727				return false;
728			}
729		}
730
731		if (lssc[num]->reverse) {
732			if (!asn1_write_BOOLEAN_context(data, lssc[num]->reverse, 1)) {
733				return false;
734			}
735		}
736
737		if (!asn1_pop_tag(data)) {
738			return false;
739		}
740	}
741
742	if (!asn1_pop_tag(data)) {
743		return false;
744	}
745
746	*out = data_blob_talloc(mem_ctx, data->data, data->length);
747	if (out->data == NULL) {
748		return false;
749	}
750	talloc_free(data);
751
752	return true;
753}
754
755static bool encode_extended_dn_request(void *mem_ctx, void *in, DATA_BLOB *out)
756{
757	struct ldb_extended_dn_control *ledc = talloc_get_type(in, struct ldb_extended_dn_control);
758	struct asn1_data *data;
759
760	if (!in) {
761		*out = data_blob(NULL, 0);
762		return true;
763	}
764
765	data = asn1_init(mem_ctx);
766
767	if (!data) return false;
768
769	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
770		return false;
771	}
772
773	if (!asn1_write_Integer(data, ledc->type)) {
774		return false;
775	}
776
777	if (!asn1_pop_tag(data)) {
778		return false;
779	}
780
781	*out = data_blob_talloc(mem_ctx, data->data, data->length);
782	if (out->data == NULL) {
783		return false;
784	}
785	talloc_free(data);
786
787	return true;
788}
789
790static bool encode_sd_flags_request(void *mem_ctx, void *in, DATA_BLOB *out)
791{
792	struct ldb_sd_flags_control *lsdfc = talloc_get_type(in, struct ldb_sd_flags_control);
793	struct asn1_data *data = asn1_init(mem_ctx);
794
795	if (!data) return false;
796
797	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
798		return false;
799	}
800
801	if (!asn1_write_Integer(data, lsdfc->secinfo_flags)) {
802		return false;
803	}
804
805	if (!asn1_pop_tag(data)) {
806		return false;
807	}
808
809	*out = data_blob_talloc(mem_ctx, data->data, data->length);
810	if (out->data == NULL) {
811		return false;
812	}
813	talloc_free(data);
814
815	return true;
816}
817
818static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *out)
819{
820	struct ldb_search_options_control *lsoc = talloc_get_type(in, struct ldb_search_options_control);
821	struct asn1_data *data = asn1_init(mem_ctx);
822
823	if (!data) return false;
824
825	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
826		return false;
827	}
828
829	if (!asn1_write_Integer(data, lsoc->search_options)) {
830		return false;
831	}
832
833	if (!asn1_pop_tag(data)) {
834		return false;
835	}
836
837	*out = data_blob_talloc(mem_ctx, data->data, data->length);
838	if (out->data == NULL) {
839		return false;
840	}
841	talloc_free(data);
842
843	return true;
844}
845
846static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out)
847{
848	struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control);
849	struct asn1_data *data = asn1_init(mem_ctx);
850
851	if (!data) return false;
852
853	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
854		return false;
855	}
856
857	if (!asn1_write_Integer(data, lprc->size)) {
858		return false;
859	}
860
861	if (!asn1_write_OctetString(data, lprc->cookie, lprc->cookie_len)) {
862		return false;
863	}
864
865	if (!asn1_pop_tag(data)) {
866		return false;
867	}
868
869	*out = data_blob_talloc(mem_ctx, data->data, data->length);
870	if (out->data == NULL) {
871		return false;
872	}
873	talloc_free(data);
874
875	return true;
876}
877
878/* seem that this controls has 2 forms one in case it is used with
879 * a Search Request and another when used ina Search Response
880 */
881static bool encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out)
882{
883	struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control);
884	struct asn1_data *data = asn1_init(mem_ctx);
885
886	if (!data) return false;
887
888	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
889		return false;
890	}
891
892	if (lac->request) {
893
894		if (!asn1_write_OctetString(data, lac->source_attribute, lac->src_attr_len)) {
895			return false;
896		}
897	} else {
898		if (!asn1_write_enumerated(data, lac->result)) {
899			return false;
900		}
901	}
902
903	if (!asn1_pop_tag(data)) {
904		return false;
905	}
906
907	*out = data_blob_talloc(mem_ctx, data->data, data->length);
908	if (out->data == NULL) {
909		return false;
910	}
911	talloc_free(data);
912
913	return true;
914}
915
916static bool encode_dirsync_request(void *mem_ctx, void *in, DATA_BLOB *out)
917{
918	struct ldb_dirsync_control *ldc = talloc_get_type(in, struct ldb_dirsync_control);
919	struct asn1_data *data = asn1_init(mem_ctx);
920
921	if (!data) return false;
922
923	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
924		return false;
925	}
926
927	if (!asn1_write_Integer(data, ldc->flags)) {
928		return false;
929	}
930
931	if (!asn1_write_Integer(data, ldc->max_attributes)) {
932		return false;
933	}
934
935	if (!asn1_write_OctetString(data, ldc->cookie, ldc->cookie_len)) {
936		return false;
937	}
938
939	if (!asn1_pop_tag(data)) {
940		return false;
941	}
942
943	*out = data_blob_talloc(mem_ctx, data->data, data->length);
944	if (out->data == NULL) {
945		return false;
946	}
947	talloc_free(data);
948
949	return true;
950}
951
952static bool encode_domain_scope_request(void *mem_ctx, void *in, DATA_BLOB *out)
953{
954	if (in) {
955		return false;
956	}
957
958	*out = data_blob(NULL, 0);
959	return true;
960}
961
962static bool encode_notification_request(void *mem_ctx, void *in, DATA_BLOB *out)
963{
964	if (in) {
965		return false;
966	}
967
968	*out = data_blob(NULL, 0);
969	return true;
970}
971
972static bool encode_show_deleted_request(void *mem_ctx, void *in, DATA_BLOB *out)
973{
974	if (in) {
975		return false;
976	}
977
978	*out = data_blob(NULL, 0);
979	return true;
980}
981
982static bool encode_show_recycled_request(void *mem_ctx, void *in, DATA_BLOB *out)
983{
984	if (in) {
985		return false;
986	}
987
988	*out = data_blob(NULL, 0);
989	return true;
990}
991
992static bool encode_show_deactivated_link_request(void *mem_ctx, void *in, DATA_BLOB *out)
993{
994	if (in) {
995		return false;
996	}
997
998	*out = data_blob(NULL, 0);
999	return true;
1000}
1001
1002static bool encode_permissive_modify_request(void *mem_ctx, void *in, DATA_BLOB *out)
1003{
1004	if (in) {
1005		return false;
1006	}
1007
1008	*out = data_blob(NULL, 0);
1009	return true;
1010}
1011
1012static bool encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out)
1013{
1014	if (in) {
1015		return false;
1016	}
1017
1018	*out = data_blob(NULL, 0);
1019	return true;
1020}
1021
1022static bool encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
1023{
1024	struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control);
1025	struct asn1_data *data = asn1_init(mem_ctx);
1026
1027	if (!data) return false;
1028
1029	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1030		return false;
1031	}
1032
1033	if (!asn1_write_Integer(data, lvrc->beforeCount)) {
1034		return false;
1035	}
1036
1037	if (!asn1_write_Integer(data, lvrc->afterCount)) {
1038		return false;
1039	}
1040
1041	if (lvrc->type == 0) {
1042		if (!asn1_push_tag(data, ASN1_CONTEXT(0))) {
1043			return false;
1044		}
1045
1046		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1047			return false;
1048		}
1049
1050		if (!asn1_write_Integer(data, lvrc->match.byOffset.offset)) {
1051			return false;
1052		}
1053
1054		if (!asn1_write_Integer(data, lvrc->match.byOffset.contentCount)) {
1055			return false;
1056		}
1057
1058		if (!asn1_pop_tag(data)) { /*SEQUENCE*/
1059			return false;
1060		}
1061
1062		if (!asn1_pop_tag(data)) { /*CONTEXT*/
1063			return false;
1064		}
1065	} else {
1066		if (!asn1_push_tag(data, ASN1_CONTEXT(1))) {
1067			return false;
1068		}
1069
1070		if (!asn1_write_OctetString(data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
1071			return false;
1072		}
1073
1074		if (!asn1_pop_tag(data)) { /*CONTEXT*/
1075			return false;
1076		}
1077	}
1078
1079	if (lvrc->ctxid_len) {
1080		if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1081			return false;
1082		}
1083	}
1084
1085	if (!asn1_pop_tag(data)) {
1086		return false;
1087	}
1088
1089	*out = data_blob_talloc(mem_ctx, data->data, data->length);
1090	if (out->data == NULL) {
1091		return false;
1092	}
1093	talloc_free(data);
1094
1095	return true;
1096}
1097
1098static bool encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out)
1099{
1100	struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control);
1101	struct asn1_data *data = asn1_init(mem_ctx);
1102
1103	if (!data) return false;
1104
1105	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1106		return false;
1107	}
1108
1109	if (!asn1_write_Integer(data, lvrc->targetPosition)) {
1110		return false;
1111	}
1112
1113	if (!asn1_write_Integer(data, lvrc->contentCount)) {
1114		return false;
1115	}
1116
1117	if (!asn1_write_enumerated(data, lvrc->vlv_result)) {
1118		return false;
1119	}
1120
1121	if (lvrc->ctxid_len) {
1122		if (!asn1_write_OctetString(data, lvrc->contextId, lvrc->ctxid_len)) {
1123			return false;
1124		}
1125	}
1126
1127	if (!asn1_pop_tag(data)) {
1128		return false;
1129	}
1130
1131	*out = data_blob_talloc(mem_ctx, data->data, data->length);
1132	if (out->data == NULL) {
1133		return false;
1134	}
1135	talloc_free(data);
1136
1137	return true;
1138}
1139
1140static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
1141{
1142	struct dsdb_openldap_dereference_control *control = talloc_get_type(in, struct dsdb_openldap_dereference_control);
1143	int i,j;
1144	struct asn1_data *data = asn1_init(mem_ctx);
1145
1146	if (!data) return false;
1147
1148	if (!control) return false;
1149
1150	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1151		return false;
1152	}
1153
1154	for (i=0; control->dereference && control->dereference[i]; i++) {
1155		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1156			return false;
1157		}
1158		if (!asn1_write_OctetString(data, control->dereference[i]->source_attribute, strlen(control->dereference[i]->source_attribute))) {
1159			return false;
1160		}
1161		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
1162			return false;
1163		}
1164		for (j=0; control->dereference && control->dereference[i]->dereference_attribute[j]; j++) {
1165			if (!asn1_write_OctetString(data, control->dereference[i]->dereference_attribute[j],
1166						    strlen(control->dereference[i]->dereference_attribute[j]))) {
1167				return false;
1168			}
1169		}
1170
1171		asn1_pop_tag(data);
1172		asn1_pop_tag(data);
1173	}
1174	asn1_pop_tag(data);
1175
1176	*out = data_blob_talloc(mem_ctx, data->data, data->length);
1177	if (out->data == NULL) {
1178		return false;
1179	}
1180	talloc_free(data);
1181	return true;
1182}
1183
1184static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
1185{
1186	void **out = (void **)_out;
1187	struct asn1_data *data = asn1_init(mem_ctx);
1188	struct dsdb_openldap_dereference_result_control *control;
1189	struct dsdb_openldap_dereference_result **r = NULL;
1190	int i = 0;
1191	if (!data) return false;
1192
1193	control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1194	if (!control) return false;
1195
1196	if (!asn1_load(data, in)) {
1197		return false;
1198	}
1199
1200	control = talloc(mem_ctx, struct dsdb_openldap_dereference_result_control);
1201	if (!control) {
1202		return false;
1203	}
1204
1205	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1206		return false;
1207	}
1208
1209	while (asn1_tag_remaining(data) > 0) {
1210		r = talloc_realloc(control, r, struct dsdb_openldap_dereference_result *, i + 2);
1211		if (!r) {
1212			return false;
1213		}
1214		r[i] = talloc_zero(r, struct dsdb_openldap_dereference_result);
1215		if (!r[i]) {
1216			return false;
1217		}
1218
1219		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
1220			return false;
1221		}
1222
1223		asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
1224		asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
1225		if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
1226			if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
1227				return false;
1228			}
1229
1230			ldap_decode_attribs_bare(r, data, &r[i]->attributes,
1231						 &r[i]->num_attributes);
1232
1233			if (!asn1_end_tag(data)) {
1234				return false;
1235			}
1236		}
1237		if (!asn1_end_tag(data)) {
1238			return false;
1239		}
1240		i++;
1241		r[i] = NULL;
1242	}
1243
1244	if (!asn1_end_tag(data)) {
1245		return false;
1246	}
1247
1248	control->attributes = r;
1249	*out = control;
1250
1251	return true;
1252}
1253
1254static const struct ldap_control_handler ldap_known_controls[] = {
1255	{ "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
1256	{ "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
1257	{ "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
1258	{ "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response },
1259	{ "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control },
1260	{ "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request },
1261	{ "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request },
1262	{ "1.2.840.113556.1.4.417", decode_show_deleted_request, encode_show_deleted_request },
1263	{ "1.2.840.113556.1.4.2064", decode_show_recycled_request, encode_show_recycled_request },
1264	{ "1.2.840.113556.1.4.2065", decode_show_deactivated_link_request, encode_show_deactivated_link_request },
1265	{ "1.2.840.113556.1.4.1413", decode_permissive_modify_request, encode_permissive_modify_request },
1266	{ "1.2.840.113556.1.4.801", decode_sd_flags_request, encode_sd_flags_request },
1267	{ "1.2.840.113556.1.4.1339", decode_domain_scope_request, encode_domain_scope_request },
1268	{ "1.2.840.113556.1.4.1340", decode_search_options_request, encode_search_options_request },
1269	{ "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request },
1270	{ "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request },
1271	{ "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response },
1272/* DSDB_CONTROL_CURRENT_PARTITION_OID is internal only, and has no network representation */
1273	{ "1.3.6.1.4.1.7165.4.3.2", NULL, NULL },
1274/* DSDB_EXTENDED_REPLICATED_OBJECTS_OID is internal only, and has no network representation */
1275	{ "1.3.6.1.4.1.7165.4.4.1", NULL, NULL },
1276	{ DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference},
1277	{ NULL, NULL, NULL }
1278};
1279
1280const struct ldap_control_handler *samba_ldap_control_handlers(void)
1281{
1282	return ldap_known_controls;
1283}
1284
1285