1/* 2 ldb database library - command line handling for ldb tools 3 4 Copyright (C) Andrew Tridgell 2005 5 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 9 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. 14 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. 19 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/>. 22*/ 23 24#include "includes.h" 25#include "ldb/include/includes.h" 26#include "ldb/tools/cmdline.h" 27 28#if (_SAMBA_BUILD_ >= 4) 29#include "lib/cmdline/popt_common.h" 30#include "lib/ldb/samba/ldif_handlers.h" 31#include "auth/gensec/gensec.h" 32#include "auth/auth.h" 33#include "db_wrap.h" 34#endif 35 36 37 38/* 39 process command line options 40*/ 41struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, 42 void (*usage)(void)) 43{ 44 static struct ldb_cmdline options; /* needs to be static for older compilers */ 45 struct ldb_cmdline *ret=NULL; 46 poptContext pc; 47#if (_SAMBA_BUILD_ >= 4) 48 int r; 49#endif 50 int num_options = 0; 51 int opt; 52 int flags = 0; 53 54 struct poptOption popt_options[] = { 55 POPT_AUTOHELP 56 { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, 57 { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" }, 58 { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" }, 59 { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" }, 60 { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL }, 61 { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL }, 62 { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL }, 63 { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL }, 64 { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL }, 65 { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL }, 66 { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, 67 { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, 68 { "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" }, 69 { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" }, 70 { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" }, 71 { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, 72 { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL }, 73#if (_SAMBA_BUILD_ >= 4) 74 POPT_COMMON_SAMBA 75 POPT_COMMON_CREDENTIALS 76 POPT_COMMON_VERSION 77#endif 78 { NULL } 79 }; 80 81 ldb_global_init(); 82 83#if (_SAMBA_BUILD_ >= 4) 84 r = ldb_register_samba_handlers(ldb); 85 if (r != 0) { 86 goto failed; 87 } 88 89#endif 90 91 ret = talloc_zero(ldb, struct ldb_cmdline); 92 if (ret == NULL) { 93 ldb_oom(ldb); 94 goto failed; 95 } 96 97 options = *ret; 98 99 /* pull in URL */ 100 options.url = getenv("LDB_URL"); 101 102 /* and editor (used by ldbedit) */ 103 options.editor = getenv("VISUAL"); 104 if (!options.editor) { 105 options.editor = getenv("EDITOR"); 106 } 107 if (!options.editor) { 108 options.editor = "vi"; 109 } 110 111 options.scope = LDB_SCOPE_DEFAULT; 112 113 pc = poptGetContext(argv[0], argc, argv, popt_options, 114 POPT_CONTEXT_KEEP_FIRST); 115 116 while((opt = poptGetNextOpt(pc)) != -1) { 117 switch (opt) { 118 case 's': { 119 const char *arg = poptGetOptArg(pc); 120 if (strcmp(arg, "base") == 0) { 121 options.scope = LDB_SCOPE_BASE; 122 } else if (strcmp(arg, "sub") == 0) { 123 options.scope = LDB_SCOPE_SUBTREE; 124 } else if (strcmp(arg, "one") == 0) { 125 options.scope = LDB_SCOPE_ONELEVEL; 126 } else { 127 fprintf(stderr, "Invalid scope '%s'\n", arg); 128 goto failed; 129 } 130 break; 131 } 132 133 case 'v': 134 options.verbose++; 135 break; 136 137 case 'o': 138 options.options = talloc_realloc(ret, options.options, 139 const char *, num_options+3); 140 if (options.options == NULL) { 141 ldb_oom(ldb); 142 goto failed; 143 } 144 options.options[num_options] = poptGetOptArg(pc); 145 options.options[num_options+1] = NULL; 146 num_options++; 147 break; 148 149 case 'c': { 150 const char *cs = poptGetOptArg(pc); 151 const char *p, *q; 152 int cc; 153 154 for (p = cs, cc = 1; (q = strchr(p, ',')); cc++, p = q + 1) ; 155 156 options.controls = talloc_array(ret, char *, cc + 1); 157 if (options.controls == NULL) { 158 ldb_oom(ldb); 159 goto failed; 160 } 161 for (p = cs, cc = 0; p != NULL; cc++) { 162 const char *t; 163 164 t = strchr(p, ','); 165 if (t == NULL) { 166 options.controls[cc] = talloc_strdup(options.controls, p); 167 p = NULL; 168 } else { 169 options.controls[cc] = talloc_strndup(options.controls, p, t-p); 170 p = t + 1; 171 } 172 } 173 options.controls[cc] = NULL; 174 175 break; 176 } 177 default: 178 fprintf(stderr, "Invalid option %s: %s\n", 179 poptBadOption(pc, 0), poptStrerror(opt)); 180 if (usage) usage(); 181 goto failed; 182 } 183 } 184 185 /* setup the remaining options for the main program to use */ 186 options.argv = poptGetArgs(pc); 187 if (options.argv) { 188 options.argv++; 189 while (options.argv[options.argc]) options.argc++; 190 } 191 192 *ret = options; 193 194 /* all utils need some option */ 195 if (ret->url == NULL) { 196 fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); 197 if (usage) usage(); 198 goto failed; 199 } 200 201 if (strcmp(ret->url, "NONE") == 0) { 202 return ret; 203 } 204 205 if (options.nosync) { 206 flags |= LDB_FLG_NOSYNC; 207 } 208 209#if (_SAMBA_BUILD_ >= 4) 210 /* Must be after we have processed command line options */ 211 gensec_init(); 212 213 if (ldb_set_opaque(ldb, "sessionInfo", system_session(ldb))) { 214 goto failed; 215 } 216 if (ldb_set_opaque(ldb, "credentials", cmdline_credentials)) { 217 goto failed; 218 } 219 ldb_set_utf8_fns(ldb, NULL, wrap_casefold); 220#endif 221 222 /* now connect to the ldb */ 223 if (ldb_connect(ldb, ret->url, flags, ret->options) != 0) { 224 fprintf(stderr, "Failed to connect to %s - %s\n", 225 ret->url, ldb_errstring(ldb)); 226 goto failed; 227 } 228 229 return ret; 230 231failed: 232 talloc_free(ret); 233 exit(1); 234 return NULL; 235} 236 237struct ldb_control **parse_controls(void *mem_ctx, char **control_strings) 238{ 239 int i; 240 struct ldb_control **ctrl; 241 242 if (control_strings == NULL || control_strings[0] == NULL) 243 return NULL; 244 245 for (i = 0; control_strings[i]; i++); 246 247 ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1); 248 249 for (i = 0; control_strings[i]; i++) { 250 if (strncmp(control_strings[i], "vlv:", 4) == 0) { 251 struct ldb_vlv_req_control *control; 252 const char *p; 253 char attr[1024]; 254 char ctxid[1024]; 255 int crit, bc, ac, os, cc, ret; 256 257 attr[0] = '\0'; 258 ctxid[0] = '\0'; 259 p = &(control_strings[i][4]); 260 ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid); 261 if (ret < 5) { 262 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid); 263 } 264 265 if ((ret < 4) || (crit < 0) || (crit > 1)) { 266 fprintf(stderr, "invalid server_sort control syntax\n"); 267 fprintf(stderr, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n"); 268 fprintf(stderr, " note: b = boolean, n = number, s = string, o = b64 binary blob\n"); 269 return NULL; 270 } 271 if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) { 272 fprintf(stderr, "talloc failed\n"); 273 return NULL; 274 } 275 ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID; 276 ctrl[i]->critical = crit; 277 if (!(control = talloc(ctrl[i], 278 struct ldb_vlv_req_control))) { 279 fprintf(stderr, "talloc failed\n"); 280 return NULL; 281 } 282 control->beforeCount = bc; 283 control->afterCount = ac; 284 if (attr[0]) { 285 control->type = 1; 286 control->match.gtOrEq.value = talloc_strdup(control, attr); 287 control->match.gtOrEq.value_len = strlen(attr); 288 } else { 289 control->type = 0; 290 control->match.byOffset.offset = os; 291 control->match.byOffset.contentCount = cc; 292 } 293 if (ctxid[0]) { 294 control->ctxid_len = ldb_base64_decode(ctxid); 295 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len); 296 } else { 297 control->ctxid_len = 0; 298 control->contextId = NULL; 299 } 300 ctrl[i]->data = control; 301 302 continue; 303 } 304 305 if (strncmp(control_strings[i], "dirsync:", 8) == 0) { 306 struct ldb_dirsync_control *control; 307 const char *p; 308 char cookie[1024]; 309 int crit, flags, max_attrs, ret; 310 311 cookie[0] = '\0'; 312 p = &(control_strings[i][8]); 313 ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie); 314 315 if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) { 316 fprintf(stderr, "invalid dirsync control syntax\n"); 317 fprintf(stderr, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"); 318 fprintf(stderr, " note: b = boolean, n = number, o = b64 binary blob\n"); 319 return NULL; 320 } 321 322 /* w2k3 seems to ignore the parameter, 323 * but w2k sends a wrong cookie when this value is to small 324 * this would cause looping forever, while getting 325 * the same data and same cookie forever 326 */ 327 if (max_attrs == 0) max_attrs = 0x0FFFFFFF; 328 329 ctrl[i] = talloc(ctrl, struct ldb_control); 330 ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID; 331 ctrl[i]->critical = crit; 332 control = talloc(ctrl[i], struct ldb_dirsync_control); 333 control->flags = flags; 334 control->max_attributes = max_attrs; 335 if (*cookie) { 336 control->cookie_len = ldb_base64_decode(cookie); 337 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len); 338 } else { 339 control->cookie = NULL; 340 control->cookie_len = 0; 341 } 342 ctrl[i]->data = control; 343 344 continue; 345 } 346 347 if (strncmp(control_strings[i], "asq:", 4) == 0) { 348 struct ldb_asq_control *control; 349 const char *p; 350 char attr[256]; 351 int crit, ret; 352 353 attr[0] = '\0'; 354 p = &(control_strings[i][4]); 355 ret = sscanf(p, "%d:%255[^$]", &crit, attr); 356 if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) { 357 fprintf(stderr, "invalid asq control syntax\n"); 358 fprintf(stderr, " syntax: crit(b):attr(s)\n"); 359 fprintf(stderr, " note: b = boolean, s = string\n"); 360 return NULL; 361 } 362 363 ctrl[i] = talloc(ctrl, struct ldb_control); 364 ctrl[i]->oid = LDB_CONTROL_ASQ_OID; 365 ctrl[i]->critical = crit; 366 control = talloc(ctrl[i], struct ldb_asq_control); 367 control->request = 1; 368 control->source_attribute = talloc_strdup(control, attr); 369 control->src_attr_len = strlen(attr); 370 ctrl[i]->data = control; 371 372 continue; 373 } 374 375 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) { 376 struct ldb_extended_dn_control *control; 377 const char *p; 378 int crit, type, ret; 379 380 p = &(control_strings[i][12]); 381 ret = sscanf(p, "%d:%d", &crit, &type); 382 if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) { 383 fprintf(stderr, "invalid extended_dn control syntax\n"); 384 fprintf(stderr, " syntax: crit(b):type(b)\n"); 385 fprintf(stderr, " note: b = boolean\n"); 386 return NULL; 387 } 388 389 ctrl[i] = talloc(ctrl, struct ldb_control); 390 ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID; 391 ctrl[i]->critical = crit; 392 control = talloc(ctrl[i], struct ldb_extended_dn_control); 393 control->type = type; 394 ctrl[i]->data = control; 395 396 continue; 397 } 398 399 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) { 400 struct ldb_sd_flags_control *control; 401 const char *p; 402 int crit, ret; 403 unsigned secinfo_flags; 404 405 p = &(control_strings[i][9]); 406 ret = sscanf(p, "%d:%u", &crit, &secinfo_flags); 407 if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) { 408 fprintf(stderr, "invalid sd_flags control syntax\n"); 409 fprintf(stderr, " syntax: crit(b):secinfo_flags(n)\n"); 410 fprintf(stderr, " note: b = boolean, n = number\n"); 411 return NULL; 412 } 413 414 ctrl[i] = talloc(ctrl, struct ldb_control); 415 ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID; 416 ctrl[i]->critical = crit; 417 control = talloc(ctrl[i], struct ldb_sd_flags_control); 418 control->secinfo_flags = secinfo_flags; 419 ctrl[i]->data = control; 420 421 continue; 422 } 423 424 if (strncmp(control_strings[i], "search_options:", 15) == 0) { 425 struct ldb_search_options_control *control; 426 const char *p; 427 int crit, ret; 428 unsigned search_options; 429 430 p = &(control_strings[i][15]); 431 ret = sscanf(p, "%d:%u", &crit, &search_options); 432 if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) { 433 fprintf(stderr, "invalid search_options control syntax\n"); 434 fprintf(stderr, " syntax: crit(b):search_options(n)\n"); 435 fprintf(stderr, " note: b = boolean, n = number\n"); 436 return NULL; 437 } 438 439 ctrl[i] = talloc(ctrl, struct ldb_control); 440 ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID; 441 ctrl[i]->critical = crit; 442 control = talloc(ctrl[i], struct ldb_search_options_control); 443 control->search_options = search_options; 444 ctrl[i]->data = control; 445 446 continue; 447 } 448 449 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) { 450 const char *p; 451 int crit, ret; 452 453 p = &(control_strings[i][13]); 454 ret = sscanf(p, "%d", &crit); 455 if ((ret != 1) || (crit < 0) || (crit > 1)) { 456 fprintf(stderr, "invalid domain_scope control syntax\n"); 457 fprintf(stderr, " syntax: crit(b)\n"); 458 fprintf(stderr, " note: b = boolean\n"); 459 return NULL; 460 } 461 462 ctrl[i] = talloc(ctrl, struct ldb_control); 463 ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID; 464 ctrl[i]->critical = crit; 465 ctrl[i]->data = NULL; 466 467 continue; 468 } 469 470 if (strncmp(control_strings[i], "paged_results:", 14) == 0) { 471 struct ldb_paged_control *control; 472 const char *p; 473 int crit, size, ret; 474 475 p = &(control_strings[i][14]); 476 ret = sscanf(p, "%d:%d", &crit, &size); 477 478 if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) { 479 fprintf(stderr, "invalid paged_results control syntax\n"); 480 fprintf(stderr, " syntax: crit(b):size(n)\n"); 481 fprintf(stderr, " note: b = boolean, n = number\n"); 482 return NULL; 483 } 484 485 ctrl[i] = talloc(ctrl, struct ldb_control); 486 ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID; 487 ctrl[i]->critical = crit; 488 control = talloc(ctrl[i], struct ldb_paged_control); 489 control->size = size; 490 control->cookie = NULL; 491 control->cookie_len = 0; 492 ctrl[i]->data = control; 493 494 continue; 495 } 496 497 if (strncmp(control_strings[i], "server_sort:", 12) == 0) { 498 struct ldb_server_sort_control **control; 499 const char *p; 500 char attr[256]; 501 char rule[128]; 502 int crit, rev, ret; 503 504 attr[0] = '\0'; 505 rule[0] = '\0'; 506 p = &(control_strings[i][12]); 507 ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule); 508 if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') { 509 fprintf(stderr, "invalid server_sort control syntax\n"); 510 fprintf(stderr, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"); 511 fprintf(stderr, " note: b = boolean, s = string\n"); 512 return NULL; 513 } 514 ctrl[i] = talloc(ctrl, struct ldb_control); 515 ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID; 516 ctrl[i]->critical = crit; 517 control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2); 518 control[0] = talloc(control, struct ldb_server_sort_control); 519 control[0]->attributeName = talloc_strdup(control, attr); 520 if (rule[0]) 521 control[0]->orderingRule = talloc_strdup(control, rule); 522 else 523 control[0]->orderingRule = NULL; 524 control[0]->reverse = rev; 525 control[1] = NULL; 526 ctrl[i]->data = control; 527 528 continue; 529 } 530 531 if (strncmp(control_strings[i], "notification:", 13) == 0) { 532 const char *p; 533 int crit, ret; 534 535 p = &(control_strings[i][13]); 536 ret = sscanf(p, "%d", &crit); 537 if ((ret != 1) || (crit < 0) || (crit > 1)) { 538 fprintf(stderr, "invalid notification control syntax\n"); 539 fprintf(stderr, " syntax: crit(b)\n"); 540 fprintf(stderr, " note: b = boolean\n"); 541 return NULL; 542 } 543 544 ctrl[i] = talloc(ctrl, struct ldb_control); 545 ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID; 546 ctrl[i]->critical = crit; 547 ctrl[i]->data = NULL; 548 549 continue; 550 } 551 552 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) { 553 const char *p; 554 int crit, ret; 555 556 p = &(control_strings[i][13]); 557 ret = sscanf(p, "%d", &crit); 558 if ((ret != 1) || (crit < 0) || (crit > 1)) { 559 fprintf(stderr, "invalid show_deleted control syntax\n"); 560 fprintf(stderr, " syntax: crit(b)\n"); 561 fprintf(stderr, " note: b = boolean\n"); 562 return NULL; 563 } 564 565 ctrl[i] = talloc(ctrl, struct ldb_control); 566 ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID; 567 ctrl[i]->critical = crit; 568 ctrl[i]->data = NULL; 569 570 continue; 571 } 572 573 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) { 574 const char *p; 575 int crit, ret; 576 577 p = &(control_strings[i][18]); 578 ret = sscanf(p, "%d", &crit); 579 if ((ret != 1) || (crit < 0) || (crit > 1)) { 580 fprintf(stderr, "invalid permissive_modify control syntax\n"); 581 fprintf(stderr, " syntax: crit(b)\n"); 582 fprintf(stderr, " note: b = boolean\n"); 583 return NULL; 584 } 585 586 ctrl[i] = talloc(ctrl, struct ldb_control); 587 ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID; 588 ctrl[i]->critical = crit; 589 ctrl[i]->data = NULL; 590 591 continue; 592 } 593 594 /* no controls matched, throw an error */ 595 fprintf(stderr, "Invalid control name: '%s'\n", control_strings[i]); 596 return NULL; 597 } 598 599 ctrl[i] = NULL; 600 601 return ctrl; 602} 603 604 605/* this function check controls reply and determines if more 606 * processing is needed setting up the request controls correctly 607 * 608 * returns: 609 * -1 error 610 * 0 all ok 611 * 1 all ok, more processing required 612 */ 613int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request) 614{ 615 int i, j; 616 int ret = 0; 617 618 if (reply == NULL || request == NULL) return -1; 619 620 for (i = 0; reply[i]; i++) { 621 if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) { 622 struct ldb_vlv_resp_control *rep_control; 623 624 rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control); 625 626 /* check we have a matching control in the request */ 627 for (j = 0; request[j]; j++) { 628 if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0) 629 break; 630 } 631 if (! request[j]) { 632 fprintf(stderr, "Warning VLV reply received but no request have been made\n"); 633 continue; 634 } 635 636 /* check the result */ 637 if (rep_control->vlv_result != 0) { 638 fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result); 639 } else { 640 fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount); 641 } 642 643 continue; 644 } 645 646 if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) { 647 struct ldb_asq_control *rep_control; 648 649 rep_control = talloc_get_type(reply[i]->data, struct ldb_asq_control); 650 651 /* check the result */ 652 if (rep_control->result != 0) { 653 fprintf(stderr, "Warning: ASQ not performed with error: %d\n", rep_control->result); 654 } 655 656 continue; 657 } 658 659 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) { 660 struct ldb_paged_control *rep_control, *req_control; 661 662 rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control); 663 if (rep_control->cookie_len == 0) /* we are done */ 664 break; 665 666 /* more processing required */ 667 /* let's fill in the request control with the new cookie */ 668 669 for (j = 0; request[j]; j++) { 670 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0) 671 break; 672 } 673 /* if there's a reply control we must find a request 674 * control matching it */ 675 if (! request[j]) return -1; 676 677 req_control = talloc_get_type(request[j]->data, struct ldb_paged_control); 678 679 if (req_control->cookie) 680 talloc_free(req_control->cookie); 681 req_control->cookie = (char *)talloc_memdup( 682 req_control, rep_control->cookie, 683 rep_control->cookie_len); 684 req_control->cookie_len = rep_control->cookie_len; 685 686 ret = 1; 687 688 continue; 689 } 690 691 if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) { 692 struct ldb_sort_resp_control *rep_control; 693 694 rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control); 695 696 /* check we have a matching control in the request */ 697 for (j = 0; request[j]; j++) { 698 if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0) 699 break; 700 } 701 if (! request[j]) { 702 fprintf(stderr, "Warning Server Sort reply received but no request found\n"); 703 continue; 704 } 705 706 /* check the result */ 707 if (rep_control->result != 0) { 708 fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result); 709 } 710 711 continue; 712 } 713 714 if (strcmp(LDB_CONTROL_DIRSYNC_OID, reply[i]->oid) == 0) { 715 struct ldb_dirsync_control *rep_control, *req_control; 716 char *cookie; 717 718 rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control); 719 if (rep_control->cookie_len == 0) /* we are done */ 720 break; 721 722 /* more processing required */ 723 /* let's fill in the request control with the new cookie */ 724 725 for (j = 0; request[j]; j++) { 726 if (strcmp(LDB_CONTROL_DIRSYNC_OID, request[j]->oid) == 0) 727 break; 728 } 729 /* if there's a reply control we must find a request 730 * control matching it */ 731 if (! request[j]) return -1; 732 733 req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control); 734 735 if (req_control->cookie) 736 talloc_free(req_control->cookie); 737 req_control->cookie = (char *)talloc_memdup( 738 req_control, rep_control->cookie, 739 rep_control->cookie_len); 740 req_control->cookie_len = rep_control->cookie_len; 741 742 cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len); 743 printf("# DIRSYNC cookie returned was:\n# %s\n", cookie); 744 745 continue; 746 } 747 748 /* no controls matched, throw a warning */ 749 fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid); 750 } 751 752 return ret; 753} 754 755