dcesrv_core: better fault codes dcesrv_auth_prepare_auth3()
[Samba.git] / lib / ldb / common / ldb_controls.c
blob3bf89d844f9037ee91dabf53717eefbd11535aed
1 /*
2 ldb database library
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
8 ** under the LGPL
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
31 * Author: Simo Sorce
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_controls_get_control(struct ldb_control **controls, const char *oid)
40 unsigned int i;
42 if (controls != NULL) {
43 for (i = 0; controls[i]; i++) {
44 if (controls[i]->oid && strcmp(oid, controls[i]->oid) == 0) {
45 break;
49 return controls[i];
52 return NULL;
55 /* check if a control with the specified "oid" exist and return it */
56 /* returns NULL if not found */
57 struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
59 return ldb_controls_get_control(req->controls, oid);
62 /* check if a control with the specified "oid" exist and return it */
63 /* returns NULL if not found */
64 struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid)
66 return ldb_controls_get_control(rep->controls, oid);
70 * Saves the current controls list into the "saver" (can also be NULL) and
71 * replace the one in "req" with a new one excluding the "exclude" control
72 * (if it is NULL then the list remains the same)
74 * Returns 0 on error.
76 int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
78 struct ldb_control **lcs, **lcs_old;
79 unsigned int i, j;
81 lcs_old = req->controls;
82 if (saver != NULL) {
83 *saver = lcs_old;
86 for (i = 0; req->controls && req->controls[i]; i++);
87 if (i == 0) {
88 req->controls = NULL;
89 return 1;
92 lcs = talloc_array(req, struct ldb_control *, i + 1);
93 if (!lcs) {
94 return 0;
97 for (i = 0, j = 0; lcs_old[i]; i++) {
98 if (exclude == lcs_old[i]) continue;
99 lcs[j] = lcs_old[i];
100 j++;
102 lcs[j] = NULL;
104 req->controls = talloc_realloc(req, lcs, struct ldb_control *, j + 1);
105 if (req->controls == NULL) {
106 return 0;
108 return 1;
112 * Returns a list of controls, except the one specified with "exclude" (can
113 * also be NULL). Included controls become a child of returned list if they
114 * were children of "controls_in".
116 * Returns NULL on error (OOM) or an empty control list.
118 struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in,
119 TALLOC_CTX *mem_ctx,
120 struct ldb_control *exclude)
122 struct ldb_control **lcs = NULL;
123 unsigned int i, j, n;
125 for (i = 0; controls_in && controls_in[i]; i++);
126 if (i == 0) {
127 return NULL;
129 n = i;
131 for (i = 0, j = 0; controls_in && controls_in[i]; i++) {
132 if (exclude == controls_in[i]) continue;
134 if (!lcs) {
135 /* Allocate here so if we remove the only
136 * control, or there were no controls, we
137 * don't allocate at all, and just return
138 * NULL */
139 lcs = talloc_array(mem_ctx, struct ldb_control *,
140 n + 1);
141 if (!lcs) {
142 return NULL;
146 lcs[j] = controls_in[i];
147 talloc_reparent(controls_in, lcs, lcs[j]);
148 j++;
150 if (lcs) {
151 lcs[j] = NULL;
153 lcs = talloc_realloc(mem_ctx, lcs, struct ldb_control *, j + 1);
156 return lcs;
159 /* check if there's any control marked as critical in the list */
160 /* return True if any, False if none */
161 int ldb_check_critical_controls(struct ldb_control **controls)
163 unsigned int i;
165 if (controls == NULL) {
166 return 0;
169 for (i = 0; controls[i]; i++) {
170 if (controls[i]->critical) {
171 return 1;
175 return 0;
178 int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data)
180 unsigned int i, n;
181 struct ldb_control **ctrls;
182 struct ldb_control *ctrl;
184 for (n=0; req->controls && req->controls[n];n++) {
185 /* having two controls of the same OID makes no sense */
186 if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
187 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
191 ctrls = talloc_array(req,
192 struct ldb_control *,
193 n + 2);
194 if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
196 for (i=0; i<n; i++) {
197 ctrls[i] = req->controls[i];
200 req->controls = ctrls;
201 ctrls[n] = NULL;
202 ctrls[n+1] = NULL;
204 ctrl = talloc(ctrls, struct ldb_control);
205 if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
207 ctrl->oid = talloc_strdup(ctrl, oid);
208 if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
209 ctrl->critical = critical;
210 ctrl->data = data;
212 ctrls[n] = ctrl;
213 return LDB_SUCCESS;
216 int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data)
218 unsigned n;
219 struct ldb_control **ctrls;
220 struct ldb_control *ctrl;
222 for (n=0; ares->controls && ares->controls[n];) {
223 /* having two controls of the same OID makes no sense */
224 if (ares->controls[n]->oid && strcmp(oid, ares->controls[n]->oid) == 0) {
225 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
227 n++;
230 ctrls = talloc_realloc(ares, ares->controls,
231 struct ldb_control *,
232 n + 2);
233 if (!ctrls) return LDB_ERR_OPERATIONS_ERROR;
234 ares->controls = ctrls;
235 ctrls[n] = NULL;
236 ctrls[n+1] = NULL;
238 ctrl = talloc(ctrls, struct ldb_control);
239 if (!ctrl) return LDB_ERR_OPERATIONS_ERROR;
241 ctrl->oid = talloc_strdup(ctrl, oid);
242 if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR;
243 ctrl->critical = critical;
244 ctrl->data = data;
246 ctrls[n] = ctrl;
247 return LDB_SUCCESS;
250 /* Add a control to the request, replacing the old one if it is already in the request */
251 int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data)
253 unsigned int n;
254 int ret;
256 ret = ldb_request_add_control(req, oid, critical, data);
257 if (ret != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
258 return ret;
261 for (n=0; req->controls[n];n++) {
262 if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) {
263 req->controls[n]->critical = critical;
264 req->controls[n]->data = data;
265 return LDB_SUCCESS;
269 return LDB_ERR_OPERATIONS_ERROR;
273 * Return a control as string
274 * the project (ie. name:value1:value2:...:valuen
275 * The string didn't include the criticity of the critical flag
277 char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control)
279 char *res = NULL;
281 if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) {
282 struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control);
283 char *cookie;
284 if (rep_control == NULL) {
285 return NULL;
288 cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len);
289 if (cookie == NULL) {
290 return NULL;
292 if (cookie[0] != '\0') {
293 res = talloc_asprintf(mem_ctx, "%s:%d:%s",
294 LDB_CONTROL_PAGED_RESULTS_NAME,
295 control->critical,
296 cookie);
298 talloc_free(cookie);
299 } else {
300 res = talloc_asprintf(mem_ctx, "%s:%d",
301 LDB_CONTROL_PAGED_RESULTS_NAME,
302 control->critical);
304 return res;
307 if (strcmp(control->oid, LDB_CONTROL_VLV_RESP_OID) == 0) {
308 struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data,
309 struct ldb_vlv_resp_control);
311 char *cookie;
313 if (rep_control == NULL) {
314 return NULL;
317 cookie = ldb_base64_encode(mem_ctx,
318 (char *)rep_control->contextId,
319 rep_control->ctxid_len);
320 if (cookie == NULL) {
321 return NULL;
324 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%s",
325 LDB_CONTROL_VLV_RESP_NAME,
326 control->critical,
327 rep_control->targetPosition,
328 rep_control->contentCount,
329 rep_control->vlv_result,
330 cookie);
332 return res;
335 if (strcmp(control->oid, LDB_CONTROL_SORT_RESP_OID) == 0) {
336 struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data,
337 struct ldb_sort_resp_control);
339 if (rep_control == NULL) {
340 return NULL;
342 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s",
343 LDB_CONTROL_SORT_RESP_NAME,
344 control->critical,
345 rep_control->result,
346 rep_control->attr_desc);
348 return res;
351 if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) {
352 struct ldb_asq_control *rep_control = talloc_get_type(control->data,
353 struct ldb_asq_control);
355 if (rep_control == NULL) {
356 return NULL;
358 res = talloc_asprintf(mem_ctx, "%s:%d:%d",
359 LDB_CONTROL_ASQ_NAME,
360 control->critical,
361 rep_control->result);
363 return res;
366 if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_OID) == 0) {
367 char *cookie;
368 struct ldb_dirsync_control *rep_control = talloc_get_type(control->data,
369 struct ldb_dirsync_control);
371 if (rep_control == NULL) {
372 return NULL;
374 cookie = ldb_base64_encode(mem_ctx, rep_control->cookie,
375 rep_control->cookie_len);
376 if (cookie == NULL) {
377 return NULL;
379 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s",
380 LDB_CONTROL_DIRSYNC_NAME,
381 control->critical,
382 rep_control->flags,
383 rep_control->max_attributes,
384 cookie);
386 talloc_free(cookie);
387 return res;
389 if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_EX_OID) == 0) {
390 char *cookie;
391 struct ldb_dirsync_control *rep_control = talloc_get_type(control->data,
392 struct ldb_dirsync_control);
394 if (rep_control == NULL) {
395 return NULL;
397 cookie = ldb_base64_encode(mem_ctx, rep_control->cookie,
398 rep_control->cookie_len);
399 if (cookie == NULL) {
400 return NULL;
402 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s",
403 LDB_CONTROL_DIRSYNC_EX_NAME,
404 control->critical,
405 rep_control->flags,
406 rep_control->max_attributes,
407 cookie);
409 talloc_free(cookie);
410 return res;
413 if (strcmp(control->oid, LDB_CONTROL_VERIFY_NAME_OID) == 0) {
414 struct ldb_verify_name_control *rep_control = talloc_get_type(control->data, struct ldb_verify_name_control);
416 if (rep_control == NULL) {
417 return NULL;
419 if (rep_control->gc != NULL) {
420 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s",
421 LDB_CONTROL_VERIFY_NAME_NAME,
422 control->critical,
423 rep_control->flags,
424 rep_control->gc);
426 } else {
427 res = talloc_asprintf(mem_ctx, "%s:%d:%d",
428 LDB_CONTROL_VERIFY_NAME_NAME,
429 control->critical,
430 rep_control->flags);
432 return res;
436 * From here we don't know the control
438 if (control->data == NULL) {
440 * We don't know the control but there is no real data attached
441 * to it so we can represent it with local_oid:oid:criticity.
443 res = talloc_asprintf(mem_ctx, "local_oid:%s:%d",
444 control->oid,
445 control->critical);
446 } else {
447 res = talloc_asprintf(mem_ctx, "unknown oid:%s",
448 control->oid);
450 return res;
455 * A little trick to allow one to use constants defined in headers rather than
456 * hardwritten in the file.
457 * "sizeof" will return the \0 char as well so it will take the place of ":"
458 * in the length of the string.
460 #define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME))
462 /* Parse one string and return associated control if parsing is successful*/
463 struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings)
465 struct ldb_control *ctrl;
467 if (!(ctrl = talloc(mem_ctx, struct ldb_control))) {
468 ldb_oom(ldb);
469 return NULL;
472 if (LDB_CONTROL_CMP(control_strings,
473 LDB_CONTROL_VLV_REQ_NAME) == 0) {
474 struct ldb_vlv_req_control *control;
475 const char *p;
476 char attr[1024];
477 char ctxid[1024];
478 int crit, bc, ac, os, cc, ret;
480 attr[0] = '\0';
481 ctxid[0] = '\0';
482 p = &(control_strings[sizeof(LDB_CONTROL_VLV_REQ_NAME)]);
483 ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
484 /* We allow 2 ways to encode the GT_EQ case, because the
485 comparison string might contain null bytes or colons, which
486 would break sscanf (or indeed any parsing mechanism). */
487 if (ret == 3) {
488 ret = sscanf(p, "%d:%d:%d:>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
490 if (ret == 3) {
491 int len;
492 ret = sscanf(p, "%d:%d:%d:base64>=%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
493 len = ldb_base64_decode(attr);
494 if (len < 0) {
495 ret = -1;
499 if ((ret < 4) || (crit < 0) || (crit > 1)) {
500 ldb_set_errstring(ldb,
501 "invalid VLV control syntax\n"
502 " syntax: crit(b):bc(n):ac(n):"
503 "{os(n):cc(n)|>=val(s)|base64>=val(o)}[:ctxid(o)]\n"
504 " note: b = boolean, n = number, s = string, o = b64 binary blob");
505 talloc_free(ctrl);
506 return NULL;
508 ctrl->oid = LDB_CONTROL_VLV_REQ_OID;
509 ctrl->critical = crit;
510 if (!(control = talloc(ctrl,
511 struct ldb_vlv_req_control))) {
512 ldb_oom(ldb);
513 talloc_free(ctrl);
514 return NULL;
516 control->beforeCount = bc;
517 control->afterCount = ac;
518 if (attr[0]) {
519 control->type = 1;
520 control->match.gtOrEq.value = talloc_strdup(control, attr);
521 control->match.gtOrEq.value_len = strlen(attr);
522 } else {
523 control->type = 0;
524 control->match.byOffset.offset = os;
525 control->match.byOffset.contentCount = cc;
527 if (ctxid[0]) {
528 int len = ldb_base64_decode(ctxid);
529 if (len < 0) {
530 ldb_set_errstring(ldb,
531 "invalid VLV context_id\n");
532 talloc_free(ctrl);
533 return NULL;
535 control->ctxid_len = len;
536 control->contextId = talloc_memdup(control, ctxid,
537 control->ctxid_len);
538 if (control->contextId == NULL) {
539 ldb_oom(ldb);
540 talloc_free(ctrl);
541 return NULL;
543 } else {
544 control->ctxid_len = 0;
545 control->contextId = NULL;
547 ctrl->data = control;
549 return ctrl;
552 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) {
553 struct ldb_dirsync_control *control;
554 const char *p;
555 char *cookie = NULL;
556 int crit, max_attrs, ret;
557 uint32_t flags;
559 cookie = talloc_zero_array(ctrl, char,
560 strlen(control_strings) + 1);
561 if (cookie == NULL) {
562 ldb_oom(ldb);
563 talloc_free(ctrl);
564 return NULL;
567 p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]);
568 ret = sscanf(p, "%d:%u:%d:%[^$]", &crit, &flags, &max_attrs, cookie);
570 if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
571 ldb_set_errstring(ldb,
572 "invalid dirsync control syntax\n"
573 " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
574 " note: b = boolean, n = number, o = b64 binary blob");
575 talloc_free(ctrl);
576 return NULL;
579 /* w2k3 seems to ignore the parameter,
580 * but w2k sends a wrong cookie when this value is to small
581 * this would cause looping forever, while getting
582 * the same data and same cookie forever
584 if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
586 ctrl->oid = LDB_CONTROL_DIRSYNC_OID;
587 ctrl->critical = crit;
588 control = talloc(ctrl, struct ldb_dirsync_control);
589 if (control == NULL) {
590 ldb_oom(ldb);
591 talloc_free(ctrl);
592 return NULL;
594 control->flags = flags;
595 control->max_attributes = max_attrs;
596 if (*cookie) {
597 int len = ldb_base64_decode(cookie);
598 if (len < 0) {
599 ldb_set_errstring(ldb,
600 "invalid dirsync cookie\n");
601 talloc_free(ctrl);
602 return NULL;
604 control->cookie_len = len;
605 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
606 if (control->cookie == NULL) {
607 ldb_oom(ldb);
608 talloc_free(ctrl);
609 return NULL;
611 } else {
612 control->cookie = NULL;
613 control->cookie_len = 0;
615 ctrl->data = control;
616 TALLOC_FREE(cookie);
618 return ctrl;
620 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_EX_NAME) == 0) {
621 struct ldb_dirsync_control *control;
622 const char *p;
623 char *cookie = NULL;
624 int crit, max_attrs, ret;
625 uint32_t flags;
627 cookie = talloc_zero_array(ctrl, char,
628 strlen(control_strings) + 1);
629 if (cookie == NULL) {
630 ldb_oom(ldb);
631 talloc_free(ctrl);
632 return NULL;
635 p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_EX_NAME)]);
636 ret = sscanf(p, "%d:%u:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
638 if ((ret < 3) || (crit < 0) || (crit > 1) || (max_attrs < 0)) {
639 ldb_set_errstring(ldb,
640 "invalid dirsync_ex control syntax\n"
641 " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"
642 " note: b = boolean, n = number, o = b64 binary blob");
643 talloc_free(ctrl);
644 return NULL;
647 /* w2k3 seems to ignore the parameter,
648 * but w2k sends a wrong cookie when this value is to small
649 * this would cause looping forever, while getting
650 * the same data and same cookie forever
652 if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
654 ctrl->oid = LDB_CONTROL_DIRSYNC_EX_OID;
655 ctrl->critical = crit;
656 control = talloc(ctrl, struct ldb_dirsync_control);
657 if (control == NULL) {
658 ldb_oom(ldb);
659 talloc_free(ctrl);
660 return NULL;
662 control->flags = flags;
663 control->max_attributes = max_attrs;
664 if (*cookie) {
665 int len = ldb_base64_decode(cookie);
666 if (len < 0) {
667 ldb_set_errstring(ldb,
668 "invalid dirsync_ex cookie"
669 " (probably too long)\n");
670 talloc_free(ctrl);
671 return NULL;
673 control->cookie_len = len;
674 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
675 if (control->cookie == NULL) {
676 ldb_oom(ldb);
677 talloc_free(ctrl);
678 return NULL;
680 } else {
681 control->cookie = NULL;
682 control->cookie_len = 0;
684 ctrl->data = control;
685 TALLOC_FREE(cookie);
687 return ctrl;
690 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_ASQ_NAME) == 0) {
691 struct ldb_asq_control *control;
692 const char *p;
693 char attr[256];
694 int crit, ret;
696 attr[0] = '\0';
697 p = &(control_strings[sizeof(LDB_CONTROL_ASQ_NAME)]);
698 ret = sscanf(p, "%d:%255[^$]", &crit, attr);
699 if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
700 ldb_set_errstring(ldb,
701 "invalid asq control syntax\n"
702 " syntax: crit(b):attr(s)\n"
703 " note: b = boolean, s = string");
704 talloc_free(ctrl);
705 return NULL;
708 ctrl->oid = LDB_CONTROL_ASQ_OID;
709 ctrl->critical = crit;
710 control = talloc(ctrl, struct ldb_asq_control);
711 if (control == NULL) {
712 ldb_oom(ldb);
713 talloc_free(ctrl);
714 return NULL;
716 control->request = 1;
717 control->source_attribute = talloc_strdup(control, attr);
718 control->src_attr_len = strlen(attr);
719 ctrl->data = control;
721 return ctrl;
724 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_EXTENDED_DN_NAME) == 0) {
725 struct ldb_extended_dn_control *control;
726 const char *p;
727 int crit, type, ret;
729 p = &(control_strings[sizeof(LDB_CONTROL_EXTENDED_DN_NAME)]);
730 ret = sscanf(p, "%d:%d", &crit, &type);
731 if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
732 ret = sscanf(p, "%d", &crit);
733 if ((ret != 1) || (crit < 0) || (crit > 1)) {
734 ldb_set_errstring(ldb,
735 "invalid extended_dn control syntax\n"
736 " syntax: crit(b)[:type(i)]\n"
737 " note: b = boolean\n"
738 " i = integer\n"
739 " valid values are: 0 - hexadecimal representation\n"
740 " 1 - normal string representation");
741 talloc_free(ctrl);
742 return NULL;
744 control = NULL;
745 } else {
746 control = talloc(ctrl, struct ldb_extended_dn_control);
747 if (control == NULL) {
748 ldb_oom(ldb);
749 talloc_free(ctrl);
750 return NULL;
752 control->type = type;
755 ctrl->oid = LDB_CONTROL_EXTENDED_DN_OID;
756 ctrl->critical = crit;
757 ctrl->data = control;
759 return ctrl;
762 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SD_FLAGS_NAME) == 0) {
763 struct ldb_sd_flags_control *control;
764 const char *p;
765 int crit, ret;
766 unsigned secinfo_flags;
768 p = &(control_strings[sizeof(LDB_CONTROL_SD_FLAGS_NAME)]);
769 ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
770 if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags > 0xF)) {
771 ldb_set_errstring(ldb,
772 "invalid sd_flags control syntax\n"
773 " syntax: crit(b):secinfo_flags(n)\n"
774 " note: b = boolean, n = number");
775 talloc_free(ctrl);
776 return NULL;
779 ctrl->oid = LDB_CONTROL_SD_FLAGS_OID;
780 ctrl->critical = crit;
781 control = talloc(ctrl, struct ldb_sd_flags_control);
782 if (control == NULL) {
783 ldb_oom(ldb);
784 talloc_free(ctrl);
785 return NULL;
788 control->secinfo_flags = secinfo_flags;
789 ctrl->data = control;
791 return ctrl;
794 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SEARCH_OPTIONS_NAME) == 0) {
795 struct ldb_search_options_control *control;
796 const char *p;
797 int crit, ret;
798 unsigned search_options;
800 p = &(control_strings[sizeof(LDB_CONTROL_SEARCH_OPTIONS_NAME)]);
801 ret = sscanf(p, "%d:%u", &crit, &search_options);
802 if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options > 0xF)) {
803 ldb_set_errstring(ldb,
804 "invalid search_options control syntax\n"
805 " syntax: crit(b):search_options(n)\n"
806 " note: b = boolean, n = number");
807 talloc_free(ctrl);
808 return NULL;
811 ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
812 ctrl->critical = crit;
813 control = talloc(ctrl, struct ldb_search_options_control);
814 if (control == NULL) {
815 ldb_oom(ldb);
816 talloc_free(ctrl);
817 return NULL;
820 control->search_options = search_options;
821 ctrl->data = control;
823 return ctrl;
826 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) {
827 const char *p;
828 int crit, ret;
830 p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]);
831 ret = sscanf(p, "%d", &crit);
832 if ((ret != 1) || (crit < 0) || (crit > 1)) {
833 ldb_set_errstring(ldb,
834 "invalid bypassoperational control syntax\n"
835 " syntax: crit(b)\n"
836 " note: b = boolean");
837 talloc_free(ctrl);
838 return NULL;
841 ctrl->oid = LDB_CONTROL_BYPASS_OPERATIONAL_OID;
842 ctrl->critical = crit;
843 ctrl->data = NULL;
845 return ctrl;
848 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RELAX_NAME) == 0) {
849 const char *p;
850 int crit, ret;
852 p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]);
853 ret = sscanf(p, "%d", &crit);
854 if ((ret != 1) || (crit < 0) || (crit > 1)) {
855 ldb_set_errstring(ldb,
856 "invalid relax control syntax\n"
857 " syntax: crit(b)\n"
858 " note: b = boolean");
859 talloc_free(ctrl);
860 return NULL;
863 ctrl->oid = LDB_CONTROL_RELAX_OID;
864 ctrl->critical = crit;
865 ctrl->data = NULL;
867 return ctrl;
870 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RECALCULATE_SD_NAME) == 0) {
871 const char *p;
872 int crit, ret;
874 p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]);
875 ret = sscanf(p, "%d", &crit);
876 if ((ret != 1) || (crit < 0) || (crit > 1)) {
877 ldb_set_errstring(ldb,
878 "invalid recalculate_sd control syntax\n"
879 " syntax: crit(b)\n"
880 " note: b = boolean");
881 talloc_free(ctrl);
882 return NULL;
885 ctrl->oid = LDB_CONTROL_RECALCULATE_SD_OID;
886 ctrl->critical = crit;
887 ctrl->data = NULL;
889 return ctrl;
892 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DOMAIN_SCOPE_NAME) == 0) {
893 const char *p;
894 int crit, ret;
896 p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]);
897 ret = sscanf(p, "%d", &crit);
898 if ((ret != 1) || (crit < 0) || (crit > 1)) {
899 ldb_set_errstring(ldb,
900 "invalid domain_scope control syntax\n"
901 " syntax: crit(b)\n"
902 " note: b = boolean");
903 talloc_free(ctrl);
904 return NULL;
907 ctrl->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
908 ctrl->critical = crit;
909 ctrl->data = NULL;
911 return ctrl;
914 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PAGED_RESULTS_NAME) == 0) {
915 struct ldb_paged_control *control;
916 const char *p;
917 char cookie[1024];
918 int crit, size, ret;
920 cookie[0] = '\0';
921 p = &(control_strings[sizeof(LDB_CONTROL_PAGED_RESULTS_NAME)]);
922 ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &size, cookie);
923 if ((ret < 2) || (ret > 3) || (crit < 0) || (crit > 1) ||
924 (size < 0)) {
925 ldb_set_errstring(ldb,
926 "invalid paged_results control syntax\n"
927 " syntax: crit(b):size(n)[:cookie(base64)]\n"
928 " note: b = boolean, n = number");
929 talloc_free(ctrl);
930 return NULL;
933 ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID;
934 ctrl->critical = crit;
935 control = talloc(ctrl, struct ldb_paged_control);
936 if (control == NULL) {
937 ldb_oom(ldb);
938 talloc_free(ctrl);
939 return NULL;
942 control->size = size;
943 if (cookie[0] != '\0') {
944 int len = ldb_base64_decode(cookie);
945 if (len < 0) {
946 ldb_set_errstring(ldb,
947 "invalid paged_results cookie"
948 " (probably too long)\n");
949 talloc_free(ctrl);
950 return NULL;
952 control->cookie_len = len;
953 control->cookie = talloc_memdup(control, cookie, control->cookie_len);
954 if (control->cookie == NULL) {
955 ldb_oom(ldb);
956 talloc_free(ctrl);
957 return NULL;
959 } else {
960 control->cookie = NULL;
961 control->cookie_len = 0;
963 ctrl->data = control;
965 return ctrl;
968 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SERVER_SORT_NAME) == 0) {
969 struct ldb_server_sort_control **control;
970 const char *p;
971 char attr[256];
972 char rule[128];
973 int crit, rev, ret;
975 attr[0] = '\0';
976 rule[0] = '\0';
977 p = &(control_strings[sizeof(LDB_CONTROL_SERVER_SORT_NAME)]);
978 ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
979 if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
980 ldb_set_errstring(ldb,
981 "invalid server_sort control syntax\n"
982 " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"
983 " note: b = boolean, s = string");
984 talloc_free(ctrl);
985 return NULL;
987 ctrl->oid = LDB_CONTROL_SERVER_SORT_OID;
988 ctrl->critical = crit;
989 control = talloc_array(ctrl, struct ldb_server_sort_control *, 2);
990 if (control == NULL) {
991 ldb_oom(ldb);
992 talloc_free(ctrl);
993 return NULL;
996 control[0] = talloc(control, struct ldb_server_sort_control);
997 if (control[0] == NULL) {
998 ldb_oom(ldb);
999 talloc_free(ctrl);
1000 return NULL;
1003 control[0]->attributeName = talloc_strdup(control, attr);
1004 if (control[0]->attributeName == NULL) {
1005 ldb_oom(ldb);
1006 talloc_free(ctrl);
1007 return NULL;
1010 if (rule[0]) {
1011 control[0]->orderingRule = talloc_strdup(control, rule);
1012 if (control[0]->orderingRule == NULL) {
1013 ldb_oom(ldb);
1014 talloc_free(ctrl);
1015 return NULL;
1017 } else {
1018 control[0]->orderingRule = NULL;
1020 control[0]->reverse = rev;
1021 control[1] = NULL;
1022 ctrl->data = control;
1024 return ctrl;
1027 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_NOTIFICATION_NAME) == 0) {
1028 const char *p;
1029 int crit, ret;
1031 p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]);
1032 ret = sscanf(p, "%d", &crit);
1033 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1034 ldb_set_errstring(ldb,
1035 "invalid notification control syntax\n"
1036 " syntax: crit(b)\n"
1037 " note: b = boolean");
1038 talloc_free(ctrl);
1039 return NULL;
1042 ctrl->oid = LDB_CONTROL_NOTIFICATION_OID;
1043 ctrl->critical = crit;
1044 ctrl->data = NULL;
1046 return ctrl;
1049 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_TREE_DELETE_NAME) == 0) {
1050 const char *p;
1051 int crit, ret;
1053 p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]);
1054 ret = sscanf(p, "%d", &crit);
1055 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1056 ldb_set_errstring(ldb,
1057 "invalid tree_delete control syntax\n"
1058 " syntax: crit(b)\n"
1059 " note: b = boolean");
1060 talloc_free(ctrl);
1061 return NULL;
1064 ctrl->oid = LDB_CONTROL_TREE_DELETE_OID;
1065 ctrl->critical = crit;
1066 ctrl->data = NULL;
1068 return ctrl;
1071 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DELETED_NAME) == 0) {
1072 const char *p;
1073 int crit, ret;
1075 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]);
1076 ret = sscanf(p, "%d", &crit);
1077 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1078 ldb_set_errstring(ldb,
1079 "invalid show_deleted control syntax\n"
1080 " syntax: crit(b)\n"
1081 " note: b = boolean");
1082 talloc_free(ctrl);
1083 return NULL;
1086 ctrl->oid = LDB_CONTROL_SHOW_DELETED_OID;
1087 ctrl->critical = crit;
1088 ctrl->data = NULL;
1090 return ctrl;
1093 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME) == 0) {
1094 const char *p;
1095 int crit, ret;
1097 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]);
1098 ret = sscanf(p, "%d", &crit);
1099 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1100 ldb_set_errstring(ldb,
1101 "invalid show_deactivated_link control syntax\n"
1102 " syntax: crit(b)\n"
1103 " note: b = boolean");
1104 talloc_free(ctrl);
1105 return NULL;
1108 ctrl->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
1109 ctrl->critical = crit;
1110 ctrl->data = NULL;
1112 return ctrl;
1115 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_RECYCLED_NAME) == 0) {
1116 const char *p;
1117 int crit, ret;
1119 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]);
1120 ret = sscanf(p, "%d", &crit);
1121 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1122 ldb_set_errstring(ldb,
1123 "invalid show_recycled control syntax\n"
1124 " syntax: crit(b)\n"
1125 " note: b = boolean");
1126 talloc_free(ctrl);
1127 return NULL;
1130 ctrl->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
1131 ctrl->critical = crit;
1132 ctrl->data = NULL;
1134 return ctrl;
1137 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PERMISSIVE_MODIFY_NAME) == 0) {
1138 const char *p;
1139 int crit, ret;
1141 p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]);
1142 ret = sscanf(p, "%d", &crit);
1143 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1144 ldb_set_errstring(ldb,
1145 "invalid permissive_modify control syntax\n"
1146 " syntax: crit(b)\n"
1147 " note: b = boolean");
1148 talloc_free(ctrl);
1149 return NULL;
1152 ctrl->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
1153 ctrl->critical = crit;
1154 ctrl->data = NULL;
1156 return ctrl;
1159 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_REVEAL_INTERNALS_NAME) == 0) {
1160 const char *p;
1161 int crit, ret;
1163 p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]);
1164 ret = sscanf(p, "%d", &crit);
1165 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1166 ldb_set_errstring(ldb,
1167 "invalid reveal_internals control syntax\n"
1168 " syntax: crit(b)\n"
1169 " note: b = boolean");
1170 talloc_free(ctrl);
1171 return NULL;
1174 ctrl->oid = LDB_CONTROL_REVEAL_INTERNALS;
1175 ctrl->critical = crit;
1176 ctrl->data = NULL;
1178 return ctrl;
1181 if (strncmp(control_strings, "local_oid:", 10) == 0) {
1182 const char *p;
1183 int crit = 0, ret = 0;
1184 char oid[256];
1186 oid[0] = '\0';
1187 p = &(control_strings[10]);
1188 ret = sscanf(p, "%255[^:]:%d", oid, &crit);
1190 if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) {
1191 ldb_set_errstring(ldb,
1192 "invalid local_oid control syntax\n"
1193 " syntax: oid(s):crit(b)\n"
1194 " note: b = boolean, s = string");
1195 talloc_free(ctrl);
1196 return NULL;
1199 ctrl->oid = talloc_strdup(ctrl, oid);
1200 if (!ctrl->oid) {
1201 ldb_oom(ldb);
1202 talloc_free(ctrl);
1203 return NULL;
1205 ctrl->critical = crit;
1206 ctrl->data = NULL;
1208 return ctrl;
1211 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RODC_DCPROMO_NAME) == 0) {
1212 const char *p;
1213 int crit, ret;
1215 p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]);
1216 ret = sscanf(p, "%d", &crit);
1217 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1218 ldb_set_errstring(ldb,
1219 "invalid rodc_join control syntax\n"
1220 " syntax: crit(b)\n"
1221 " note: b = boolean");
1222 talloc_free(ctrl);
1223 return NULL;
1226 ctrl->oid = LDB_CONTROL_RODC_DCPROMO_OID;
1227 ctrl->critical = crit;
1228 ctrl->data = NULL;
1230 return ctrl;
1233 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PROVISION_NAME) == 0) {
1234 const char *p;
1235 int crit, ret;
1237 p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]);
1238 ret = sscanf(p, "%d", &crit);
1239 if ((ret != 1) || (crit < 0) || (crit > 1)) {
1240 ldb_set_errstring(ldb,
1241 "invalid provision control syntax\n"
1242 " syntax: crit(b)\n"
1243 " note: b = boolean");
1244 talloc_free(ctrl);
1245 return NULL;
1248 ctrl->oid = LDB_CONTROL_PROVISION_OID;
1249 ctrl->critical = crit;
1250 ctrl->data = NULL;
1252 return ctrl;
1254 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_VERIFY_NAME_NAME) == 0) {
1255 const char *p;
1256 char gc[1024];
1257 int crit, flags, ret;
1258 struct ldb_verify_name_control *control;
1260 gc[0] = '\0';
1262 p = &(control_strings[sizeof(LDB_CONTROL_VERIFY_NAME_NAME)]);
1263 ret = sscanf(p, "%d:%d:%1023[^$]", &crit, &flags, gc);
1264 if ((ret != 3) || (crit < 0) || (crit > 1)) {
1265 ret = sscanf(p, "%d:%d", &crit, &flags);
1266 if ((ret != 2) || (crit < 0) || (crit > 1)) {
1267 ldb_set_errstring(ldb,
1268 "invalid verify_name control syntax\n"
1269 " syntax: crit(b):flags(i)[:gc(s)]\n"
1270 " note: b = boolean"
1271 " note: i = integer"
1272 " note: s = string");
1273 talloc_free(ctrl);
1274 return NULL;
1278 ctrl->oid = LDB_CONTROL_VERIFY_NAME_OID;
1279 ctrl->critical = crit;
1280 control = talloc(ctrl, struct ldb_verify_name_control);
1281 if (control == NULL) {
1282 ldb_oom(ldb);
1283 talloc_free(ctrl);
1284 return NULL;
1287 control->gc = talloc_strdup(control, gc);
1288 if (control->gc == NULL) {
1289 ldb_oom(ldb);
1290 talloc_free(ctrl);
1291 return NULL;
1294 control->gc_len = strlen(gc);
1295 control->flags = flags;
1296 ctrl->data = control;
1297 return ctrl;
1300 * When no matching control has been found.
1302 TALLOC_FREE(ctrl);
1303 return NULL;
1306 /* Parse controls from the format used on the command line and in ejs */
1307 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings)
1309 unsigned int i;
1310 struct ldb_control **ctrl;
1312 if (control_strings == NULL || control_strings[0] == NULL)
1313 return NULL;
1315 for (i = 0; control_strings[i]; i++);
1317 ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
1319 ldb_reset_err_string(ldb);
1320 for (i = 0; control_strings[i]; i++) {
1321 ctrl[i] = ldb_parse_control_from_string(ldb, ctrl, control_strings[i]);
1322 if (ctrl[i] == NULL) {
1323 if (ldb_errstring(ldb) == NULL) {
1324 /* no controls matched, throw an error */
1325 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
1327 talloc_free(ctrl);
1328 return NULL;
1332 ctrl[i] = NULL;
1334 return ctrl;