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_includes.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 /* check if there's a paged request control */
43 if (req
->controls
!= NULL
) {
44 for (i
= 0; req
->controls
[i
]; i
++) {
45 if (strcmp(oid
, req
->controls
[i
]->oid
) == 0) {
50 return req
->controls
[i
];
56 /* check if a control with the specified "oid" exist and return it */
57 /* returns NULL if not found */
58 struct ldb_control
*ldb_reply_get_control(struct ldb_reply
*rep
, const char *oid
)
62 /* check if there's a paged request control */
63 if (rep
->controls
!= NULL
) {
64 for (i
= 0; rep
->controls
[i
]; i
++) {
65 if (strcmp(oid
, rep
->controls
[i
]->oid
) == 0) {
70 return rep
->controls
[i
];
76 /* saves the current controls list into the "saver" and replace the one in req with a new one excluding
77 the "exclude" control */
78 /* returns False on error */
79 int save_controls(struct ldb_control
*exclude
, struct ldb_request
*req
, struct ldb_control
***saver
)
81 struct ldb_control
**lcs
;
84 *saver
= req
->controls
;
85 for (i
= 0; req
->controls
[i
]; i
++);
91 lcs
= talloc_array(req
, struct ldb_control
*, i
);
96 for (i
= 0, j
= 0; (*saver
)[i
]; i
++) {
97 if (exclude
== (*saver
)[i
]) continue;
107 /* check if there's any control marked as critical in the list */
108 /* return True if any, False if none */
109 int check_critical_controls(struct ldb_control
**controls
)
113 if (controls
== NULL
) {
117 for (i
= 0; controls
[i
]; i
++) {
118 if (controls
[i
]->critical
) {
126 int ldb_request_add_control(struct ldb_request
*req
, const char *oid
, bool critical
, void *data
)
129 struct ldb_control
**ctrls
;
130 struct ldb_control
*ctrl
;
132 for (n
=0; req
->controls
&& req
->controls
[n
];) { n
++; }
134 ctrls
= talloc_realloc(req
, req
->controls
,
135 struct ldb_control
*,
137 if (!ctrls
) return LDB_ERR_OPERATIONS_ERROR
;
138 req
->controls
= ctrls
;
142 ctrl
= talloc(ctrls
, struct ldb_control
);
143 if (!ctrl
) return LDB_ERR_OPERATIONS_ERROR
;
145 ctrl
->oid
= talloc_strdup(ctrl
, oid
);
146 if (!ctrl
->oid
) return LDB_ERR_OPERATIONS_ERROR
;
147 ctrl
->critical
= critical
;
154 /* Parse controls from the format used on the command line and in ejs */
156 struct ldb_control
**ldb_parse_control_strings(struct ldb_context
*ldb
, void *mem_ctx
, const char **control_strings
)
159 struct ldb_control
**ctrl
;
161 char *error_string
= NULL
;
163 if (control_strings
== NULL
|| control_strings
[0] == NULL
)
166 for (i
= 0; control_strings
[i
]; i
++);
168 ctrl
= talloc_array(mem_ctx
, struct ldb_control
*, i
+ 1);
170 for (i
= 0; control_strings
[i
]; i
++) {
171 if (strncmp(control_strings
[i
], "vlv:", 4) == 0) {
172 struct ldb_vlv_req_control
*control
;
176 int crit
, bc
, ac
, os
, cc
, ret
;
180 p
= &(control_strings
[i
][4]);
181 ret
= sscanf(p
, "%d:%d:%d:%d:%d:%1023[^$]", &crit
, &bc
, &ac
, &os
, &cc
, ctxid
);
183 ret
= sscanf(p
, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit
, &bc
, &ac
, attr
, ctxid
);
186 if ((ret
< 4) || (crit
< 0) || (crit
> 1)) {
187 error_string
= talloc_asprintf(mem_ctx
, "invalid server_sort control syntax\n");
188 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
189 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number, s = string, o = b64 binary blob");
190 ldb_set_errstring(ldb
, error_string
);
191 talloc_free(error_string
);
194 if (!(ctrl
[i
] = talloc(ctrl
, struct ldb_control
))) {
198 ctrl
[i
]->oid
= LDB_CONTROL_VLV_REQ_OID
;
199 ctrl
[i
]->critical
= crit
;
200 if (!(control
= talloc(ctrl
[i
],
201 struct ldb_vlv_req_control
))) {
205 control
->beforeCount
= bc
;
206 control
->afterCount
= ac
;
209 control
->match
.gtOrEq
.value
= talloc_strdup(control
, attr
);
210 control
->match
.gtOrEq
.value_len
= strlen(attr
);
213 control
->match
.byOffset
.offset
= os
;
214 control
->match
.byOffset
.contentCount
= cc
;
217 control
->ctxid_len
= ldb_base64_decode(ctxid
);
218 control
->contextId
= (char *)talloc_memdup(control
, ctxid
, control
->ctxid_len
);
220 control
->ctxid_len
= 0;
221 control
->contextId
= NULL
;
223 ctrl
[i
]->data
= control
;
228 if (strncmp(control_strings
[i
], "dirsync:", 8) == 0) {
229 struct ldb_dirsync_control
*control
;
232 int crit
, flags
, max_attrs
, ret
;
235 p
= &(control_strings
[i
][8]);
236 ret
= sscanf(p
, "%d:%d:%d:%1023[^$]", &crit
, &flags
, &max_attrs
, cookie
);
238 if ((ret
< 3) || (crit
< 0) || (crit
> 1) || (flags
< 0) || (max_attrs
< 0)) {
239 error_string
= talloc_asprintf(mem_ctx
, "invalid dirsync control syntax\n");
240 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
241 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number, o = b64 binary blob");
242 ldb_set_errstring(ldb
, error_string
);
243 talloc_free(error_string
);
247 /* w2k3 seems to ignore the parameter,
248 * but w2k sends a wrong cookie when this value is to small
249 * this would cause looping forever, while getting
250 * the same data and same cookie forever
252 if (max_attrs
== 0) max_attrs
= 0x0FFFFFFF;
254 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
255 ctrl
[i
]->oid
= LDB_CONTROL_DIRSYNC_OID
;
256 ctrl
[i
]->critical
= crit
;
257 control
= talloc(ctrl
[i
], struct ldb_dirsync_control
);
258 control
->flags
= flags
;
259 control
->max_attributes
= max_attrs
;
261 control
->cookie_len
= ldb_base64_decode(cookie
);
262 control
->cookie
= (char *)talloc_memdup(control
, cookie
, control
->cookie_len
);
264 control
->cookie
= NULL
;
265 control
->cookie_len
= 0;
267 ctrl
[i
]->data
= control
;
272 if (strncmp(control_strings
[i
], "asq:", 4) == 0) {
273 struct ldb_asq_control
*control
;
279 p
= &(control_strings
[i
][4]);
280 ret
= sscanf(p
, "%d:%255[^$]", &crit
, attr
);
281 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (attr
[0] == '\0')) {
282 error_string
= talloc_asprintf(mem_ctx
, "invalid asq control syntax\n");
283 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):attr(s)\n");
284 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, s = string");
285 ldb_set_errstring(ldb
, error_string
);
286 talloc_free(error_string
);
290 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
295 ctrl
[i
]->oid
= LDB_CONTROL_ASQ_OID
;
296 ctrl
[i
]->critical
= crit
;
297 control
= talloc(ctrl
[i
], struct ldb_asq_control
);
298 control
->request
= 1;
299 control
->source_attribute
= talloc_strdup(control
, attr
);
300 control
->src_attr_len
= strlen(attr
);
301 ctrl
[i
]->data
= control
;
306 if (strncmp(control_strings
[i
], "extended_dn:", 12) == 0) {
307 struct ldb_extended_dn_control
*control
;
311 p
= &(control_strings
[i
][12]);
312 ret
= sscanf(p
, "%d:%d", &crit
, &type
);
313 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (type
< 0) || (type
> 1)) {
314 ret
= sscanf(p
, "%d", &crit
);
315 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
316 error_string
= talloc_asprintf(mem_ctx
, "invalid extended_dn control syntax\n");
317 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)[:type(i)]\n");
318 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean\n");
319 error_string
= talloc_asprintf_append(error_string
, " i = integer\n");
320 error_string
= talloc_asprintf_append(error_string
, " valid values are: 0 - hexadecimal representation\n");
321 error_string
= talloc_asprintf_append(error_string
, " 1 - normal string representation");
322 ldb_set_errstring(ldb
, error_string
);
323 talloc_free(error_string
);
328 control
= talloc(ctrl
, struct ldb_extended_dn_control
);
329 control
->type
= type
;
332 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
337 ctrl
[i
]->oid
= LDB_CONTROL_EXTENDED_DN_OID
;
338 ctrl
[i
]->critical
= crit
;
339 ctrl
[i
]->data
= talloc_steal(ctrl
[i
], control
);
344 if (strncmp(control_strings
[i
], "sd_flags:", 9) == 0) {
345 struct ldb_sd_flags_control
*control
;
348 unsigned secinfo_flags
;
350 p
= &(control_strings
[i
][9]);
351 ret
= sscanf(p
, "%d:%u", &crit
, &secinfo_flags
);
352 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (secinfo_flags
< 0) || (secinfo_flags
> 0xF)) {
353 error_string
= talloc_asprintf(mem_ctx
, "invalid sd_flags control syntax\n");
354 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):secinfo_flags(n)\n");
355 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
356 ldb_set_errstring(ldb
, error_string
);
357 talloc_free(error_string
);
361 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
366 ctrl
[i
]->oid
= LDB_CONTROL_SD_FLAGS_OID
;
367 ctrl
[i
]->critical
= crit
;
368 control
= talloc(ctrl
[i
], struct ldb_sd_flags_control
);
369 control
->secinfo_flags
= secinfo_flags
;
370 ctrl
[i
]->data
= control
;
375 if (strncmp(control_strings
[i
], "search_options:", 15) == 0) {
376 struct ldb_search_options_control
*control
;
379 unsigned search_options
;
381 p
= &(control_strings
[i
][15]);
382 ret
= sscanf(p
, "%d:%u", &crit
, &search_options
);
383 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (search_options
< 0) || (search_options
> 0xF)) {
384 error_string
= talloc_asprintf(mem_ctx
, "invalid search_options control syntax\n");
385 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):search_options(n)\n");
386 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
387 ldb_set_errstring(ldb
, error_string
);
388 talloc_free(error_string
);
392 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
397 ctrl
[i
]->oid
= LDB_CONTROL_SEARCH_OPTIONS_OID
;
398 ctrl
[i
]->critical
= crit
;
399 control
= talloc(ctrl
[i
], struct ldb_search_options_control
);
400 control
->search_options
= search_options
;
401 ctrl
[i
]->data
= control
;
406 if (strncmp(control_strings
[i
], "domain_scope:", 13) == 0) {
410 p
= &(control_strings
[i
][13]);
411 ret
= sscanf(p
, "%d", &crit
);
412 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
413 error_string
= talloc_asprintf(mem_ctx
, "invalid domain_scope control syntax\n");
414 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
415 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
416 ldb_set_errstring(ldb
, error_string
);
417 talloc_free(error_string
);
421 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
426 ctrl
[i
]->oid
= LDB_CONTROL_DOMAIN_SCOPE_OID
;
427 ctrl
[i
]->critical
= crit
;
428 ctrl
[i
]->data
= NULL
;
433 if (strncmp(control_strings
[i
], "paged_results:", 14) == 0) {
434 struct ldb_paged_control
*control
;
438 p
= &(control_strings
[i
][14]);
439 ret
= sscanf(p
, "%d:%d", &crit
, &size
);
441 if ((ret
!= 2) || (crit
< 0) || (crit
> 1) || (size
< 0)) {
442 error_string
= talloc_asprintf(mem_ctx
, "invalid paged_results control syntax\n");
443 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):size(n)\n");
444 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, n = number");
445 ldb_set_errstring(ldb
, error_string
);
446 talloc_free(error_string
);
450 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
455 ctrl
[i
]->oid
= LDB_CONTROL_PAGED_RESULTS_OID
;
456 ctrl
[i
]->critical
= crit
;
457 control
= talloc(ctrl
[i
], struct ldb_paged_control
);
458 control
->size
= size
;
459 control
->cookie
= NULL
;
460 control
->cookie_len
= 0;
461 ctrl
[i
]->data
= control
;
466 if (strncmp(control_strings
[i
], "server_sort:", 12) == 0) {
467 struct ldb_server_sort_control
**control
;
475 p
= &(control_strings
[i
][12]);
476 ret
= sscanf(p
, "%d:%d:%255[^:]:%127[^:]", &crit
, &rev
, attr
, rule
);
477 if ((ret
< 3) || (crit
< 0) || (crit
> 1) || (rev
< 0 ) || (rev
> 1) ||attr
[0] == '\0') {
478 error_string
= talloc_asprintf(mem_ctx
, "invalid server_sort control syntax\n");
479 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
480 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean, s = string");
481 ldb_set_errstring(ldb
, error_string
);
482 talloc_free(error_string
);
485 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
490 ctrl
[i
]->oid
= LDB_CONTROL_SERVER_SORT_OID
;
491 ctrl
[i
]->critical
= crit
;
492 control
= talloc_array(ctrl
[i
], struct ldb_server_sort_control
*, 2);
493 control
[0] = talloc(control
, struct ldb_server_sort_control
);
494 control
[0]->attributeName
= talloc_strdup(control
, attr
);
496 control
[0]->orderingRule
= talloc_strdup(control
, rule
);
498 control
[0]->orderingRule
= NULL
;
499 control
[0]->reverse
= rev
;
501 ctrl
[i
]->data
= control
;
506 if (strncmp(control_strings
[i
], "notification:", 13) == 0) {
510 p
= &(control_strings
[i
][13]);
511 ret
= sscanf(p
, "%d", &crit
);
512 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
513 error_string
= talloc_asprintf(mem_ctx
, "invalid notification control syntax\n");
514 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
515 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
516 ldb_set_errstring(ldb
, error_string
);
517 talloc_free(error_string
);
521 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
526 ctrl
[i
]->oid
= LDB_CONTROL_NOTIFICATION_OID
;
527 ctrl
[i
]->critical
= crit
;
528 ctrl
[i
]->data
= NULL
;
533 if (strncmp(control_strings
[i
], "show_deleted:", 13) == 0) {
537 p
= &(control_strings
[i
][13]);
538 ret
= sscanf(p
, "%d", &crit
);
539 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
540 error_string
= talloc_asprintf(mem_ctx
, "invalid show_deleted control syntax\n");
541 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
542 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
543 ldb_set_errstring(ldb
, error_string
);
544 talloc_free(error_string
);
548 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
553 ctrl
[i
]->oid
= LDB_CONTROL_SHOW_DELETED_OID
;
554 ctrl
[i
]->critical
= crit
;
555 ctrl
[i
]->data
= NULL
;
560 if (strncmp(control_strings
[i
], "permissive_modify:", 18) == 0) {
564 p
= &(control_strings
[i
][18]);
565 ret
= sscanf(p
, "%d", &crit
);
566 if ((ret
!= 1) || (crit
< 0) || (crit
> 1)) {
567 error_string
= talloc_asprintf(mem_ctx
, "invalid permissive_modify control syntax\n");
568 error_string
= talloc_asprintf_append(error_string
, " syntax: crit(b)\n");
569 error_string
= talloc_asprintf_append(error_string
, " note: b = boolean");
570 ldb_set_errstring(ldb
, error_string
);
571 talloc_free(error_string
);
575 ctrl
[i
] = talloc(ctrl
, struct ldb_control
);
580 ctrl
[i
]->oid
= LDB_CONTROL_PERMISSIVE_MODIFY_OID
;
581 ctrl
[i
]->critical
= crit
;
582 ctrl
[i
]->data
= NULL
;
587 /* no controls matched, throw an error */
588 ldb_asprintf_errstring(ldb
, "Invalid control name: '%s'", control_strings
[i
]);