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