9f404cd0bdedad3b8856c023724e4308877bd879
[abartlet/samba.git/.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, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb_controls.c
27  *
28  *  Component: ldb controls utility functions
29  *
30  *  Description: helper functions for control modules
31  *
32  *  Author: Simo Sorce
33  */
34
35 #include "ldb_includes.h"
36
37 /* check if a control with the specified "oid" exist and return it */
38 /* returns NULL if not found */
39 struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
40 {
41         int i;
42
43         /* check if there's a paged request control */
44         if (req->controls != NULL) {
45                 for (i = 0; req->controls[i]; i++) {
46                         if (strcmp(oid, req->controls[i]->oid) == 0) {
47                                 break;
48                         }
49                 }
50
51                 return req->controls[i];
52         }
53
54         return NULL;
55 }
56
57 /* saves the current controls list into the "saver" and replace the one in req with a new one excluding
58 the "exclude" control */
59 /* returns False on error */
60 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
61 {
62         struct ldb_control **lcs;
63         int i, j;
64
65         *saver = req->controls;
66         for (i = 0; req->controls[i]; i++);
67         if (i == 1) {
68                 req->controls = NULL;
69                 return 1;
70         }
71
72         lcs = talloc_array(req, struct ldb_control *, i);
73         if (!lcs) {
74                 return 0;
75         }
76
77         for (i = 0, j = 0; (*saver)[i]; i++) {
78                 if (exclude == (*saver)[i]) continue;
79                 lcs[j] = (*saver)[i];
80                 j++;
81         }
82         lcs[j] = NULL;
83
84         req->controls = lcs;
85         return 1;
86 }
87
88 /* check if there's any control marked as critical in the list */
89 /* return True if any, False if none */
90 int check_critical_controls(struct ldb_control **controls)
91 {
92         int i;
93
94         if (controls == NULL) {
95                 return 0;
96         }
97
98         for (i = 0; controls[i]; i++) {
99                 if (controls[i]->critical) {
100                         return 1;
101                 }
102         }
103
104         return 0;
105 }
106
107 int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
108 {
109         unsigned n;
110         struct ldb_control **ctrls;
111         struct ldb_control *ctrl;
112
113         for (n=0; req->controls && req->controls[n];) { n++; }
114
115         ctrls = talloc_realloc(req, req->controls,
116                                struct ldb_control *,
117                                n + 2);
118         if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
119         req->controls = ctrls;
120         ctrls[n] = NULL;
121         ctrls[n+1] = NULL;
122
123         ctrl = talloc(ctrls, struct ldb_control);
124         if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
125
126         ctrl->oid       = talloc_strdup(ctrl, oid);
127         if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
128         ctrl->critical  = critical;
129         ctrl->data      = data;
130
131         ctrls[n] = ctrl;
132         return LDB_SUCCESS;
133 }
134
135 /* Parse controls from the format used on the command line and in ejs */
136
137 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
138 {
139         int i;
140         struct ldb_control **ctrl;
141
142         char *error_string = NULL;
143
144         if (control_strings == NULL || control_strings[0] == NULL)
145                 return NULL;
146
147         for (i = 0; control_strings[i]; i++);
148
149         ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
150
151         for (i = 0; control_strings[i]; i++) {
152                 if (strncmp(control_strings[i], "vlv:", 4) == 0) {
153                         struct ldb_vlv_req_control *control;
154                         const char *p;
155                         char attr[1024];
156                         char ctxid[1024];
157                         int crit, bc, ac, os, cc, ret;
158
159                         attr[0] = '\0';
160                         ctxid[0] = '\0';
161                         p = &(control_strings[i][4]);
162                         ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
163                         if (ret < 5) {
164                                 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
165                         }
166                                
167                         if ((ret < 4) || (crit < 0) || (crit > 1)) {
168                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
169                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
170                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, s = string, o = b64 binary blob");
171                                 ldb_set_errstring(ldb, error_string);
172                                 talloc_free(error_string);
173                                 return NULL;
174                         }
175                         if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
176                                 ldb_oom(ldb);
177                                 return NULL;
178                         }
179                         ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
180                         ctrl[i]->critical = crit;
181                         if (!(control = talloc(ctrl[i],
182                                                struct ldb_vlv_req_control))) {
183                                 ldb_oom(ldb);
184                                 return NULL;
185                         }
186                         control->beforeCount = bc;
187                         control->afterCount = ac;
188                         if (attr[0]) {
189                                 control->type = 1;
190                                 control->match.gtOrEq.value = talloc_strdup(control, attr);
191                                 control->match.gtOrEq.value_len = strlen(attr);
192                         } else {
193                                 control->type = 0;
194                                 control->match.byOffset.offset = os;
195                                 control->match.byOffset.contentCount = cc;
196                         }
197                         if (ctxid[0]) {
198                                 control->ctxid_len = ldb_base64_decode(ctxid);
199                                 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
200                         } else {
201                                 control->ctxid_len = 0;
202                                 control->contextId = NULL;
203                         }
204                         ctrl[i]->data = control;
205
206                         continue;
207                 }
208
209                 if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
210                         struct ldb_dirsync_control *control;
211                         const char *p;
212                         char cookie[1024];
213                         int crit, flags, max_attrs, ret;
214                        
215                         cookie[0] = '\0';
216                         p = &(control_strings[i][8]);
217                         ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
218
219                         if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
220                                 error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
221                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
222                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number, o = b64 binary blob");
223                                 ldb_set_errstring(ldb, error_string);
224                                 talloc_free(error_string);
225                                 return NULL;
226                         }
227
228                         /* w2k3 seems to ignore the parameter,
229                          * but w2k sends a wrong cookie when this value is to small
230                          * this would cause looping forever, while getting
231                          * the same data and same cookie forever
232                          */
233                         if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
234
235                         ctrl[i] = talloc(ctrl, struct ldb_control);
236                         ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
237                         ctrl[i]->critical = crit;
238                         control = talloc(ctrl[i], struct ldb_dirsync_control);
239                         control->flags = flags;
240                         control->max_attributes = max_attrs;
241                         if (*cookie) {
242                                 control->cookie_len = ldb_base64_decode(cookie);
243                                 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
244                         } else {
245                                 control->cookie = NULL;
246                                 control->cookie_len = 0;
247                         }
248                         ctrl[i]->data = control;
249
250                         continue;
251                 }
252
253                 if (strncmp(control_strings[i], "asq:", 4) == 0) {
254                         struct ldb_asq_control *control;
255                         const char *p;
256                         char attr[256];
257                         int crit, ret;
258
259                         attr[0] = '\0';
260                         p = &(control_strings[i][4]);
261                         ret = sscanf(p, "%d:%255[^$]", &crit, attr);
262                         if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
263                                 error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
264                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
265                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
266                                 ldb_set_errstring(ldb, error_string);
267                                 talloc_free(error_string);
268                                 return NULL;
269                         }
270
271                         ctrl[i] = talloc(ctrl, struct ldb_control);
272                         if (!ctrl[i]) {
273                                 ldb_oom(ldb);
274                                 return NULL;
275                         }
276                         ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
277                         ctrl[i]->critical = crit;
278                         control = talloc(ctrl[i], struct ldb_asq_control);
279                         control->request = 1;
280                         control->source_attribute = talloc_strdup(control, attr);
281                         control->src_attr_len = strlen(attr);
282                         ctrl[i]->data = control;
283
284                         continue;
285                 }
286
287                 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
288                         struct ldb_extended_dn_control *control;
289                         const char *p;
290                         int crit, type, ret;
291
292                         p = &(control_strings[i][12]);
293                         ret = sscanf(p, "%d:%d", &crit, &type);
294                         if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
295                                 error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
296                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):type(b)\n");
297                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
298                                 ldb_set_errstring(ldb, error_string);
299                                 talloc_free(error_string);
300                                 return NULL;
301                         }
302
303                         ctrl[i] = talloc(ctrl, struct ldb_control);
304                         if (!ctrl[i]) {
305                                 ldb_oom(ldb);
306                                 return NULL;
307                         }
308                         ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
309                         ctrl[i]->critical = crit;
310                         control = talloc(ctrl[i], struct ldb_extended_dn_control);
311                         control->type = type;
312                         ctrl[i]->data = control;
313
314                         continue;
315                 }
316
317                 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
318                         struct ldb_sd_flags_control *control;
319                         const char *p;
320                         int crit, ret;
321                         unsigned secinfo_flags;
322
323                         p = &(control_strings[i][9]);
324                         ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
325                         if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
326                                 error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
327                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
328                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
329                                 ldb_set_errstring(ldb, error_string);
330                                 talloc_free(error_string);
331                                 return NULL;
332                         }
333
334                         ctrl[i] = talloc(ctrl, struct ldb_control);
335                         if (!ctrl[i]) {
336                                 ldb_oom(ldb);
337                                 return NULL;
338                         }
339                         ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
340                         ctrl[i]->critical = crit;
341                         control = talloc(ctrl[i], struct ldb_sd_flags_control);
342                         control->secinfo_flags = secinfo_flags;
343                         ctrl[i]->data = control;
344
345                         continue;
346                 }
347
348                 if (strncmp(control_strings[i], "search_options:", 15) == 0) {
349                         struct ldb_search_options_control *control;
350                         const char *p;
351                         int crit, ret;
352                         unsigned search_options;
353
354                         p = &(control_strings[i][15]);
355                         ret = sscanf(p, "%d:%u", &crit, &search_options);
356                         if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
357                                 error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
358                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(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_SEARCH_OPTIONS_OID;
371                         ctrl[i]->critical = crit;
372                         control = talloc(ctrl[i], struct ldb_search_options_control);
373                         control->search_options = search_options;
374                         ctrl[i]->data = control;
375
376                         continue;
377                 }
378
379                 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
380                         const char *p;
381                         int crit, ret;
382
383                         p = &(control_strings[i][13]);
384                         ret = sscanf(p, "%d", &crit);
385                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
386                                 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
387                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
388                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
389                                 ldb_set_errstring(ldb, error_string);
390                                 talloc_free(error_string);
391                                 return NULL;
392                         }
393
394                         ctrl[i] = talloc(ctrl, struct ldb_control);
395                         if (!ctrl[i]) {
396                                 ldb_oom(ldb);
397                                 return NULL;
398                         }
399                         ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
400                         ctrl[i]->critical = crit;
401                         ctrl[i]->data = NULL;
402
403                         continue;
404                 }
405
406                 if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
407                         struct ldb_paged_control *control;
408                         const char *p;
409                         int crit, size, ret;
410                        
411                         p = &(control_strings[i][14]);
412                         ret = sscanf(p, "%d:%d", &crit, &size);
413
414                         if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
415                                 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
416                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
417                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, n = number");
418                                 ldb_set_errstring(ldb, error_string);
419                                 talloc_free(error_string);
420                                 return NULL;
421                         }
422
423                         ctrl[i] = talloc(ctrl, struct ldb_control);
424                         if (!ctrl[i]) {
425                                 ldb_oom(ldb);
426                                 return NULL;
427                         }
428                         ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
429                         ctrl[i]->critical = crit;
430                         control = talloc(ctrl[i], struct ldb_paged_control);
431                         control->size = size;
432                         control->cookie = NULL;
433                         control->cookie_len = 0;
434                         ctrl[i]->data = control;
435
436                         continue;
437                 }
438
439                 if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
440                         struct ldb_server_sort_control **control;
441                         const char *p;
442                         char attr[256];
443                         char rule[128];
444                         int crit, rev, ret;
445
446                         attr[0] = '\0';
447                         rule[0] = '\0';
448                         p = &(control_strings[i][12]);
449                         ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
450                         if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
451                                 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
452                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
453                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean, s = string");
454                                 ldb_set_errstring(ldb, error_string);
455                                 talloc_free(error_string);
456                                 return NULL;
457                         }
458                         ctrl[i] = talloc(ctrl, struct ldb_control);
459                         if (!ctrl[i]) {
460                                 ldb_oom(ldb);
461                                 return NULL;
462                         }
463                         ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
464                         ctrl[i]->critical = crit;
465                         control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
466                         control[0] = talloc(control, struct ldb_server_sort_control);
467                         control[0]->attributeName = talloc_strdup(control, attr);
468                         if (rule[0])
469                                 control[0]->orderingRule = talloc_strdup(control, rule);
470                         else
471                                 control[0]->orderingRule = NULL;
472                         control[0]->reverse = rev;
473                         control[1] = NULL;
474                         ctrl[i]->data = control;
475
476                         continue;
477                 }
478
479                 if (strncmp(control_strings[i], "notification:", 13) == 0) {
480                         const char *p;
481                         int crit, ret;
482
483                         p = &(control_strings[i][13]);
484                         ret = sscanf(p, "%d", &crit);
485                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
486                                 error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
487                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
488                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
489                                 ldb_set_errstring(ldb, error_string);
490                                 talloc_free(error_string);
491                                 return NULL;
492                         }
493
494                         ctrl[i] = talloc(ctrl, struct ldb_control);
495                         if (!ctrl[i]) {
496                                 ldb_oom(ldb);
497                                 return NULL;
498                         }
499                         ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
500                         ctrl[i]->critical = crit;
501                         ctrl[i]->data = NULL;
502
503                         continue;
504                 }
505
506                 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
507                         const char *p;
508                         int crit, ret;
509
510                         p = &(control_strings[i][13]);
511                         ret = sscanf(p, "%d", &crit);
512                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
513                                 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
514                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
515                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
516                                 ldb_set_errstring(ldb, error_string);
517                                 talloc_free(error_string);
518                                 return NULL;
519                         }
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_SHOW_DELETED_OID;
527                         ctrl[i]->critical = crit;
528                         ctrl[i]->data = NULL;
529
530                         continue;
531                 }
532
533                 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
534                         const char *p;
535                         int crit, ret;
536
537                         p = &(control_strings[i][18]);
538                         ret = sscanf(p, "%d", &crit);
539                         if ((ret != 1) || (crit < 0) || (crit > 1)) {
540                                 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
541                                 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
542                                 error_string = talloc_asprintf_append(error_string, "   note: b = boolean");
543                                 ldb_set_errstring(ldb, error_string);
544                                 talloc_free(error_string);
545                                 return NULL;
546                         }
547
548                         ctrl[i] = talloc(ctrl, struct ldb_control);
549                         if (!ctrl[i]) {
550                                 ldb_oom(ldb);
551                                 return NULL;
552                         }
553                         ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
554                         ctrl[i]->critical = crit;
555                         ctrl[i]->data = NULL;
556
557                         continue;
558                 }
559
560                 /* no controls matched, throw an error */
561                 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
562                 return NULL;
563         }
564
565         ctrl[i] = NULL;
566
567         return ctrl;
568 }
569
570