• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/lib/ldb/common/
1/*
2   ldb database library
3
4   Copyright (C) Simo Sorce  2005
5
6     ** NOTE! The following LGPL license applies to the ldb
7     ** library. This does NOT imply that all of Samba is released
8     ** under the LGPL
9
10   This library is free software; you can redistribute it and/or
11   modify it under the terms of the GNU Lesser General Public
12   License as published by the Free Software Foundation; either
13   version 3 of the License, or (at your option) any later version.
14
15   This library 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 GNU
18   Lesser General Public License for more details.
19
20   You should have received a copy of the GNU Lesser General Public
21   License along with this library; if not, see <http://www.gnu.org/licenses/>.
22*/
23
24/*
25 *  Name: ldb_controls.c
26 *
27 *  Component: ldb controls utility functions
28 *
29 *  Description: helper functions for control modules
30 *
31 *  Author: Simo Sorce
32 */
33
34#include "ldb_private.h"
35
36/* check if a control with the specified "oid" exist and return it */
37/* returns NULL if not found */
38struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
39{
40	int i;
41
42	if (req->controls != NULL) {
43		for (i = 0; req->controls[i]; i++) {
44			if (strcmp(oid, req->controls[i]->oid) == 0) {
45				break;
46			}
47		}
48
49		return req->controls[i];
50	}
51
52	return NULL;
53}
54
55/* check if a control with the specified "oid" exist and return it */
56/* returns NULL if not found */
57struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid)
58{
59	int i;
60
61	if (rep->controls != NULL) {
62		for (i = 0; rep->controls[i]; i++) {
63			if (strcmp(oid, rep->controls[i]->oid) == 0) {
64				break;
65			}
66		}
67
68		return rep->controls[i];
69	}
70
71	return NULL;
72}
73
74/* saves the current controls list into the "saver" and replace the one in req with a new one excluding
75the "exclude" control */
76/* returns 0 on error */
77int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
78{
79	struct ldb_control **lcs;
80	int i, j;
81
82	*saver = req->controls;
83	for (i = 0; req->controls[i]; i++);
84	if (i == 1) {
85		req->controls = NULL;
86		return 1;
87	}
88
89	lcs = talloc_array(req, struct ldb_control *, i);
90	if (!lcs) {
91		return 0;
92	}
93
94	for (i = 0, j = 0; (*saver)[i]; i++) {
95		if (exclude == (*saver)[i]) continue;
96		lcs[j] = (*saver)[i];
97		j++;
98	}
99	lcs[j] = NULL;
100
101	req->controls = lcs;
102	return 1;
103}
104
105/* check if there's any control marked as critical in the list */
106/* return True if any, False if none */
107int check_critical_controls(struct ldb_control **controls)
108{
109	int i;
110
111	if (controls == NULL) {
112		return 0;
113	}
114
115	for (i = 0; controls[i]; i++) {
116		if (controls[i]->critical) {
117			return 1;
118		}
119	}
120
121	return 0;
122}
123
124int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
125{
126	unsigned n;
127	struct ldb_control **ctrls;
128	struct ldb_control *ctrl;
129
130	for (n=0; req->controls && req->controls[n];) {
131		/* having two controls of the same OID makes no sense */
132		if (strcmp(oid, req->controls[n]->oid) == 0) {
133			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
134		}
135		n++;
136	}
137
138	ctrls = talloc_realloc(req, req->controls,
139			       struct ldb_control *,
140			       n + 2);
141	if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
142	req->controls = ctrls;
143	ctrls[n] = NULL;
144	ctrls[n+1] = NULL;
145
146	ctrl = talloc(ctrls, struct ldb_control);
147	if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
148
149	ctrl->oid	= talloc_strdup(ctrl, oid);
150	if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
151	ctrl->critical	= critical;
152	ctrl->data	= data;
153
154	ctrls[n] = ctrl;
155	return LDB_SUCCESS;
156}
157
158/* Parse controls from the format used on the command line and in ejs */
159
160struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
161{
162	int i;
163	struct ldb_control **ctrl;
164
165	char *error_string = NULL;
166
167	if (control_strings == NULL || control_strings[0] == NULL)
168		return NULL;
169
170	for (i = 0; control_strings[i]; i++);
171
172	ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
173
174	for (i = 0; control_strings[i]; i++) {
175		if (strncmp(control_strings[i], "vlv:", 4) == 0) {
176			struct ldb_vlv_req_control *control;
177			const char *p;
178			char attr[1024];
179			char ctxid[1024];
180			int crit, bc, ac, os, cc, ret;
181
182			attr[0] = '\0';
183			ctxid[0] = '\0';
184			p = &(control_strings[i][4]);
185			ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
186			if (ret < 5) {
187				ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
188			}
189
190			if ((ret < 4) || (crit < 0) || (crit > 1)) {
191				error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
192				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
193				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, s = string, o = b64 binary blob");
194				ldb_set_errstring(ldb, error_string);
195				talloc_free(error_string);
196				return NULL;
197			}
198			if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
199				ldb_oom(ldb);
200				return NULL;
201			}
202			ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
203			ctrl[i]->critical = crit;
204			if (!(control = talloc(ctrl[i],
205					       struct ldb_vlv_req_control))) {
206				ldb_oom(ldb);
207				return NULL;
208			}
209			control->beforeCount = bc;
210			control->afterCount = ac;
211			if (attr[0]) {
212				control->type = 1;
213				control->match.gtOrEq.value = talloc_strdup(control, attr);
214				control->match.gtOrEq.value_len = strlen(attr);
215			} else {
216				control->type = 0;
217				control->match.byOffset.offset = os;
218				control->match.byOffset.contentCount = cc;
219			}
220			if (ctxid[0]) {
221				control->ctxid_len = ldb_base64_decode(ctxid);
222				control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
223			} else {
224				control->ctxid_len = 0;
225				control->contextId = NULL;
226			}
227			ctrl[i]->data = control;
228
229			continue;
230		}
231
232		if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
233			struct ldb_dirsync_control *control;
234			const char *p;
235			char cookie[1024];
236			int crit, flags, max_attrs, ret;
237
238			cookie[0] = '\0';
239			p = &(control_strings[i][8]);
240			ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
241
242			if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
243				error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
244				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
245				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, o = b64 binary blob");
246				ldb_set_errstring(ldb, error_string);
247				talloc_free(error_string);
248				return NULL;
249			}
250
251			/* w2k3 seems to ignore the parameter,
252			 * but w2k sends a wrong cookie when this value is to small
253			 * this would cause looping forever, while getting
254			 * the same data and same cookie forever
255			 */
256			if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
257
258			ctrl[i] = talloc(ctrl, struct ldb_control);
259			ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
260			ctrl[i]->critical = crit;
261			control = talloc(ctrl[i], struct ldb_dirsync_control);
262			control->flags = flags;
263			control->max_attributes = max_attrs;
264			if (*cookie) {
265				control->cookie_len = ldb_base64_decode(cookie);
266				control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
267			} else {
268				control->cookie = NULL;
269				control->cookie_len = 0;
270			}
271			ctrl[i]->data = control;
272
273			continue;
274		}
275
276		if (strncmp(control_strings[i], "asq:", 4) == 0) {
277			struct ldb_asq_control *control;
278			const char *p;
279			char attr[256];
280			int crit, ret;
281
282			attr[0] = '\0';
283			p = &(control_strings[i][4]);
284			ret = sscanf(p, "%d:%255[^$]", &crit, attr);
285			if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
286				error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
287				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
288				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
289				ldb_set_errstring(ldb, error_string);
290				talloc_free(error_string);
291				return NULL;
292			}
293
294			ctrl[i] = talloc(ctrl, struct ldb_control);
295			if (!ctrl[i]) {
296				ldb_oom(ldb);
297				return NULL;
298			}
299			ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
300			ctrl[i]->critical = crit;
301			control = talloc(ctrl[i], struct ldb_asq_control);
302			control->request = 1;
303			control->source_attribute = talloc_strdup(control, attr);
304			control->src_attr_len = strlen(attr);
305			ctrl[i]->data = control;
306
307			continue;
308		}
309
310		if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
311			struct ldb_extended_dn_control *control;
312			const char *p;
313			int crit, type, ret;
314
315			p = &(control_strings[i][12]);
316			ret = sscanf(p, "%d:%d", &crit, &type);
317			if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
318				ret = sscanf(p, "%d", &crit);
319				if ((ret != 1) || (crit < 0) || (crit > 1)) {
320					error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
321					error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
322					error_string = talloc_asprintf_append(error_string, "   note: b = boolean\n");
323					error_string = talloc_asprintf_append(error_string, "         i = integer\n");
324					error_string = talloc_asprintf_append(error_string, "   valid values are: 0 - hexadecimal representation\n");
325					error_string = talloc_asprintf_append(error_string, "                     1 - normal string representation");
326					ldb_set_errstring(ldb, error_string);
327					talloc_free(error_string);
328					return NULL;
329				}
330				control = NULL;
331			} else {
332				control = talloc(ctrl, struct ldb_extended_dn_control);
333				control->type = type;
334			}
335
336			ctrl[i] = talloc(ctrl, struct ldb_control);
337			if (!ctrl[i]) {
338				ldb_oom(ldb);
339				return NULL;
340			}
341			ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
342			ctrl[i]->critical = crit;
343			ctrl[i]->data = talloc_steal(ctrl[i], control);
344
345			continue;
346		}
347
348		if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
349			struct ldb_sd_flags_control *control;
350			const char *p;
351			int crit, ret;
352			unsigned secinfo_flags;
353
354			p = &(control_strings[i][9]);
355			ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
356			if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
357				error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
358				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
359				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
360				ldb_set_errstring(ldb, error_string);
361				talloc_free(error_string);
362				return NULL;
363			}
364
365			ctrl[i] = talloc(ctrl, struct ldb_control);
366			if (!ctrl[i]) {
367				ldb_oom(ldb);
368				return NULL;
369			}
370			ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
371			ctrl[i]->critical = crit;
372			control = talloc(ctrl[i], struct ldb_sd_flags_control);
373			control->secinfo_flags = secinfo_flags;
374			ctrl[i]->data = control;
375
376			continue;
377		}
378
379		if (strncmp(control_strings[i], "search_options:", 15) == 0) {
380			struct ldb_search_options_control *control;
381			const char *p;
382			int crit, ret;
383			unsigned search_options;
384
385			p = &(control_strings[i][15]);
386			ret = sscanf(p, "%d:%u", &crit, &search_options);
387			if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
388				error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
389				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
390				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
391				ldb_set_errstring(ldb, error_string);
392				talloc_free(error_string);
393				return NULL;
394			}
395
396			ctrl[i] = talloc(ctrl, struct ldb_control);
397			if (!ctrl[i]) {
398				ldb_oom(ldb);
399				return NULL;
400			}
401			ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
402			ctrl[i]->critical = crit;
403			control = talloc(ctrl[i], struct ldb_search_options_control);
404			control->search_options = search_options;
405			ctrl[i]->data = control;
406
407			continue;
408		}
409
410		if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
411			const char *p;
412			int crit, ret;
413
414			p = &(control_strings[i][13]);
415			ret = sscanf(p, "%d", &crit);
416			if ((ret != 1) || (crit < 0) || (crit > 1)) {
417				error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
418				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
419				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
420				ldb_set_errstring(ldb, error_string);
421				talloc_free(error_string);
422				return NULL;
423			}
424
425			ctrl[i] = talloc(ctrl, struct ldb_control);
426			if (!ctrl[i]) {
427				ldb_oom(ldb);
428				return NULL;
429			}
430			ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
431			ctrl[i]->critical = crit;
432			ctrl[i]->data = NULL;
433
434			continue;
435		}
436
437		if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
438			struct ldb_paged_control *control;
439			const char *p;
440			int crit, size, ret;
441
442			p = &(control_strings[i][14]);
443			ret = sscanf(p, "%d:%d", &crit, &size);
444
445			if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
446				error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
447				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
448				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
449				ldb_set_errstring(ldb, error_string);
450				talloc_free(error_string);
451				return NULL;
452			}
453
454			ctrl[i] = talloc(ctrl, struct ldb_control);
455			if (!ctrl[i]) {
456				ldb_oom(ldb);
457				return NULL;
458			}
459			ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
460			ctrl[i]->critical = crit;
461			control = talloc(ctrl[i], struct ldb_paged_control);
462			control->size = size;
463			control->cookie = NULL;
464			control->cookie_len = 0;
465			ctrl[i]->data = control;
466
467			continue;
468		}
469
470		if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
471			struct ldb_server_sort_control **control;
472			const char *p;
473			char attr[256];
474			char rule[128];
475			int crit, rev, ret;
476
477			attr[0] = '\0';
478			rule[0] = '\0';
479			p = &(control_strings[i][12]);
480			ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
481			if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
482				error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
483				error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
484				error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
485				ldb_set_errstring(ldb, error_string);
486				talloc_free(error_string);
487				return NULL;
488			}
489			ctrl[i] = talloc(ctrl, struct ldb_control);
490			if (!ctrl[i]) {
491				ldb_oom(ldb);
492				return NULL;
493			}
494			ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
495			ctrl[i]->critical = crit;
496			control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
497			control[0] = talloc(control, struct ldb_server_sort_control);
498			control[0]->attributeName = talloc_strdup(control, attr);
499			if (rule[0])
500				control[0]->orderingRule = talloc_strdup(control, rule);
501			else
502				control[0]->orderingRule = NULL;
503			control[0]->reverse = rev;
504			control[1] = NULL;
505			ctrl[i]->data = control;
506
507			continue;
508		}
509
510		if (strncmp(control_strings[i], "notification:", 13) == 0) {
511			const char *p;
512			int crit, ret;
513
514			p = &(control_strings[i][13]);
515			ret = sscanf(p, "%d", &crit);
516			if ((ret != 1) || (crit < 0) || (crit > 1)) {
517				error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
518				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
519				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
520				ldb_set_errstring(ldb, error_string);
521				talloc_free(error_string);
522				return NULL;
523			}
524
525			ctrl[i] = talloc(ctrl, struct ldb_control);
526			if (!ctrl[i]) {
527				ldb_oom(ldb);
528				return NULL;
529			}
530			ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
531			ctrl[i]->critical = crit;
532			ctrl[i]->data = NULL;
533
534			continue;
535		}
536
537		if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
538			const char *p;
539			int crit, ret;
540
541			p = &(control_strings[i][13]);
542			ret = sscanf(p, "%d", &crit);
543			if ((ret != 1) || (crit < 0) || (crit > 1)) {
544				error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
545				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
546				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
547				ldb_set_errstring(ldb, error_string);
548				talloc_free(error_string);
549				return NULL;
550			}
551
552			ctrl[i] = talloc(ctrl, struct ldb_control);
553			if (!ctrl[i]) {
554				ldb_oom(ldb);
555				return NULL;
556			}
557			ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
558			ctrl[i]->critical = crit;
559			ctrl[i]->data = NULL;
560
561			continue;
562		}
563
564		if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
565			const char *p;
566			int crit, ret;
567
568			p = &(control_strings[i][22]);
569			ret = sscanf(p, "%d", &crit);
570			if ((ret != 1) || (crit < 0) || (crit > 1)) {
571				error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
572				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
573				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
574				ldb_set_errstring(ldb, error_string);
575				talloc_free(error_string);
576				return NULL;
577			}
578
579			ctrl[i] = talloc(ctrl, struct ldb_control);
580			if (!ctrl[i]) {
581				ldb_oom(ldb);
582				return NULL;
583			}
584			ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
585			ctrl[i]->critical = crit;
586			ctrl[i]->data = NULL;
587
588			continue;
589		}
590
591		if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
592			const char *p;
593			int crit, ret;
594
595			p = &(control_strings[i][14]);
596			ret = sscanf(p, "%d", &crit);
597			if ((ret != 1) || (crit < 0) || (crit > 1)) {
598				error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
599				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
600				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
601				ldb_set_errstring(ldb, error_string);
602				talloc_free(error_string);
603				return NULL;
604			}
605
606			ctrl[i] = talloc(ctrl, struct ldb_control);
607			if (!ctrl[i]) {
608				ldb_oom(ldb);
609				return NULL;
610			}
611			ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
612			ctrl[i]->critical = crit;
613			ctrl[i]->data = NULL;
614
615			continue;
616		}
617
618		if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
619			const char *p;
620			int crit, ret;
621
622			p = &(control_strings[i][18]);
623			ret = sscanf(p, "%d", &crit);
624			if ((ret != 1) || (crit < 0) || (crit > 1)) {
625				error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
626				error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
627				error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
628				ldb_set_errstring(ldb, error_string);
629				talloc_free(error_string);
630				return NULL;
631			}
632
633			ctrl[i] = talloc(ctrl, struct ldb_control);
634			if (!ctrl[i]) {
635				ldb_oom(ldb);
636				return NULL;
637			}
638			ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
639			ctrl[i]->critical = crit;
640			ctrl[i]->data = NULL;
641
642			continue;
643		}
644
645		/* no controls matched, throw an error */
646		ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
647		return NULL;
648	}
649
650	ctrl[i] = NULL;
651
652	return ctrl;
653}
654
655
656