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_controls_get_control(struct ldb_control
**controls
, const char *oid
)
42 if (controls
!= NULL
) {
43 for (i
= 0; controls
[i
]; i
++) {
44 if (controls
[i
]->oid
&& strcmp(oid
, controls
[i
]->oid
) == 0) {
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)
76 int ldb_save_controls(struct ldb_control
*exclude
, struct ldb_request
*req
, struct ldb_control
***saver
)
78 struct ldb_control
**lcs
, **lcs_old
;
81 lcs_old
= req
->controls
;
86 for (i
= 0; req
->controls
&& req
->controls
[i
]; i
++);
92 lcs
= talloc_array(req
, struct ldb_control
*, i
+ 1);
97 for (i
= 0, j
= 0; lcs_old
[i
]; i
++) {
98 if (exclude
== lcs_old
[i
]) continue;
104 req
->controls
= talloc_realloc(req
, lcs
, struct ldb_control
*, j
+ 1);
105 if (req
->controls
== NULL
) {
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
,
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
++);
131 for (i
= 0, j
= 0; controls_in
&& controls_in
[i
]; i
++) {
132 if (exclude
== controls_in
[i
]) continue;
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
139 lcs
= talloc_array(mem_ctx
, struct ldb_control
*,
146 lcs
[j
] = controls_in
[i
];
147 talloc_reparent(controls_in
, lcs
, lcs
[j
]);
153 lcs
= talloc_realloc(mem_ctx
, lcs
, struct ldb_control
*, j
+ 1);
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
)
165 if (controls
== NULL
) {
169 for (i
= 0; controls
[i
]; i
++) {
170 if (controls
[i
]->critical
) {
178 int ldb_request_add_control(struct ldb_request
*req
, const char *oid
, bool critical
, void *data
)
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
*,
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
;
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
;
216 int ldb_reply_add_control(struct ldb_reply
*ares
, const char *oid
, bool critical
, void *data
)
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
;
230 ctrls
= talloc_realloc(ares
, ares
->controls
,
231 struct ldb_control
*,
233 if (!ctrls
) return LDB_ERR_OPERATIONS_ERROR
;
234 ares
->controls
= ctrls
;
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
;
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
)
256 ret
= ldb_request_add_control(req
, oid
, critical
, data
);
257 if (ret
!= LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
) {
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
;
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
)
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
);
284 if (rep_control
== NULL
) {
288 cookie
= ldb_base64_encode(mem_ctx
, rep_control
->cookie
, rep_control
->cookie_len
);
289 if (cookie
== NULL
) {
292 if (cookie
[0] != '\0') {
293 res
= talloc_asprintf(mem_ctx
, "%s:%d:%s",
294 LDB_CONTROL_PAGED_RESULTS_NAME
,
300 res
= talloc_asprintf(mem_ctx
, "%s:%d",
301 LDB_CONTROL_PAGED_RESULTS_NAME
,
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
);
313 if (rep_control
== NULL
) {
317 cookie
= ldb_base64_encode(mem_ctx
,
318 (char *)rep_control
->contextId
,
319 rep_control
->ctxid_len
);
320 if (cookie
== NULL
) {
324 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d:%d:%d:%s",
325 LDB_CONTROL_VLV_RESP_NAME
,
327 rep_control
->targetPosition
,
328 rep_control
->contentCount
,
329 rep_control
->vlv_result
,
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
) {
342 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d:%s",
343 LDB_CONTROL_SORT_RESP_NAME
,
346 rep_control
->attr_desc
);
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
) {
358 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d",
359 LDB_CONTROL_ASQ_NAME
,
361 rep_control
->result
);
366 if (strcmp(control
->oid
, LDB_CONTROL_DIRSYNC_OID
) == 0) {
368 struct ldb_dirsync_control
*rep_control
= talloc_get_type(control
->data
,
369 struct ldb_dirsync_control
);
371 if (rep_control
== NULL
) {
374 cookie
= ldb_base64_encode(mem_ctx
, rep_control
->cookie
,
375 rep_control
->cookie_len
);
376 if (cookie
== NULL
) {
379 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d:%d:%s",
380 LDB_CONTROL_DIRSYNC_NAME
,
383 rep_control
->max_attributes
,
389 if (strcmp(control
->oid
, LDB_CONTROL_DIRSYNC_EX_OID
) == 0) {
391 struct ldb_dirsync_control
*rep_control
= talloc_get_type(control
->data
,
392 struct ldb_dirsync_control
);
394 if (rep_control
== NULL
) {
397 cookie
= ldb_base64_encode(mem_ctx
, rep_control
->cookie
,
398 rep_control
->cookie_len
);
399 if (cookie
== NULL
) {
402 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d:%d:%s",
403 LDB_CONTROL_DIRSYNC_EX_NAME
,
406 rep_control
->max_attributes
,
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
) {
419 if (rep_control
->gc
!= NULL
) {
420 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d:%s",
421 LDB_CONTROL_VERIFY_NAME_NAME
,
427 res
= talloc_asprintf(mem_ctx
, "%s:%d:%d",
428 LDB_CONTROL_VERIFY_NAME_NAME
,
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",
447 res
= talloc_asprintf(mem_ctx
, "unknown oid:%s",
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
))) {
472 if (LDB_CONTROL_CMP(control_strings
,
473 LDB_CONTROL_VLV_REQ_NAME
) == 0) {
474 struct ldb_vlv_req_control
*control
;
478 int crit
, bc
, ac
, os
, cc
, ret
;
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). */
488 ret
= sscanf(p
, "%d:%d:%d:>=%1023[^:]:%1023[^$]", &crit
, &bc
, &ac
, attr
, ctxid
);
492 ret
= sscanf(p
, "%d:%d:%d:base64>=%1023[^:]:%1023[^$]", &crit
, &bc
, &ac
, attr
, ctxid
);
493 len
= ldb_base64_decode(attr
);
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");
508 ctrl
->oid
= LDB_CONTROL_VLV_REQ_OID
;
509 ctrl
->critical
= crit
;
510 if (!(control
= talloc(ctrl
,
511 struct ldb_vlv_req_control
))) {
516 control
->beforeCount
= bc
;
517 control
->afterCount
= ac
;
520 control
->match
.gtOrEq
.value
= talloc_strdup(control
, attr
);
521 control
->match
.gtOrEq
.value_len
= strlen(attr
);
524 control
->match
.byOffset
.offset
= os
;
525 control
->match
.byOffset
.contentCount
= cc
;
528 int len
= ldb_base64_decode(ctxid
);
530 ldb_set_errstring(ldb
,
531 "invalid VLV context_id\n");
535 control
->ctxid_len
= len
;
536 control
->contextId
= talloc_memdup(control
, ctxid
,
538 if (control
->contextId
== NULL
) {
544 control
->ctxid_len
= 0;
545 control
->contextId
= NULL
;
547 ctrl
->data
= control
;
552 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_DIRSYNC_NAME
) == 0) {
553 struct ldb_dirsync_control
*control
;
556 int crit
, max_attrs
, ret
;
559 cookie
= talloc_zero_array(ctrl
, char,
560 strlen(control_strings
) + 1);
561 if (cookie
== 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");
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
) {
594 control
->flags
= flags
;
595 control
->max_attributes
= max_attrs
;
597 int len
= ldb_base64_decode(cookie
);
599 ldb_set_errstring(ldb
,
600 "invalid dirsync cookie\n");
604 control
->cookie_len
= len
;
605 control
->cookie
= (char *)talloc_memdup(control
, cookie
, control
->cookie_len
);
606 if (control
->cookie
== NULL
) {
612 control
->cookie
= NULL
;
613 control
->cookie_len
= 0;
615 ctrl
->data
= control
;
620 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_DIRSYNC_EX_NAME
) == 0) {
621 struct ldb_dirsync_control
*control
;
624 int crit
, max_attrs
, ret
;
627 cookie
= talloc_zero_array(ctrl
, char,
628 strlen(control_strings
) + 1);
629 if (cookie
== 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");
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
) {
662 control
->flags
= flags
;
663 control
->max_attributes
= max_attrs
;
665 int len
= ldb_base64_decode(cookie
);
667 ldb_set_errstring(ldb
,
668 "invalid dirsync_ex cookie"
669 " (probably too long)\n");
673 control
->cookie_len
= len
;
674 control
->cookie
= (char *)talloc_memdup(control
, cookie
, control
->cookie_len
);
675 if (control
->cookie
== NULL
) {
681 control
->cookie
= NULL
;
682 control
->cookie_len
= 0;
684 ctrl
->data
= control
;
690 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_ASQ_NAME
) == 0) {
691 struct ldb_asq_control
*control
;
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");
708 ctrl
->oid
= LDB_CONTROL_ASQ_OID
;
709 ctrl
->critical
= crit
;
710 control
= talloc(ctrl
, struct ldb_asq_control
);
711 if (control
== NULL
) {
716 control
->request
= 1;
717 control
->source_attribute
= talloc_strdup(control
, attr
);
718 control
->src_attr_len
= strlen(attr
);
719 ctrl
->data
= control
;
724 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_EXTENDED_DN_NAME
) == 0) {
725 struct ldb_extended_dn_control
*control
;
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"
739 " valid values are: 0 - hexadecimal representation\n"
740 " 1 - normal string representation");
746 control
= talloc(ctrl
, struct ldb_extended_dn_control
);
747 if (control
== NULL
) {
752 control
->type
= type
;
755 ctrl
->oid
= LDB_CONTROL_EXTENDED_DN_OID
;
756 ctrl
->critical
= crit
;
757 ctrl
->data
= control
;
762 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SD_FLAGS_NAME
) == 0) {
763 struct ldb_sd_flags_control
*control
;
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");
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
) {
788 control
->secinfo_flags
= secinfo_flags
;
789 ctrl
->data
= control
;
794 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SEARCH_OPTIONS_NAME
) == 0) {
795 struct ldb_search_options_control
*control
;
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");
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
) {
820 control
->search_options
= search_options
;
821 ctrl
->data
= control
;
826 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_BYPASS_OPERATIONAL_NAME
) == 0) {
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"
836 " note: b = boolean");
841 ctrl
->oid
= LDB_CONTROL_BYPASS_OPERATIONAL_OID
;
842 ctrl
->critical
= crit
;
848 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_RELAX_NAME
) == 0) {
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"
858 " note: b = boolean");
863 ctrl
->oid
= LDB_CONTROL_RELAX_OID
;
864 ctrl
->critical
= crit
;
870 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_RECALCULATE_SD_NAME
) == 0) {
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"
880 " note: b = boolean");
885 ctrl
->oid
= LDB_CONTROL_RECALCULATE_SD_OID
;
886 ctrl
->critical
= crit
;
892 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_DOMAIN_SCOPE_NAME
) == 0) {
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"
902 " note: b = boolean");
907 ctrl
->oid
= LDB_CONTROL_DOMAIN_SCOPE_OID
;
908 ctrl
->critical
= crit
;
914 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_PAGED_RESULTS_NAME
) == 0) {
915 struct ldb_paged_control
*control
;
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) ||
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");
933 ctrl
->oid
= LDB_CONTROL_PAGED_RESULTS_OID
;
934 ctrl
->critical
= crit
;
935 control
= talloc(ctrl
, struct ldb_paged_control
);
936 if (control
== NULL
) {
942 control
->size
= size
;
943 if (cookie
[0] != '\0') {
944 int len
= ldb_base64_decode(cookie
);
946 ldb_set_errstring(ldb
,
947 "invalid paged_results cookie"
948 " (probably too long)\n");
952 control
->cookie_len
= len
;
953 control
->cookie
= talloc_memdup(control
, cookie
, control
->cookie_len
);
954 if (control
->cookie
== NULL
) {
960 control
->cookie
= NULL
;
961 control
->cookie_len
= 0;
963 ctrl
->data
= control
;
968 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SERVER_SORT_NAME
) == 0) {
969 struct ldb_server_sort_control
**control
;
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");
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
) {
996 control
[0] = talloc(control
, struct ldb_server_sort_control
);
997 if (control
[0] == NULL
) {
1003 control
[0]->attributeName
= talloc_strdup(control
, attr
);
1004 if (control
[0]->attributeName
== NULL
) {
1011 control
[0]->orderingRule
= talloc_strdup(control
, rule
);
1012 if (control
[0]->orderingRule
== NULL
) {
1018 control
[0]->orderingRule
= NULL
;
1020 control
[0]->reverse
= rev
;
1022 ctrl
->data
= control
;
1027 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_NOTIFICATION_NAME
) == 0) {
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");
1042 ctrl
->oid
= LDB_CONTROL_NOTIFICATION_OID
;
1043 ctrl
->critical
= crit
;
1049 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_TREE_DELETE_NAME
) == 0) {
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");
1064 ctrl
->oid
= LDB_CONTROL_TREE_DELETE_OID
;
1065 ctrl
->critical
= crit
;
1071 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SHOW_DELETED_NAME
) == 0) {
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");
1086 ctrl
->oid
= LDB_CONTROL_SHOW_DELETED_OID
;
1087 ctrl
->critical
= crit
;
1093 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME
) == 0) {
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");
1108 ctrl
->oid
= LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID
;
1109 ctrl
->critical
= crit
;
1115 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_SHOW_RECYCLED_NAME
) == 0) {
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");
1130 ctrl
->oid
= LDB_CONTROL_SHOW_RECYCLED_OID
;
1131 ctrl
->critical
= crit
;
1137 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_PERMISSIVE_MODIFY_NAME
) == 0) {
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");
1152 ctrl
->oid
= LDB_CONTROL_PERMISSIVE_MODIFY_OID
;
1153 ctrl
->critical
= crit
;
1159 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_REVEAL_INTERNALS_NAME
) == 0) {
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");
1174 ctrl
->oid
= LDB_CONTROL_REVEAL_INTERNALS
;
1175 ctrl
->critical
= crit
;
1181 if (strncmp(control_strings
, "local_oid:", 10) == 0) {
1183 int crit
= 0, ret
= 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");
1199 ctrl
->oid
= talloc_strdup(ctrl
, oid
);
1205 ctrl
->critical
= crit
;
1211 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_RODC_DCPROMO_NAME
) == 0) {
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");
1226 ctrl
->oid
= LDB_CONTROL_RODC_DCPROMO_OID
;
1227 ctrl
->critical
= crit
;
1233 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_PROVISION_NAME
) == 0) {
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");
1248 ctrl
->oid
= LDB_CONTROL_PROVISION_OID
;
1249 ctrl
->critical
= crit
;
1254 if (LDB_CONTROL_CMP(control_strings
, LDB_CONTROL_VERIFY_NAME_NAME
) == 0) {
1257 int crit
, flags
, ret
;
1258 struct ldb_verify_name_control
*control
;
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");
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
) {
1287 control
->gc
= talloc_strdup(control
, gc
);
1288 if (control
->gc
== NULL
) {
1294 control
->gc_len
= strlen(gc
);
1295 control
->flags
= flags
;
1296 ctrl
->data
= control
;
1300 * When no matching control has been found.
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
)
1310 struct ldb_control
**ctrl
;
1312 if (control_strings
== NULL
|| control_strings
[0] == 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
]);