Line data Source code
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 "replace.h"
25 : #include "system/filesys.h"
26 : #include "system/time.h"
27 : #include "ldb.h"
28 : #include "ldb_module.h"
29 : #include "tools/cmdline.h"
30 :
31 : static struct ldb_cmdline options; /* needs to be static for older compilers */
32 :
33 : enum ldb_cmdline_options { CMDLINE_RELAX=1 };
34 :
35 : static struct poptOption builtin_popt_options[] = {
36 : POPT_AUTOHELP
37 : {
38 : .longName = "url",
39 : .shortName = 'H',
40 : .argInfo = POPT_ARG_STRING,
41 : .arg = &options.url,
42 : .val = 0,
43 : .descrip = "database URL",
44 : .argDescrip = "URL"
45 : },
46 : {
47 : .longName = "basedn",
48 : .shortName = 'b',
49 : .argInfo = POPT_ARG_STRING,
50 : .arg = &options.basedn,
51 : .val = 0,
52 : .descrip = "base DN",
53 : .argDescrip = "DN"
54 : },
55 : {
56 : .longName = "editor",
57 : .shortName = 'e',
58 : .argInfo = POPT_ARG_STRING,
59 : .arg = &options.editor,
60 : .val = 0,
61 : .descrip = "external editor",
62 : .argDescrip = "PROGRAM"
63 : },
64 : {
65 : .longName = "scope",
66 : .shortName = 's',
67 : .argInfo = POPT_ARG_STRING,
68 : .arg = NULL,
69 : .val = 's',
70 : .descrip = "search scope",
71 : .argDescrip = "SCOPE"
72 : },
73 : {
74 : .longName = "verbose",
75 : .shortName = 'v',
76 : .argInfo = POPT_ARG_NONE,
77 : .arg = NULL,
78 : .val = 'v',
79 : .descrip = "increase verbosity",
80 : .argDescrip = NULL
81 : },
82 : {
83 : .longName = "trace",
84 : .shortName = 0,
85 : .argInfo = POPT_ARG_NONE,
86 : .arg = &options.tracing,
87 : .val = 0,
88 : .descrip = "enable tracing",
89 : .argDescrip = NULL
90 : },
91 : {
92 : .longName = "interactive",
93 : .shortName = 'i',
94 : .argInfo = POPT_ARG_NONE,
95 : .arg = &options.interactive,
96 : .val = 0,
97 : .descrip = "input from stdin",
98 : .argDescrip = NULL
99 : },
100 : {
101 : .longName = "recursive",
102 : .shortName = 'r',
103 : .argInfo = POPT_ARG_NONE,
104 : .arg = &options.recursive,
105 : .val = 0,
106 : .descrip = "recursive delete",
107 : .argDescrip = NULL
108 : },
109 : {
110 : .longName = "modules-path",
111 : .shortName = 0,
112 : .argInfo = POPT_ARG_STRING,
113 : .arg = &options.modules_path,
114 : .val = 0,
115 : .descrip = "modules path",
116 : .argDescrip = "PATH"
117 : },
118 : {
119 : .longName = "num-searches",
120 : .shortName = 0,
121 : .argInfo = POPT_ARG_INT,
122 : .arg = &options.num_searches,
123 : .val = 0,
124 : .descrip = "number of test searches",
125 : .argDescrip = NULL
126 : },
127 : {
128 : .longName = "num-records",
129 : .shortName = 0,
130 : .argInfo = POPT_ARG_INT,
131 : .arg = &options.num_records,
132 : .val = 0,
133 : .descrip = "number of test records",
134 : .argDescrip = NULL
135 : },
136 : {
137 : .longName = "all",
138 : .shortName = 'a',
139 : .argInfo = POPT_ARG_NONE,
140 : .arg = &options.all_records,
141 : .val = 0,
142 : .descrip = "(|(objectClass=*)(distinguishedName=*))",
143 : .argDescrip = NULL
144 : },
145 : {
146 : .longName = "nosync",
147 : .shortName = 0,
148 : .argInfo = POPT_ARG_NONE,
149 : .arg = &options.nosync,
150 : .val = 0,
151 : .descrip = "non-synchronous transactions",
152 : .argDescrip = NULL
153 : },
154 : {
155 : .longName = "sorted",
156 : .shortName = 'S',
157 : .argInfo = POPT_ARG_NONE,
158 : .arg = &options.sorted,
159 : .val = 0,
160 : .descrip = "sort attributes",
161 : .argDescrip = NULL
162 : },
163 : {
164 : .longName = NULL,
165 : .shortName = 'o',
166 : .argInfo = POPT_ARG_STRING,
167 : .arg = NULL,
168 : .val = 'o',
169 : .descrip = "ldb_connect option",
170 : .argDescrip = "OPTION"
171 : },
172 : {
173 : .longName = "controls",
174 : .shortName = 0,
175 : .argInfo = POPT_ARG_STRING,
176 : .arg = NULL,
177 : .val = 'c',
178 : .descrip = "controls",
179 : .argDescrip = NULL
180 : },
181 : {
182 : .longName = "show-binary",
183 : .shortName = 0,
184 : .argInfo = POPT_ARG_NONE,
185 : .arg = &options.show_binary,
186 : .val = 0,
187 : .descrip = "display binary LDIF",
188 : .argDescrip = NULL
189 : },
190 : {
191 : .longName = "paged",
192 : .shortName = 0,
193 : .argInfo = POPT_ARG_NONE,
194 : .arg = NULL,
195 : .val = 'P',
196 : .descrip = "use a paged search",
197 : .argDescrip = NULL
198 : },
199 : {
200 : .longName = "show-deleted",
201 : .shortName = 0,
202 : .argInfo = POPT_ARG_NONE,
203 : .arg = NULL,
204 : .val = 'D',
205 : .descrip = "show deleted objects",
206 : .argDescrip = NULL
207 : },
208 : {
209 : .longName = "show-recycled",
210 : .shortName = 0,
211 : .argInfo = POPT_ARG_NONE,
212 : .arg = NULL,
213 : .val = 'R',
214 : .descrip = "show recycled objects",
215 : .argDescrip = NULL
216 : },
217 : {
218 : .longName = "show-deactivated-link",
219 : .shortName = 0,
220 : .argInfo = POPT_ARG_NONE,
221 : .arg = NULL,
222 : .val = 'd',
223 : .descrip = "show deactivated links",
224 : .argDescrip = NULL
225 : },
226 : {
227 : .longName = "reveal",
228 : .shortName = 0,
229 : .argInfo = POPT_ARG_NONE,
230 : .arg = NULL,
231 : .val = 'r',
232 : .descrip = "reveal ldb internals",
233 : .argDescrip = NULL
234 : },
235 : {
236 : .longName = "relax",
237 : .shortName = 0,
238 : .argInfo = POPT_ARG_NONE,
239 : .arg = NULL,
240 : .val = CMDLINE_RELAX,
241 : .descrip = "pass relax control",
242 : .argDescrip = NULL
243 : },
244 : {
245 : .longName = "cross-ncs",
246 : .shortName = 0,
247 : .argInfo = POPT_ARG_NONE,
248 : .arg = NULL,
249 : .val = 'N',
250 : .descrip = "search across NC boundaries",
251 : .argDescrip = NULL
252 : },
253 : {
254 : .longName = "extended-dn",
255 : .shortName = 0,
256 : .argInfo = POPT_ARG_NONE,
257 : .arg = NULL,
258 : .val = 'E',
259 : .descrip = "show extended DNs",
260 : .argDescrip = NULL
261 : },
262 : POPT_TABLEEND
263 : };
264 :
265 6 : void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f)
266 : {
267 0 : poptContext pc;
268 6 : struct poptOption **popt_options = ldb_module_popt_options(ldb);
269 6 : pc = poptGetContext(cmdname, 0, NULL, *popt_options,
270 : POPT_CONTEXT_KEEP_FIRST);
271 6 : poptPrintHelp(pc, f, 0);
272 6 : }
273 :
274 : /*
275 : add a control to the options structure
276 : */
277 232 : static bool add_control(TALLOC_CTX *mem_ctx, const char *control)
278 : {
279 37 : unsigned int i;
280 :
281 : /* count how many controls we already have */
282 278 : for (i=0; options.controls && options.controls[i]; i++) ;
283 :
284 232 : options.controls = talloc_realloc(mem_ctx, options.controls, const char *, i + 2);
285 232 : if (options.controls == NULL) {
286 0 : return false;
287 : }
288 232 : options.controls[i] = control;
289 232 : options.controls[i+1] = NULL;
290 232 : return true;
291 : }
292 :
293 : /**
294 : process command line options
295 : */
296 1538 : static struct ldb_cmdline *ldb_cmdline_process_internal(struct ldb_context *ldb,
297 : int argc, const char **argv,
298 : void (*usage)(struct ldb_context *),
299 : bool dont_create,
300 : bool search)
301 : {
302 1538 : struct ldb_cmdline *ret=NULL;
303 192 : poptContext pc;
304 1538 : int num_options = 0;
305 192 : int opt;
306 1538 : unsigned int flags = 0;
307 192 : int rc;
308 192 : struct poptOption **popt_options;
309 :
310 : /* make the ldb utilities line buffered */
311 1538 : setlinebuf(stdout);
312 :
313 1538 : ret = talloc_zero(ldb, struct ldb_cmdline);
314 1538 : if (ret == NULL) {
315 0 : fprintf(stderr, "Out of memory!\n");
316 0 : goto failed;
317 : }
318 :
319 1538 : options = *ret;
320 :
321 : /* pull in URL */
322 1538 : options.url = getenv("LDB_URL");
323 :
324 : /* and editor (used by ldbedit) */
325 1538 : options.editor = getenv("VISUAL");
326 1538 : if (!options.editor) {
327 1538 : options.editor = getenv("EDITOR");
328 : }
329 1538 : if (!options.editor) {
330 1538 : options.editor = "vi";
331 : }
332 :
333 1538 : options.scope = LDB_SCOPE_DEFAULT;
334 :
335 1538 : popt_options = ldb_module_popt_options(ldb);
336 1538 : (*popt_options) = builtin_popt_options;
337 :
338 1538 : rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_OPTIONS);
339 1538 : if (rc != LDB_SUCCESS) {
340 0 : fprintf(stderr, "ldb: failed to run command line hooks : %s\n", ldb_strerror(rc));
341 0 : goto failed;
342 : }
343 :
344 1538 : pc = poptGetContext(argv[0], argc, argv, *popt_options,
345 : POPT_CONTEXT_KEEP_FIRST);
346 :
347 2247 : while((opt = poptGetNextOpt(pc)) != -1) {
348 715 : switch (opt) {
349 486 : case 's': {
350 486 : const char *arg = poptGetOptArg(pc);
351 486 : if (strcmp(arg, "base") == 0) {
352 438 : options.scope = LDB_SCOPE_BASE;
353 48 : } else if (strcmp(arg, "sub") == 0) {
354 25 : options.scope = LDB_SCOPE_SUBTREE;
355 23 : } else if (strcmp(arg, "one") == 0) {
356 23 : options.scope = LDB_SCOPE_ONELEVEL;
357 : } else {
358 0 : fprintf(stderr, "Invalid scope '%s'\n", arg);
359 0 : goto failed;
360 : }
361 447 : break;
362 : }
363 :
364 2 : case 'v':
365 2 : options.verbose++;
366 2 : break;
367 :
368 0 : case 'o':
369 0 : options.options = talloc_realloc(ret, options.options,
370 : const char *, num_options+3);
371 0 : if (options.options == NULL) {
372 0 : fprintf(stderr, "Out of memory!\n");
373 0 : goto failed;
374 : }
375 0 : options.options[num_options] = poptGetOptArg(pc);
376 0 : options.options[num_options+1] = NULL;
377 0 : num_options++;
378 0 : break;
379 :
380 139 : case 'c': {
381 139 : const char *cs = poptGetOptArg(pc);
382 3 : const char *p;
383 :
384 292 : for (p = cs; p != NULL; ) {
385 3 : const char *t, *c;
386 :
387 150 : t = strchr(p, ',');
388 150 : if (t == NULL) {
389 139 : c = talloc_strdup(options.controls, p);
390 139 : p = NULL;
391 : } else {
392 11 : c = talloc_strndup(options.controls, p, t-p);
393 11 : p = t + 1;
394 : }
395 150 : if (c == NULL || !add_control(ret, c)) {
396 0 : fprintf(stderr, __location__ ": out of memory\n");
397 0 : goto failed;
398 : }
399 : }
400 :
401 136 : break;
402 : }
403 0 : case 'P':
404 0 : if (!add_control(ret, "paged_results:1:1024")) {
405 0 : fprintf(stderr, __location__ ": out of memory\n");
406 0 : goto failed;
407 : }
408 0 : break;
409 27 : case 'D':
410 27 : if (!add_control(ret, "show_deleted:1")) {
411 0 : fprintf(stderr, __location__ ": out of memory\n");
412 0 : goto failed;
413 : }
414 12 : break;
415 4 : case 'R':
416 4 : if (!add_control(ret, "show_recycled:0")) {
417 0 : fprintf(stderr, __location__ ": out of memory\n");
418 0 : goto failed;
419 : }
420 2 : break;
421 2 : case 'd':
422 2 : if (!add_control(ret, "show_deactivated_link:0")) {
423 0 : fprintf(stderr, __location__ ": out of memory\n");
424 0 : goto failed;
425 : }
426 0 : break;
427 23 : case 'r':
428 23 : if (!add_control(ret, "reveal_internals:0")) {
429 0 : fprintf(stderr, __location__ ": out of memory\n");
430 0 : goto failed;
431 : }
432 9 : break;
433 12 : case CMDLINE_RELAX:
434 12 : if (!add_control(ret, "relax:0")) {
435 0 : fprintf(stderr, __location__ ": out of memory\n");
436 0 : goto failed;
437 : }
438 11 : break;
439 0 : case 'N':
440 0 : if (!add_control(ret, "search_options:1:2")) {
441 0 : fprintf(stderr, __location__ ": out of memory\n");
442 0 : goto failed;
443 : }
444 0 : break;
445 14 : case 'E':
446 14 : if (!add_control(ret, "extended_dn:1:1")) {
447 0 : fprintf(stderr, __location__ ": out of memory\n");
448 0 : goto failed;
449 : }
450 14 : break;
451 6 : default:
452 6 : fprintf(stderr, "Invalid option %s: %s\n",
453 : poptBadOption(pc, 0), poptStrerror(opt));
454 6 : if (usage) usage(ldb);
455 0 : goto failed;
456 : }
457 : }
458 :
459 : /* setup the remaining options for the main program to use */
460 1526 : options.argv = poptGetArgs(pc);
461 1526 : if (options.argv) {
462 1526 : options.argv++;
463 2778 : while (options.argv[options.argc]) options.argc++;
464 : }
465 :
466 1526 : *ret = options;
467 :
468 : /* all utils need some option */
469 1526 : if (ret->url == NULL) {
470 0 : fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n");
471 0 : if (usage) usage(ldb);
472 0 : goto failed;
473 : }
474 :
475 1526 : if (strcmp(ret->url, "NONE") == 0) {
476 0 : return ret;
477 : }
478 :
479 1526 : if (options.nosync) {
480 0 : flags |= LDB_FLG_NOSYNC;
481 : }
482 :
483 1526 : if (search) {
484 924 : flags |= LDB_FLG_DONT_CREATE_DB;
485 :
486 924 : if (options.show_binary) {
487 20 : flags |= LDB_FLG_SHOW_BINARY;
488 : }
489 : }
490 :
491 1526 : if (options.tracing) {
492 0 : flags |= LDB_FLG_ENABLE_TRACING;
493 : }
494 :
495 1526 : if (options.modules_path != NULL) {
496 0 : ldb_set_modules_dir(ldb, options.modules_path);
497 : }
498 :
499 1526 : rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT);
500 1526 : if (rc != LDB_SUCCESS) {
501 0 : fprintf(stderr, "ldb: failed to run preconnect hooks : %s\n", ldb_strerror(rc));
502 0 : goto failed;
503 : }
504 :
505 : /* now connect to the ldb */
506 1526 : if (ldb_connect(ldb, ret->url, flags, ret->options) != LDB_SUCCESS) {
507 24 : fprintf(stderr, "Failed to connect to %s - %s\n",
508 : ret->url, ldb_errstring(ldb));
509 24 : goto failed;
510 : }
511 :
512 1502 : rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT);
513 1502 : if (rc != LDB_SUCCESS) {
514 0 : fprintf(stderr, "ldb: failed to run post connect hooks : %s\n", ldb_strerror(rc));
515 0 : goto failed;
516 : }
517 :
518 1311 : return ret;
519 :
520 24 : failed:
521 24 : talloc_free(ret);
522 24 : exit(LDB_ERR_OPERATIONS_ERROR);
523 : return NULL;
524 : }
525 :
526 926 : struct ldb_cmdline *ldb_cmdline_process_search(struct ldb_context *ldb,
527 : int argc, const char **argv,
528 : void (*usage)(struct ldb_context *))
529 : {
530 926 : return ldb_cmdline_process_internal(ldb, argc, argv, usage, true, true);
531 : }
532 :
533 2 : struct ldb_cmdline *ldb_cmdline_process_edit(struct ldb_context *ldb,
534 : int argc, const char **argv,
535 : void (*usage)(struct ldb_context *))
536 : {
537 2 : return ldb_cmdline_process_internal(ldb, argc, argv, usage, false, true);
538 : }
539 :
540 610 : struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
541 : int argc, const char **argv,
542 : void (*usage)(struct ldb_context *))
543 : {
544 610 : return ldb_cmdline_process_internal(ldb, argc, argv, usage, false, false);
545 : }
546 :
547 : /* this function check controls reply and determines if more
548 : * processing is needed setting up the request controls correctly
549 : *
550 : * returns:
551 : * -1 error
552 : * 0 all ok
553 : * 1 all ok, more processing required
554 : */
555 44 : int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request)
556 : {
557 0 : unsigned int i, j;
558 44 : int ret = 0;
559 :
560 44 : if (reply == NULL || request == NULL) return -1;
561 :
562 77 : for (i = 0; reply[i]; i++) {
563 44 : if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) {
564 0 : struct ldb_vlv_resp_control *rep_control;
565 :
566 0 : rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control);
567 0 : if (rep_control == NULL) {
568 0 : fprintf(stderr,
569 : "Warning VLV reply OID received "
570 : "with no VLV data\n");
571 0 : continue;
572 : }
573 :
574 : /* check we have a matching control in the request */
575 0 : for (j = 0; request[j]; j++) {
576 0 : if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0)
577 0 : break;
578 : }
579 0 : if (! request[j]) {
580 0 : fprintf(stderr, "Warning VLV reply received but no request have been made\n");
581 0 : continue;
582 : }
583 :
584 : /* check the result */
585 0 : if (rep_control->vlv_result != 0) {
586 0 : fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result);
587 : } else {
588 0 : fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount);
589 : }
590 :
591 0 : continue;
592 : }
593 :
594 44 : if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) {
595 0 : struct ldb_asq_control *rep_control;
596 :
597 11 : rep_control = talloc_get_type(reply[i]->data, struct ldb_asq_control);
598 11 : if (rep_control == NULL) {
599 0 : fprintf(stderr,
600 : "Warning ASQ reply OID received "
601 : "with no ASQ data\n");
602 0 : continue;
603 : }
604 :
605 : /* check the result */
606 11 : if (rep_control->result != 0) {
607 0 : fprintf(stderr, "Warning: ASQ not performed with error: %d\n", rep_control->result);
608 : }
609 :
610 11 : continue;
611 : }
612 :
613 33 : if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) {
614 0 : struct ldb_paged_control *rep_control, *req_control;
615 :
616 33 : rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control);
617 33 : if (rep_control == NULL) {
618 0 : fprintf(stderr,
619 : "Warning PAGED_RESULTS reply OID "
620 : "received with no data\n");
621 0 : continue;
622 : }
623 :
624 33 : if (rep_control->cookie_len == 0) { /* we are done */
625 11 : break;
626 : }
627 :
628 : /* more processing required */
629 : /* let's fill in the request control with the new cookie */
630 :
631 22 : for (j = 0; request[j]; j++) {
632 22 : if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0)
633 22 : break;
634 : }
635 : /* if there's a reply control we must find a request
636 : * control matching it */
637 22 : if (! request[j]) return -1;
638 :
639 22 : req_control = talloc_get_type(request[j]->data, struct ldb_paged_control);
640 :
641 22 : if (req_control->cookie)
642 11 : talloc_free(req_control->cookie);
643 22 : req_control->cookie = (char *)talloc_memdup(
644 : req_control, rep_control->cookie,
645 : rep_control->cookie_len);
646 22 : req_control->cookie_len = rep_control->cookie_len;
647 :
648 22 : ret = 1;
649 :
650 22 : continue;
651 : }
652 :
653 0 : if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) {
654 0 : struct ldb_sort_resp_control *rep_control;
655 :
656 0 : rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control);
657 0 : if (rep_control == NULL) {
658 0 : fprintf(stderr,
659 : "Warning SORT reply OID "
660 : "received with no data\n");
661 0 : continue;
662 : }
663 :
664 : /* check we have a matching control in the request */
665 0 : for (j = 0; request[j]; j++) {
666 0 : if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0)
667 0 : break;
668 : }
669 0 : if (! request[j]) {
670 0 : fprintf(stderr, "Warning Server Sort reply received but no request found\n");
671 0 : continue;
672 : }
673 :
674 : /* check the result */
675 0 : if (rep_control->result != 0) {
676 0 : fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result);
677 : }
678 :
679 0 : continue;
680 : }
681 :
682 0 : if (strcmp(LDB_CONTROL_DIRSYNC_OID, reply[i]->oid) == 0) {
683 0 : struct ldb_dirsync_control *rep_control, *req_control;
684 0 : char *cookie;
685 :
686 0 : rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control);
687 0 : if (rep_control == NULL) {
688 0 : fprintf(stderr,
689 : "Warning DIRSYNC reply OID "
690 : "received with no data\n");
691 0 : continue;
692 : }
693 0 : if (rep_control->cookie_len == 0) /* we are done */
694 0 : break;
695 :
696 : /* more processing required */
697 : /* let's fill in the request control with the new cookie */
698 :
699 0 : for (j = 0; request[j]; j++) {
700 0 : if (strcmp(LDB_CONTROL_DIRSYNC_OID, request[j]->oid) == 0)
701 0 : break;
702 : }
703 : /* if there's a reply control we must find a request
704 : * control matching it */
705 0 : if (! request[j]) return -1;
706 :
707 0 : req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control);
708 :
709 0 : if (req_control->cookie)
710 0 : talloc_free(req_control->cookie);
711 0 : req_control->cookie = (char *)talloc_memdup(
712 : req_control, rep_control->cookie,
713 : rep_control->cookie_len);
714 0 : req_control->cookie_len = rep_control->cookie_len;
715 :
716 0 : cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
717 0 : printf("# DIRSYNC cookie returned was:\n# %s\n", cookie);
718 :
719 0 : continue;
720 : }
721 0 : if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, reply[i]->oid) == 0) {
722 0 : struct ldb_dirsync_control *rep_control, *req_control;
723 0 : char *cookie;
724 :
725 0 : rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control);
726 0 : if (rep_control == NULL) {
727 0 : fprintf(stderr,
728 : "Warning DIRSYNC_EX reply OID "
729 : "received with no data\n");
730 0 : continue;
731 : }
732 0 : if (rep_control->cookie_len == 0) /* we are done */
733 0 : break;
734 :
735 : /* more processing required */
736 : /* let's fill in the request control with the new cookie */
737 :
738 0 : for (j = 0; request[j]; j++) {
739 0 : if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, request[j]->oid) == 0)
740 0 : break;
741 : }
742 : /* if there's a reply control we must find a request
743 : * control matching it */
744 0 : if (! request[j]) return -1;
745 :
746 0 : req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control);
747 :
748 0 : if (req_control->cookie)
749 0 : talloc_free(req_control->cookie);
750 0 : req_control->cookie = (char *)talloc_memdup(
751 : req_control, rep_control->cookie,
752 : rep_control->cookie_len);
753 0 : req_control->cookie_len = rep_control->cookie_len;
754 :
755 0 : cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
756 0 : printf("# DIRSYNC_EX cookie returned was:\n# %s\n", cookie);
757 :
758 0 : continue;
759 : }
760 :
761 : /* no controls matched, throw a warning */
762 0 : fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid);
763 : }
764 :
765 44 : return ret;
766 : }
|