4 Copyright (C) Simo Sorce 2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
25 * Name: ldb_controls.c
27 * Component: ldb controls utility functions
29 * Description: helper functions for control modules
34 #include "ldb_private.h"
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)
42 if (req->controls != NULL) {
43 for (i = 0; req->controls[i]; i++) {
44 if (strcmp(oid, req->controls[i]->oid) == 0) {
49 return req->controls[i];
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)
61 if (rep->controls != NULL) {
62 for (i = 0; rep->controls[i]; i++) {
63 if (strcmp(oid, rep->controls[i]->oid) == 0) {
68 return rep->controls[i];
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)
79 struct ldb_control **lcs;
82 *saver = req->controls;
83 for (i = 0; req->controls[i]; i++);
89 lcs = talloc_array(req, struct ldb_control *, i);
94 for (i = 0, j = 0; (*saver)[i]; i++) {
95 if (exclude == (*saver)[i]) continue;
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)
111 if (controls == NULL) {
115 for (i = 0; controls[i]; i++) {
116 if (controls[i]->critical) {
124 int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
127 struct ldb_control **ctrls;
128 struct ldb_control *ctrl;
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;
138 ctrls = talloc_array(req,
139 struct ldb_control *,
141 if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
143 for (i=0; i<n; i++) {
144 ctrls[i] = req->controls[i];
147 req->controls = ctrls;
151 ctrl = talloc(ctrls, struct ldb_control);
152 if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
154 ctrl->oid = talloc_strdup(ctrl, oid);
155 if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
156 ctrl->critical = critical;
163 /* Parse controls from the format used on the command line and in ejs */
165 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
168 struct ldb_control **ctrl;
170 char *error_string = NULL;
172 if (control_strings == NULL || control_strings[0] == NULL)
175 for (i = 0; control_strings[i]; i++);
177 ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
179 for (i = 0; control_strings[i]; i++) {
180 if (strncmp(control_strings[i], "vlv:", 4) == 0) {
181 struct ldb_vlv_req_control *control;
185 int crit, bc, ac, os, cc, ret;
189 p = &(control_strings[i][4]);
190 ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
192 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
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);
203 if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
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))) {
214 control->beforeCount = bc;
215 control->afterCount = ac;
218 control->match.gtOrEq.value = talloc_strdup(control, attr);
219 control->match.gtOrEq.value_len = strlen(attr);
222 control->match.byOffset.offset = os;
223 control->match.byOffset.contentCount = cc;
226 control->ctxid_len = ldb_base64_decode(ctxid);
227 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
229 control->ctxid_len = 0;
230 control->contextId = NULL;
232 ctrl[i]->data = control;
237 if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
238 struct ldb_dirsync_control *control;
241 int crit, flags, max_attrs, ret;
244 p = &(control_strings[i][8]);
245 ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
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);
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
261 if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
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;
270 control->cookie_len = ldb_base64_decode(cookie);
271 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
273 control->cookie = NULL;
274 control->cookie_len = 0;
276 ctrl[i]->data = control;
281 if (strncmp(control_strings[i], "asq:", 4) == 0) {
282 struct ldb_asq_control *control;
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);
299 ctrl[i] = talloc(ctrl, struct ldb_control);
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;
315 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
316 struct ldb_extended_dn_control *control;
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);
337 control = talloc(ctrl, struct ldb_extended_dn_control);
338 control->type = type;
341 ctrl[i] = talloc(ctrl, struct ldb_control);
346 ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
347 ctrl[i]->critical = crit;
348 ctrl[i]->data = talloc_steal(ctrl[i], control);
353 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
354 struct ldb_sd_flags_control *control;
357 unsigned secinfo_flags;
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);
370 ctrl[i] = talloc(ctrl, struct ldb_control);
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;
384 if (strncmp(control_strings[i], "search_options:", 15) == 0) {
385 struct ldb_search_options_control *control;
388 unsigned search_options;
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);
401 ctrl[i] = talloc(ctrl, struct ldb_control);
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;
415 if (strncmp(control_strings[i], "relax:", 6) == 0) {
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);
430 ctrl[i] = talloc(ctrl, struct ldb_control);
435 ctrl[i]->oid = LDB_CONTROL_RELAX_OID;
436 ctrl[i]->critical = crit;
437 ctrl[i]->data = NULL;
442 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
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);
457 ctrl[i] = talloc(ctrl, struct ldb_control);
462 ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
463 ctrl[i]->critical = crit;
464 ctrl[i]->data = NULL;
469 if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
470 struct ldb_paged_control *control;
474 p = &(control_strings[i][14]);
475 ret = sscanf(p, "%d:%d", &crit, &size);
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);
486 ctrl[i] = talloc(ctrl, struct ldb_control);
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;
502 if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
503 struct ldb_server_sort_control **control;
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);
521 ctrl[i] = talloc(ctrl, struct ldb_control);
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);
532 control[0]->orderingRule = talloc_strdup(control, rule);
534 control[0]->orderingRule = NULL;
535 control[0]->reverse = rev;
537 ctrl[i]->data = control;
542 if (strncmp(control_strings[i], "notification:", 13) == 0) {
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);
557 ctrl[i] = talloc(ctrl, struct ldb_control);
562 ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
563 ctrl[i]->critical = crit;
564 ctrl[i]->data = NULL;
569 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
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);
584 ctrl[i] = talloc(ctrl, struct ldb_control);
589 ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
590 ctrl[i]->critical = crit;
591 ctrl[i]->data = NULL;
596 if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
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);
611 ctrl[i] = talloc(ctrl, struct ldb_control);
616 ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
617 ctrl[i]->critical = crit;
618 ctrl[i]->data = NULL;
623 if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
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);
638 ctrl[i] = talloc(ctrl, struct ldb_control);
643 ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
644 ctrl[i]->critical = crit;
645 ctrl[i]->data = NULL;
650 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
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);
665 ctrl[i] = talloc(ctrl, struct ldb_control);
670 ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
671 ctrl[i]->critical = crit;
672 ctrl[i]->data = NULL;
677 /* no controls matched, throw an error */
678 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);