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_realloc(req
, req
->controls
,
139 struct ldb_control
*,
141 if (!ctrls
) return LDB_ERR_OPERATIONS_ERROR
;
142 req
->controls
= ctrls
;
146 ctrl
= talloc(ctrls
, struct ldb_control
);
147 if (!ctrl
) return LDB_ERR_OPERATIONS_ERROR
;
149 ctrl
->oid
= talloc_strdup(ctrl
, oid
);
150 if (!ctrl
->oid
) return LDB_ERR_OPERATIONS_ERROR
;
151 ctrl
->critical
= critical
;
158 /* Parse controls from the format used on the command line and in ejs */
160 struct ldb_control
**ldb_parse_control_strings(struct ldb_context
*ldb
, void *mem_ctx
, const char **control_strings
)
163 struct ldb_control
**ctrl
;
165 char *error_string
= NULL
;
167 if (control_strings
== NULL
|| control_strings
[0] == NULL
)
170 for (i
= 0; control_strings
[i
]; i
++);
172 ctrl
= talloc_array(mem_ctx
, struct ldb_control
*, i
+ 1);
174 for (i
= 0; control_strings
[i
]; i
++) {
175 if (strncmp(control_strings
[i
], "vlv:", 4) == 0) {
176 struct ldb_vlv_req_control
*control
;
180 int crit
, bc
, ac
, os
, cc
, ret
;
184 p
= &(control_strings
[i
][4]);
185 ret
= sscanf(p
, "%d:%d:%d:%d:%d:%1023[^$]", &crit
, &bc
, &ac
, &os
, &cc
, ctxid
);
187 ret
= sscanf(p
, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit
, &bc
, &ac
, attr
, ctxid
);
190 if ((ret
< 4) || (crit
< 0) || (crit
> 1)) {
191 error_string
= talloc_asprintf(mem_ctx
, "invalid server_sort control syntax\n");
192 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
193 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number, s = string, o = b64 binary blob");
194 ldb_set_errstring(ldb
, error_string
);
195 talloc_free(error_string
);
198 if (!(ctrl
[i
] = talloc(ctrl
, struct ldb_control
))) {
202 ctrl
[i
]->oid
= LDB_CONTROL_VLV_REQ_OID
;
203 ctrl
[i
]->critical
= crit
;
204 if (!(control
= talloc(ctrl
[i
],
205 struct ldb_vlv_req_control
))) {
209 control
->beforeCount
= bc
;
210 control
->afterCount
= ac
;
213 control
->match
.gtOrEq
.value
= talloc_strdup(control
, attr
);
214 control
->match
.gtOrEq
.value_len
= strlen(attr
);
217 control
->match
.byOffset
.offset
= os
;
218 control
->match
.byOffset
.contentCount
= cc
;
221 control
->ctxid_len
= ldb_base64_decode(ctxid
);
222 control
->contextId
= (char *)talloc_memdup(control
, ctxid
, control
->ctxid_len
);
224 control
->ctxid_len
= 0;
225 control
->contextId
= NULL
;
227 ctrl
[i
]->data
= control
;
232 if (strncmp(control_strings
[i
], "dirsync:", 8) == 0) {
233 struct ldb_dirsync_control
*control
;
236 int crit
, flags
, max_attrs
, ret
;
239 p
= &(control_strings
[i
][8]);
240 ret
= sscanf(p
, "%d:%d:%d:%1023[^$]", &crit
, &flags
, &max_attrs
, cookie
);
242 if ((ret
< 3) || (crit
< 0) || (crit
> 1) || (flags
< 0) || (max_attrs
< 0)) {
243 error_string
= talloc_asprintf(mem_ctx
, "invalid dirsync control syntax\n");
244 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
245 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number, o = b64 binary blob");
246 ldb_set_errstring(ldb
, error_string
);
247 talloc_free(error_string
);
251 /* w2k3 seems to ignore the parameter,
252 * but w2k sends a wrong cookie when this value is to small
253 * this would cause looping forever, while getting
254 * the same data and same cookie forever
256 if (max_attrs
== 0) max_attrs
= 0x0FFFFFFF;
258 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
259 ctrl
[i
]->oid
= LDB_CONTROL_DIRSYNC_OID
;
260 ctrl
[i
]->critical
= crit
;
261 control
= talloc(ctrl
[i
], struct ldb_dirsync_control
);
262 control
->flags
= flags
;
263 control
->max_attributes
= max_attrs
;
265 control
->cookie_len
= ldb_base64_decode(cookie
);
266 control
->cookie
= (char *)talloc_memdup(control
, cookie
, control
->cookie_len
);
268 control
->cookie
= NULL
;
269 control
->cookie_len
= 0;
271 ctrl
[i
]->data
= control
;
276 if (strncmp(control_strings
[i
], "asq:", 4) == 0) {
277 struct ldb_asq_control
*control
;
283 p
= &(control_strings
[i
][4]);
284 ret
= sscanf(p
, "%d:%255[^$]", &crit
, attr
);
285 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (attr
[0] == '\0')) {
286 error_string
= talloc_asprintf(mem_ctx
, "invalid asq control syntax\n");
287 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):attr(s)\n");
288 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, s = string");
289 ldb_set_errstring(ldb
, error_string
);
290 talloc_free(error_string
);
294 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
299 ctrl
[i
]->oid
= LDB_CONTROL_ASQ_OID
;
300 ctrl
[i
]->critical
= crit
;
301 control
= talloc(ctrl
[i
], struct ldb_asq_control
);
302 control
->request
= 1;
303 control
->source_attribute
= talloc_strdup(control
, attr
);
304 control
->src_attr_len
= strlen(attr
);
305 ctrl
[i
]->data
= control
;
310 if (strncmp(control_strings
[i
], "extended_dn:", 12) == 0) {
311 struct ldb_extended_dn_control
*control
;
315 p
= &(control_strings
[i
][12]);
316 ret
= sscanf(p
, "%d:%d", &crit
, &type
);
317 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (type
< 0) || (type
> 1)) {
318 ret
= sscanf(p
, "%d", &crit
);
319 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
320 error_string
= talloc_asprintf(mem_ctx
, "invalid extended_dn control syntax\n");
321 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)[:type(i)]\n");
322 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean\n");
323 error_string
= talloc_asprintf_append(error_string
, " i = integer\n");
324 error_string
= talloc_asprintf_append(error_string
, " valid values are: 0 - hexadecimal representation\n");
325 error_string
= talloc_asprintf_append(error_string
, " 1 - normal string representation");
326 ldb_set_errstring(ldb
, error_string
);
327 talloc_free(error_string
);
332 control
= talloc(ctrl
, struct ldb_extended_dn_control
);
333 control
->type
= type
;
336 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
341 ctrl
[i
]->oid
= LDB_CONTROL_EXTENDED_DN_OID
;
342 ctrl
[i
]->critical
= crit
;
343 ctrl
[i
]->data
= talloc_steal(ctrl
[i
], control
);
348 if (strncmp(control_strings
[i
], "sd_flags:", 9) == 0) {
349 struct ldb_sd_flags_control
*control
;
352 unsigned secinfo_flags
;
354 p
= &(control_strings
[i
][9]);
355 ret
= sscanf(p
, "%d:%u", &crit
, &secinfo_flags
);
356 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (secinfo_flags
< 0) || (secinfo_flags
> 0xF)) {
357 error_string
= talloc_asprintf(mem_ctx
, "invalid sd_flags control syntax\n");
358 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):secinfo_flags(n)\n");
359 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
360 ldb_set_errstring(ldb
, error_string
);
361 talloc_free(error_string
);
365 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
370 ctrl
[i
]->oid
= LDB_CONTROL_SD_FLAGS_OID
;
371 ctrl
[i
]->critical
= crit
;
372 control
= talloc(ctrl
[i
], struct ldb_sd_flags_control
);
373 control
->secinfo_flags
= secinfo_flags
;
374 ctrl
[i
]->data
= control
;
379 if (strncmp(control_strings
[i
], "search_options:", 15) == 0) {
380 struct ldb_search_options_control
*control
;
383 unsigned search_options
;
385 p
= &(control_strings
[i
][15]);
386 ret
= sscanf(p
, "%d:%u", &crit
, &search_options
);
387 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (search_options
< 0) || (search_options
> 0xF)) {
388 error_string
= talloc_asprintf(mem_ctx
, "invalid search_options control syntax\n");
389 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):search_options(n)\n");
390 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
391 ldb_set_errstring(ldb
, error_string
);
392 talloc_free(error_string
);
396 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
401 ctrl
[i
]->oid
= LDB_CONTROL_SEARCH_OPTIONS_OID
;
402 ctrl
[i
]->critical
= crit
;
403 control
= talloc(ctrl
[i
], struct ldb_search_options_control
);
404 control
->search_options
= search_options
;
405 ctrl
[i
]->data
= control
;
410 if (strncmp(control_strings
[i
], "domain_scope:", 13) == 0) {
414 p
= &(control_strings
[i
][13]);
415 ret
= sscanf(p
, "%d", &crit
);
416 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
417 error_string
= talloc_asprintf(mem_ctx
, "invalid domain_scope control syntax\n");
418 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
419 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
420 ldb_set_errstring(ldb
, error_string
);
421 talloc_free(error_string
);
425 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
430 ctrl
[i
]->oid
= LDB_CONTROL_DOMAIN_SCOPE_OID
;
431 ctrl
[i
]->critical
= crit
;
432 ctrl
[i
]->data
= NULL
;
437 if (strncmp(control_strings
[i
], "paged_results:", 14) == 0) {
438 struct ldb_paged_control
*control
;
442 p
= &(control_strings
[i
][14]);
443 ret
= sscanf(p
, "%d:%d", &crit
, &size
);
445 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (size
< 0)) {
446 error_string
= talloc_asprintf(mem_ctx
, "invalid paged_results control syntax\n");
447 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):size(n)\n");
448 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
449 ldb_set_errstring(ldb
, error_string
);
450 talloc_free(error_string
);
454 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
459 ctrl
[i
]->oid
= LDB_CONTROL_PAGED_RESULTS_OID
;
460 ctrl
[i
]->critical
= crit
;
461 control
= talloc(ctrl
[i
], struct ldb_paged_control
);
462 control
->size
= size
;
463 control
->cookie
= NULL
;
464 control
->cookie_len
= 0;
465 ctrl
[i
]->data
= control
;
470 if (strncmp(control_strings
[i
], "server_sort:", 12) == 0) {
471 struct ldb_server_sort_control
**control
;
479 p
= &(control_strings
[i
][12]);
480 ret
= sscanf(p
, "%d:%d:%255[^:]:%127[^:]", &crit
, &rev
, attr
, rule
);
481 if ((ret
< 3) || (crit
< 0) || (crit
> 1) || (rev
< 0 ) || (rev
> 1) ||attr
[0] == '\0') {
482 error_string
= talloc_asprintf(mem_ctx
, "invalid server_sort control syntax\n");
483 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
484 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, s = string");
485 ldb_set_errstring(ldb
, error_string
);
486 talloc_free(error_string
);
489 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
494 ctrl
[i
]->oid
= LDB_CONTROL_SERVER_SORT_OID
;
495 ctrl
[i
]->critical
= crit
;
496 control
= talloc_array(ctrl
[i
], struct ldb_server_sort_control
*, 2);
497 control
[0] = talloc(control
, struct ldb_server_sort_control
);
498 control
[0]->attributeName
= talloc_strdup(control
, attr
);
500 control
[0]->orderingRule
= talloc_strdup(control
, rule
);
502 control
[0]->orderingRule
= NULL
;
503 control
[0]->reverse
= rev
;
505 ctrl
[i
]->data
= control
;
510 if (strncmp(control_strings
[i
], "notification:", 13) == 0) {
514 p
= &(control_strings
[i
][13]);
515 ret
= sscanf(p
, "%d", &crit
);
516 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
517 error_string
= talloc_asprintf(mem_ctx
, "invalid notification control syntax\n");
518 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
519 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
520 ldb_set_errstring(ldb
, error_string
);
521 talloc_free(error_string
);
525 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
530 ctrl
[i
]->oid
= LDB_CONTROL_NOTIFICATION_OID
;
531 ctrl
[i
]->critical
= crit
;
532 ctrl
[i
]->data
= NULL
;
537 if (strncmp(control_strings
[i
], "show_deleted:", 13) == 0) {
541 p
= &(control_strings
[i
][13]);
542 ret
= sscanf(p
, "%d", &crit
);
543 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
544 error_string
= talloc_asprintf(mem_ctx
, "invalid show_deleted control syntax\n");
545 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
546 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
547 ldb_set_errstring(ldb
, error_string
);
548 talloc_free(error_string
);
552 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
557 ctrl
[i
]->oid
= LDB_CONTROL_SHOW_DELETED_OID
;
558 ctrl
[i
]->critical
= crit
;
559 ctrl
[i
]->data
= NULL
;
564 if (strncmp(control_strings
[i
], "show_deactivated_link:", 22) == 0) {
568 p
= &(control_strings
[i
][22]);
569 ret
= sscanf(p
, "%d", &crit
);
570 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
571 error_string
= talloc_asprintf(mem_ctx
, "invalid show_deactivated_link control syntax\n");
572 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
573 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
574 ldb_set_errstring(ldb
, error_string
);
575 talloc_free(error_string
);
579 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
584 ctrl
[i
]->oid
= LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID
;
585 ctrl
[i
]->critical
= crit
;
586 ctrl
[i
]->data
= NULL
;
591 if (strncmp(control_strings
[i
], "show_recycled:", 14) == 0) {
595 p
= &(control_strings
[i
][14]);
596 ret
= sscanf(p
, "%d", &crit
);
597 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
598 error_string
= talloc_asprintf(mem_ctx
, "invalid show_recycled control syntax\n");
599 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
600 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
601 ldb_set_errstring(ldb
, error_string
);
602 talloc_free(error_string
);
606 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
611 ctrl
[i
]->oid
= LDB_CONTROL_SHOW_RECYCLED_OID
;
612 ctrl
[i
]->critical
= crit
;
613 ctrl
[i
]->data
= NULL
;
618 if (strncmp(control_strings
[i
], "permissive_modify:", 18) == 0) {
622 p
= &(control_strings
[i
][18]);
623 ret
= sscanf(p
, "%d", &crit
);
624 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
625 error_string
= talloc_asprintf(mem_ctx
, "invalid permissive_modify control syntax\n");
626 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
627 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
628 ldb_set_errstring(ldb
, error_string
);
629 talloc_free(error_string
);
633 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
638 ctrl
[i
]->oid
= LDB_CONTROL_PERMISSIVE_MODIFY_OID
;
639 ctrl
[i
]->critical
= crit
;
640 ctrl
[i
]->data
= NULL
;
645 /* no controls matched, throw an error */
646 ldb_asprintf_errstring(ldb
, "Invalid control name: '%s'", control_strings
[i
]);