32b2c0f66dfc7fe8a0abd057e99b883a9f4cee42
[ira/wip.git] / source4 / lib / ldb / common / ldb_controls.c
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 */
38 struct 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 */
57 struct 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
75 the "exclude" control */
76 /* returns 0 on error */
77 int 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 */
107 int 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
124 int 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
160 struct 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], "relax:", 6) == 0) {
411                         const char *p;
412                         int crit, ret;
413
414                         p = &(control_strings[i][6]);
415                         ret = sscanf(p, "%d", &crit);
416                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
417                                 error_string = talloc_asprintf(mem_ctx, "invalid relax 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_RELAX_OID;
431                         ctrl[i]->critical = crit;
432                         ctrl[i]->data = NULL;
433
434                         continue;
435                 }
436
437                 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
438                         const char *p;
439                         int crit, ret;
440
441                         p = &(control_strings[i][13]);
442                         ret = sscanf(p, "%d", &crit);
443                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
444                                 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
445                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
446                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
447                                 ldb_set_errstring(ldb, error_string);
448                                 talloc_free(error_string);
449                                 return NULL;
450                         }
451
452                         ctrl[i] = talloc(ctrl, struct ldb_control);
453                         if (!ctrl[i]) {
454                                 ldb_oom(ldb);
455                                 return NULL;
456                         }
457                         ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
458                         ctrl[i]->critical = crit;
459                         ctrl[i]->data = NULL;
460
461                         continue;
462                 }
463
464                 if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
465                         struct ldb_paged_control *control;
466                         const char *p;
467                         int crit, size, ret;
468                        
469                         p = &(control_strings[i][14]);
470                         ret = sscanf(p, "%d:%d", &crit, &size);
471
472                         if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
473                                 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
474                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
475                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
476                                 ldb_set_errstring(ldb, error_string);
477                                 talloc_free(error_string);
478                                 return NULL;
479                         }
480
481                         ctrl[i] = talloc(ctrl, struct ldb_control);
482                         if (!ctrl[i]) {
483                                 ldb_oom(ldb);
484                                 return NULL;
485                         }
486                         ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
487                         ctrl[i]->critical = crit;
488                         control = talloc(ctrl[i], struct ldb_paged_control);
489                         control->size = size;
490                         control->cookie = NULL;
491                         control->cookie_len = 0;
492                         ctrl[i]->data = control;
493
494                         continue;
495                 }
496
497                 if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
498                         struct ldb_server_sort_control **control;
499                         const char *p;
500                         char attr[256];
501                         char rule[128];
502                         int crit, rev, ret;
503
504                         attr[0] = '\0';
505                         rule[0] = '\0';
506                         p = &(control_strings[i][12]);
507                         ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
508                         if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
509                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
510                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
511                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
512                                 ldb_set_errstring(ldb, error_string);
513                                 talloc_free(error_string);
514                                 return NULL;
515                         }
516                         ctrl[i] = talloc(ctrl, struct ldb_control);
517                         if (!ctrl[i]) {
518                                 ldb_oom(ldb);
519                                 return NULL;
520                         }
521                         ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
522                         ctrl[i]->critical = crit;
523                         control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
524                         control[0] = talloc(control, struct ldb_server_sort_control);
525                         control[0]->attributeName = talloc_strdup(control, attr);
526                         if (rule[0])
527                                 control[0]->orderingRule = talloc_strdup(control, rule);
528                         else
529                                 control[0]->orderingRule = NULL;
530                         control[0]->reverse = rev;
531                         control[1] = NULL;
532                         ctrl[i]->data = control;
533
534                         continue;
535                 }
536
537                 if (strncmp(control_strings[i], "notification:", 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 notification 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_NOTIFICATION_OID;
558                         ctrl[i]->critical = crit;
559                         ctrl[i]->data = NULL;
560
561                         continue;
562                 }
563
564                 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
565                         const char *p;
566                         int crit, ret;
567
568                         p = &(control_strings[i][13]);
569                         ret = sscanf(p, "%d", &crit);
570                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
571                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted 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_DELETED_OID;
585                         ctrl[i]->critical = crit;
586                         ctrl[i]->data = NULL;
587
588                         continue;
589                 }
590
591                 if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
592                         const char *p;
593                         int crit, ret;
594
595                         p = &(control_strings[i][22]);
596                         ret = sscanf(p, "%d", &crit);
597                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
598                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link 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_DEACTIVATED_LINK_OID;
612                         ctrl[i]->critical = crit;
613                         ctrl[i]->data = NULL;
614
615                         continue;
616                 }
617
618                 if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
619                         const char *p;
620                         int crit, ret;
621
622                         p = &(control_strings[i][14]);
623                         ret = sscanf(p, "%d", &crit);
624                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
625                                 error_string = talloc_asprintf(mem_ctx, "invalid show_recycled 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_SHOW_RECYCLED_OID;
639                         ctrl[i]->critical = crit;
640                         ctrl[i]->data = NULL;
641
642                         continue;
643                 }
644
645                 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
646                         const char *p;
647                         int crit, ret;
648
649                         p = &(control_strings[i][18]);
650                         ret = sscanf(p, "%d", &crit);
651                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
652                                 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
653                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
654                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
655                                 ldb_set_errstring(ldb, error_string);
656                                 talloc_free(error_string);
657                                 return NULL;
658                         }
659
660                         ctrl[i] = talloc(ctrl, struct ldb_control);
661                         if (!ctrl[i]) {
662                                 ldb_oom(ldb);
663                                 return NULL;
664                         }
665                         ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
666                         ctrl[i]->critical = crit;
667                         ctrl[i]->data = NULL;
668
669                         continue;
670                 }
671
672                 /* no controls matched, throw an error */
673                 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
674                 return NULL;
675         }
676
677         ctrl[i] = NULL;
678
679         return ctrl;
680 }
681
682