s4:ldb - fixed dangling pointer in ldb_request_add_control()
[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 i, 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_array(req,
139                                struct ldb_control *,
140                                n + 2);
141         if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
142
143         for (i=0; i<n; i++) {
144                 ctrls[i] = req->controls[i];
145         }
146
147         req->controls = ctrls;
148         ctrls[n] = NULL;
149         ctrls[n+1] = NULL;
150
151         ctrl = talloc(ctrls, struct ldb_control);
152         if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
153
154         ctrl->oid       = talloc_strdup(ctrl, oid);
155         if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
156         ctrl->critical  = critical;
157         ctrl->data      = data;
158
159         ctrls[n] = ctrl;
160         return LDB_SUCCESS;
161 }
162
163 /* Parse controls from the format used on the command line and in ejs */
164
165 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
166 {
167         int i;
168         struct ldb_control **ctrl;
169
170         char *error_string = NULL;
171
172         if (control_strings == NULL || control_strings[0] == NULL)
173                 return NULL;
174
175         for (i = 0; control_strings[i]; i++);
176
177         ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
178
179         for (i = 0; control_strings[i]; i++) {
180                 if (strncmp(control_strings[i], "vlv:", 4) == 0) {
181                         struct ldb_vlv_req_control *control;
182                         const char *p;
183                         char attr[1024];
184                         char ctxid[1024];
185                         int crit, bc, ac, os, cc, ret;
186
187                         attr[0] = '\0';
188                         ctxid[0] = '\0';
189                         p = &(control_strings[i][4]);
190                         ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
191                         if (ret < 5) {
192                                 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
193                         }
194                                
195                         if ((ret < 4) || (crit < 0) || (crit > 1)) {
196                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
197                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
198                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, s = string, o = b64 binary blob");
199                                 ldb_set_errstring(ldb, error_string);
200                                 talloc_free(error_string);
201                                 return NULL;
202                         }
203                         if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
204                                 ldb_oom(ldb);
205                                 return NULL;
206                         }
207                         ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
208                         ctrl[i]->critical = crit;
209                         if (!(control = talloc(ctrl[i],
210                                                struct ldb_vlv_req_control))) {
211                                 ldb_oom(ldb);
212                                 return NULL;
213                         }
214                         control->beforeCount = bc;
215                         control->afterCount = ac;
216                         if (attr[0]) {
217                                 control->type = 1;
218                                 control->match.gtOrEq.value = talloc_strdup(control, attr);
219                                 control->match.gtOrEq.value_len = strlen(attr);
220                         } else {
221                                 control->type = 0;
222                                 control->match.byOffset.offset = os;
223                                 control->match.byOffset.contentCount = cc;
224                         }
225                         if (ctxid[0]) {
226                                 control->ctxid_len = ldb_base64_decode(ctxid);
227                                 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
228                         } else {
229                                 control->ctxid_len = 0;
230                                 control->contextId = NULL;
231                         }
232                         ctrl[i]->data = control;
233
234                         continue;
235                 }
236
237                 if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
238                         struct ldb_dirsync_control *control;
239                         const char *p;
240                         char cookie[1024];
241                         int crit, flags, max_attrs, ret;
242                        
243                         cookie[0] = '\0';
244                         p = &(control_strings[i][8]);
245                         ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
246
247                         if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
248                                 error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
249                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
250                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, o = b64 binary blob");
251                                 ldb_set_errstring(ldb, error_string);
252                                 talloc_free(error_string);
253                                 return NULL;
254                         }
255
256                         /* w2k3 seems to ignore the parameter,
257                          * but w2k sends a wrong cookie when this value is to small
258                          * this would cause looping forever, while getting
259                          * the same data and same cookie forever
260                          */
261                         if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
262
263                         ctrl[i] = talloc(ctrl, struct ldb_control);
264                         ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
265                         ctrl[i]->critical = crit;
266                         control = talloc(ctrl[i], struct ldb_dirsync_control);
267                         control->flags = flags;
268                         control->max_attributes = max_attrs;
269                         if (*cookie) {
270                                 control->cookie_len = ldb_base64_decode(cookie);
271                                 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
272                         } else {
273                                 control->cookie = NULL;
274                                 control->cookie_len = 0;
275                         }
276                         ctrl[i]->data = control;
277
278                         continue;
279                 }
280
281                 if (strncmp(control_strings[i], "asq:", 4) == 0) {
282                         struct ldb_asq_control *control;
283                         const char *p;
284                         char attr[256];
285                         int crit, ret;
286
287                         attr[0] = '\0';
288                         p = &(control_strings[i][4]);
289                         ret = sscanf(p, "%d:%255[^$]", &crit, attr);
290                         if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
291                                 error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
292                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
293                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
294                                 ldb_set_errstring(ldb, error_string);
295                                 talloc_free(error_string);
296                                 return NULL;
297                         }
298
299                         ctrl[i] = talloc(ctrl, struct ldb_control);
300                         if (!ctrl[i]) {
301                                 ldb_oom(ldb);
302                                 return NULL;
303                         }
304                         ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
305                         ctrl[i]->critical = crit;
306                         control = talloc(ctrl[i], struct ldb_asq_control);
307                         control->request = 1;
308                         control->source_attribute = talloc_strdup(control, attr);
309                         control->src_attr_len = strlen(attr);
310                         ctrl[i]->data = control;
311
312                         continue;
313                 }
314
315                 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
316                         struct ldb_extended_dn_control *control;
317                         const char *p;
318                         int crit, type, ret;
319
320                         p = &(control_strings[i][12]);
321                         ret = sscanf(p, "%d:%d", &crit, &type);
322                         if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
323                                 ret = sscanf(p, "%d", &crit);
324                                 if ((ret != 1) || (crit < 0) || (crit > 1)) {
325                                         error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
326                                         error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n");
327                                         error_string = talloc_asprintf_append(error_string, "   note: b = boolean\n");
328                                         error_string = talloc_asprintf_append(error_string, "         i = integer\n");
329                                         error_string = talloc_asprintf_append(error_string, "   valid values are: 0 - hexadecimal representation\n");
330                                         error_string = talloc_asprintf_append(error_string, "                     1 - normal string representation");
331                                         ldb_set_errstring(ldb, error_string);
332                                         talloc_free(error_string);
333                                         return NULL;
334                                 }
335                                 control = NULL;
336                         } else {
337                                 control = talloc(ctrl, struct ldb_extended_dn_control);
338                                 control->type = type;
339                         }
340
341                         ctrl[i] = talloc(ctrl, struct ldb_control);
342                         if (!ctrl[i]) {
343                                 ldb_oom(ldb);
344                                 return NULL;
345                         }
346                         ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
347                         ctrl[i]->critical = crit;
348                         ctrl[i]->data = talloc_steal(ctrl[i], control);
349
350                         continue;
351                 }
352
353                 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
354                         struct ldb_sd_flags_control *control;
355                         const char *p;
356                         int crit, ret;
357                         unsigned secinfo_flags;
358
359                         p = &(control_strings[i][9]);
360                         ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
361                         if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
362                                 error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
363                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
364                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
365                                 ldb_set_errstring(ldb, error_string);
366                                 talloc_free(error_string);
367                                 return NULL;
368                         }
369
370                         ctrl[i] = talloc(ctrl, struct ldb_control);
371                         if (!ctrl[i]) {
372                                 ldb_oom(ldb);
373                                 return NULL;
374                         }
375                         ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
376                         ctrl[i]->critical = crit;
377                         control = talloc(ctrl[i], struct ldb_sd_flags_control);
378                         control->secinfo_flags = secinfo_flags;
379                         ctrl[i]->data = control;
380
381                         continue;
382                 }
383
384                 if (strncmp(control_strings[i], "search_options:", 15) == 0) {
385                         struct ldb_search_options_control *control;
386                         const char *p;
387                         int crit, ret;
388                         unsigned search_options;
389
390                         p = &(control_strings[i][15]);
391                         ret = sscanf(p, "%d:%u", &crit, &search_options);
392                         if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
393                                 error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
394                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
395                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
396                                 ldb_set_errstring(ldb, error_string);
397                                 talloc_free(error_string);
398                                 return NULL;
399                         }
400
401                         ctrl[i] = talloc(ctrl, struct ldb_control);
402                         if (!ctrl[i]) {
403                                 ldb_oom(ldb);
404                                 return NULL;
405                         }
406                         ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
407                         ctrl[i]->critical = crit;
408                         control = talloc(ctrl[i], struct ldb_search_options_control);
409                         control->search_options = search_options;
410                         ctrl[i]->data = control;
411
412                         continue;
413                 }
414
415                 if (strncmp(control_strings[i], "relax:", 6) == 0) {
416                         const char *p;
417                         int crit, ret;
418
419                         p = &(control_strings[i][6]);
420                         ret = sscanf(p, "%d", &crit);
421                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
422                                 error_string = talloc_asprintf(mem_ctx, "invalid relax control syntax\n");
423                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
424                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
425                                 ldb_set_errstring(ldb, error_string);
426                                 talloc_free(error_string);
427                                 return NULL;
428                         }
429
430                         ctrl[i] = talloc(ctrl, struct ldb_control);
431                         if (!ctrl[i]) {
432                                 ldb_oom(ldb);
433                                 return NULL;
434                         }
435                         ctrl[i]->oid = LDB_CONTROL_RELAX_OID;
436                         ctrl[i]->critical = crit;
437                         ctrl[i]->data = NULL;
438
439                         continue;
440                 }
441
442                 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
443                         const char *p;
444                         int crit, ret;
445
446                         p = &(control_strings[i][13]);
447                         ret = sscanf(p, "%d", &crit);
448                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
449                                 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
450                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
451                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
452                                 ldb_set_errstring(ldb, error_string);
453                                 talloc_free(error_string);
454                                 return NULL;
455                         }
456
457                         ctrl[i] = talloc(ctrl, struct ldb_control);
458                         if (!ctrl[i]) {
459                                 ldb_oom(ldb);
460                                 return NULL;
461                         }
462                         ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
463                         ctrl[i]->critical = crit;
464                         ctrl[i]->data = NULL;
465
466                         continue;
467                 }
468
469                 if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
470                         struct ldb_paged_control *control;
471                         const char *p;
472                         int crit, size, ret;
473                        
474                         p = &(control_strings[i][14]);
475                         ret = sscanf(p, "%d:%d", &crit, &size);
476
477                         if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
478                                 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
479                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
480                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
481                                 ldb_set_errstring(ldb, error_string);
482                                 talloc_free(error_string);
483                                 return NULL;
484                         }
485
486                         ctrl[i] = talloc(ctrl, struct ldb_control);
487                         if (!ctrl[i]) {
488                                 ldb_oom(ldb);
489                                 return NULL;
490                         }
491                         ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
492                         ctrl[i]->critical = crit;
493                         control = talloc(ctrl[i], struct ldb_paged_control);
494                         control->size = size;
495                         control->cookie = NULL;
496                         control->cookie_len = 0;
497                         ctrl[i]->data = control;
498
499                         continue;
500                 }
501
502                 if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
503                         struct ldb_server_sort_control **control;
504                         const char *p;
505                         char attr[256];
506                         char rule[128];
507                         int crit, rev, ret;
508
509                         attr[0] = '\0';
510                         rule[0] = '\0';
511                         p = &(control_strings[i][12]);
512                         ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
513                         if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
514                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
515                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
516                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
517                                 ldb_set_errstring(ldb, error_string);
518                                 talloc_free(error_string);
519                                 return NULL;
520                         }
521                         ctrl[i] = talloc(ctrl, struct ldb_control);
522                         if (!ctrl[i]) {
523                                 ldb_oom(ldb);
524                                 return NULL;
525                         }
526                         ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
527                         ctrl[i]->critical = crit;
528                         control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
529                         control[0] = talloc(control, struct ldb_server_sort_control);
530                         control[0]->attributeName = talloc_strdup(control, attr);
531                         if (rule[0])
532                                 control[0]->orderingRule = talloc_strdup(control, rule);
533                         else
534                                 control[0]->orderingRule = NULL;
535                         control[0]->reverse = rev;
536                         control[1] = NULL;
537                         ctrl[i]->data = control;
538
539                         continue;
540                 }
541
542                 if (strncmp(control_strings[i], "notification:", 13) == 0) {
543                         const char *p;
544                         int crit, ret;
545
546                         p = &(control_strings[i][13]);
547                         ret = sscanf(p, "%d", &crit);
548                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
549                                 error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
550                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
551                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
552                                 ldb_set_errstring(ldb, error_string);
553                                 talloc_free(error_string);
554                                 return NULL;
555                         }
556
557                         ctrl[i] = talloc(ctrl, struct ldb_control);
558                         if (!ctrl[i]) {
559                                 ldb_oom(ldb);
560                                 return NULL;
561                         }
562                         ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
563                         ctrl[i]->critical = crit;
564                         ctrl[i]->data = NULL;
565
566                         continue;
567                 }
568
569                 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
570                         const char *p;
571                         int crit, ret;
572
573                         p = &(control_strings[i][13]);
574                         ret = sscanf(p, "%d", &crit);
575                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
576                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
577                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
578                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
579                                 ldb_set_errstring(ldb, error_string);
580                                 talloc_free(error_string);
581                                 return NULL;
582                         }
583
584                         ctrl[i] = talloc(ctrl, struct ldb_control);
585                         if (!ctrl[i]) {
586                                 ldb_oom(ldb);
587                                 return NULL;
588                         }
589                         ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
590                         ctrl[i]->critical = crit;
591                         ctrl[i]->data = NULL;
592
593                         continue;
594                 }
595
596                 if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
597                         const char *p;
598                         int crit, ret;
599
600                         p = &(control_strings[i][22]);
601                         ret = sscanf(p, "%d", &crit);
602                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
603                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
604                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
605                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
606                                 ldb_set_errstring(ldb, error_string);
607                                 talloc_free(error_string);
608                                 return NULL;
609                         }
610
611                         ctrl[i] = talloc(ctrl, struct ldb_control);
612                         if (!ctrl[i]) {
613                                 ldb_oom(ldb);
614                                 return NULL;
615                         }
616                         ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
617                         ctrl[i]->critical = crit;
618                         ctrl[i]->data = NULL;
619
620                         continue;
621                 }
622
623                 if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
624                         const char *p;
625                         int crit, ret;
626
627                         p = &(control_strings[i][14]);
628                         ret = sscanf(p, "%d", &crit);
629                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
630                                 error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
631                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
632                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
633                                 ldb_set_errstring(ldb, error_string);
634                                 talloc_free(error_string);
635                                 return NULL;
636                         }
637
638                         ctrl[i] = talloc(ctrl, struct ldb_control);
639                         if (!ctrl[i]) {
640                                 ldb_oom(ldb);
641                                 return NULL;
642                         }
643                         ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
644                         ctrl[i]->critical = crit;
645                         ctrl[i]->data = NULL;
646
647                         continue;
648                 }
649
650                 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
651                         const char *p;
652                         int crit, ret;
653
654                         p = &(control_strings[i][18]);
655                         ret = sscanf(p, "%d", &crit);
656                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
657                                 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
658                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
659                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
660                                 ldb_set_errstring(ldb, error_string);
661                                 talloc_free(error_string);
662                                 return NULL;
663                         }
664
665                         ctrl[i] = talloc(ctrl, struct ldb_control);
666                         if (!ctrl[i]) {
667                                 ldb_oom(ldb);
668                                 return NULL;
669                         }
670                         ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
671                         ctrl[i]->critical = crit;
672                         ctrl[i]->data = NULL;
673
674                         continue;
675                 }
676
677                 /* no controls matched, throw an error */
678                 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
679                 return NULL;
680         }
681
682         ctrl[i] = NULL;
683
684         return ctrl;
685 }
686
687