1 /* ldapsearch -- a tool for searching LDAP directories */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 1998-2021 The OpenLDAP Foundation.
6 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
7 * Portions Copyright 1998-2001 Net Boolean Incorporated.
8 * Portions Copyright 2001-2003 IBM Corporation.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms are permitted
23 * provided that this notice is preserved and that due credit is given
24 * to the University of Michigan at Ann Arbor. The name of the
25 * University may not be used to endorse or promote products derived
26 * from this software without specific prior written permission. This
27 * software is provided ``as is'' without express or implied warranty.
28 */
29 /* ACKNOWLEDGEMENTS:
30 * This work was originally developed by the University of Michigan
31 * (as part of U-MICH LDAP). Additional significant contributors
32 * include:
33 * Jong Hyuk Choi
34 * Lynn Moss
35 * Mikhail Sahalaev
36 * Kurt D. Zeilenga
37 */
38
39 #include "portable.h"
40
41 #include <stdio.h>
42
43 #include <ac/stdlib.h>
44 #include <ac/ctype.h>
45 #include <ac/string.h>
46 #include <ac/unistd.h>
47 #include <ac/errno.h>
48 #include <ac/time.h>
49
50 #include <sys/stat.h>
51
52 #include <ac/signal.h>
53
54 #ifdef HAVE_FCNTL_H
55 #include <fcntl.h>
56 #endif
57 #ifdef HAVE_SYS_TYPES_H
58 #include <sys/types.h>
59 #endif
60 #ifdef HAVE_IO_H
61 #include <io.h>
62 #endif
63
64 #include <ldap.h>
65
66 #include "ldif.h"
67 #include "lutil.h"
68 #include "lutil_ldap.h"
69 #include "ldap_defaults.h"
70 #include "ldap_pvt.h"
71
72 #include "common.h"
73
74 #if !LDAP_DEPRECATED
75 /*
76 * NOTE: we use this deprecated function only because
77 * we want ldapsearch to provide some client-side sorting
78 * capability.
79 */
80 /* from ldap.h */
81 typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */
82 LDAP_CONST char *left,
83 LDAP_CONST char *right ));
84
85 LDAP_F( int ) /* deprecated */
86 ldap_sort_entries LDAP_P(( LDAP *ld,
87 LDAPMessage **chain,
88 LDAP_CONST char *attr,
89 LDAP_SORT_AD_CMP_PROC *cmp ));
90 #endif
91
92 static int scope = LDAP_SCOPE_SUBTREE;
93 static int deref = -1;
94 static int attrsonly;
95 static int timelimit = -1;
96 static int sizelimit = -1;
97
98 static char *control;
99
100 static char *def_tmpdir;
101 static char *def_urlpre;
102
103 #if defined(__CYGWIN__) || defined(__MINGW32__)
104 /* Turn off commandline globbing, otherwise you cannot search for
105 * attribute '*'
106 */
107 int _CRT_glob = 0;
108 #endif
109
110 void
usage(void)111 usage( void )
112 {
113 fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog);
114 fprintf( stderr, _(" filter\tRFC 4515 compliant LDAP search filter\n"));
115 fprintf( stderr, _(" attributes\twhitespace-separated list of attribute descriptions\n"));
116 fprintf( stderr, _(" which may include:\n"));
117 fprintf( stderr, _(" 1.1 no attributes\n"));
118 fprintf( stderr, _(" * all user attributes\n"));
119 fprintf( stderr, _(" + all operational attributes\n"));
120
121
122 fprintf( stderr, _("Search options:\n"));
123 fprintf( stderr, _(" -a deref one of never (default), always, search, or find\n"));
124 fprintf( stderr, _(" -A retrieve attribute names only (no values)\n"));
125 fprintf( stderr, _(" -b basedn base dn for search\n"));
126 fprintf( stderr, _(" -c continuous operation mode (do not stop on errors)\n"));
127 fprintf( stderr, _(" -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n"));
128 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
129 fprintf( stderr, _(" [!]accountUsability (NetScape Account usability)\n"));
130 #endif
131 fprintf( stderr, _(" [!]domainScope (domain scope)\n"));
132 fprintf( stderr, _(" !dontUseCopy (Don't Use Copy)\n"));
133 fprintf( stderr, _(" [!]mv=<filter> (RFC 3876 matched values filter)\n"));
134 fprintf( stderr, _(" [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
135 fprintf( stderr, _(" [!]ps=<changetypes>/<changesonly>/<echg> (draft persistent search)\n"));
136 fprintf( stderr, _(" [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
137 fprintf( stderr, _(" (RFC 2891 server side sorting)\n"));
138 fprintf( stderr, _(" [!]subentries[=true|false] (RFC 3672 subentries)\n"));
139 fprintf( stderr, _(" [!]sync=ro[/<cookie>] (RFC 4533 LDAP Sync refreshOnly)\n"));
140 fprintf( stderr, _(" rp[/<cookie>][/<slimit>] (refreshAndPersist)\n"));
141 fprintf( stderr, _(" [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n"));
142 fprintf( stderr, _(" (ldapv3-vlv-09 virtual list views)\n"));
143 #ifdef LDAP_CONTROL_X_DEREF
144 fprintf( stderr, _(" [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
145 #endif
146 #ifdef LDAP_CONTROL_X_DIRSYNC
147 fprintf( stderr, _(" !dirSync=<flags>/<maxAttrCount>[/<cookie>]\n"));
148 fprintf( stderr, _(" (MS AD DirSync)\n"));
149 #endif
150 #ifdef LDAP_CONTROL_X_EXTENDED_DN
151 fprintf( stderr, _(" [!]extendedDn=<flag> (MS AD Extended DN\n"));
152 #endif
153 #ifdef LDAP_CONTROL_X_SHOW_DELETED
154 fprintf( stderr, _(" [!]showDeleted (MS AD Show Deleted)\n"));
155 #endif
156 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
157 fprintf( stderr, _(" [!]serverNotif (MS AD Server Notification)\n"));
158 #endif
159 fprintf( stderr, _(" [!]<oid>[=:<value>|::<b64value>] (generic control; no response handling)\n"));
160 fprintf( stderr, _(" -f file read operations from `file'\n"));
161 fprintf( stderr, _(" -F prefix URL prefix for files (default: %s)\n"), def_urlpre);
162 fprintf( stderr, _(" -l limit time limit (in seconds, or \"none\" or \"max\") for search\n"));
163 fprintf( stderr, _(" -L print responses in LDIFv1 format\n"));
164 fprintf( stderr, _(" -LL print responses in LDIF format without comments\n"));
165 fprintf( stderr, _(" -LLL print responses in LDIF format without comments\n"));
166 fprintf( stderr, _(" and version\n"));
167 fprintf( stderr, _(" -M enable Manage DSA IT control (-MM to make critical)\n"));
168 fprintf( stderr, _(" -P version protocol version (default: 3)\n"));
169 fprintf( stderr, _(" -s scope one of base, one, sub or children (search scope)\n"));
170 fprintf( stderr, _(" -S attr sort the results by attribute `attr'\n"));
171 fprintf( stderr, _(" -t write binary values to files in temporary directory\n"));
172 fprintf( stderr, _(" -tt write all values to files in temporary directory\n"));
173 fprintf( stderr, _(" -T path write files to directory specified by path (default: %s)\n"), def_tmpdir);
174 fprintf( stderr, _(" -u include User Friendly entry names in the output\n"));
175 fprintf( stderr, _(" -z limit size limit (in entries, or \"none\" or \"max\") for search\n"));
176 tool_common_usage();
177 exit( EXIT_FAILURE );
178 }
179
180 static void print_entry LDAP_P((
181 LDAP *ld,
182 LDAPMessage *entry,
183 int attrsonly));
184
185 static void print_reference(
186 LDAP *ld,
187 LDAPMessage *reference );
188
189 static void print_extended(
190 LDAP *ld,
191 LDAPMessage *extended );
192
193 static void print_syncinfo(
194 BerValue *info );
195
196 static void print_partial(
197 LDAP *ld,
198 LDAPMessage *partial );
199
200 static int print_result(
201 LDAP *ld,
202 LDAPMessage *result,
203 int search );
204
205 static int dosearch LDAP_P((
206 LDAP *ld,
207 char *base,
208 int scope,
209 char *filtpatt,
210 char *value,
211 char **attrs,
212 int attrsonly,
213 LDAPControl **sctrls,
214 LDAPControl **cctrls,
215 struct timeval *timeout,
216 int sizelimit ));
217
218 static char *tmpdir = NULL;
219 static char *urlpre = NULL;
220 static char *base = NULL;
221 static char *sortattr = NULL;
222 static int includeufn, vals2tmp = 0;
223
224 static int subentries = 0, valuesReturnFilter = 0;
225 static char *vrFilter = NULL;
226
227 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
228 static int accountUsability = 0;
229 #endif
230
231 #ifdef LDAP_CONTROL_DONTUSECOPY
232 static int dontUseCopy = 0;
233 #endif
234
235 static int domainScope = 0;
236
237 static int sss = 0;
238 static LDAPSortKey **sss_keys = NULL;
239
240 static int vlv = 0;
241 static LDAPVLVInfo vlvInfo;
242 static struct berval vlvValue;
243
244 static int ldapsync = 0;
245 static struct berval sync_cookie = { 0, NULL };
246 static int sync_slimit = -1;
247
248 static int psearch = 0;
249 static int ps_chgtypes, ps_chgsonly, ps_echg_ctrls;
250
251 /* cookie and morePagedResults moved to common.c */
252 static int pagedResults = 0;
253 static int pagePrompt = 1;
254 static ber_int_t pageSize = 0;
255 static ber_int_t entriesLeft = 0;
256 static int npagedresponses;
257 static int npagedentries;
258 static int npagedreferences;
259 static int npagedextended;
260 static int npagedpartial;
261
262 static LDAPControl *c = NULL;
263 static int nctrls = 0;
264 static int save_nctrls = 0;
265
266 #ifdef LDAP_CONTROL_X_DEREF
267 static int derefcrit;
268 static LDAPDerefSpec *ds;
269 static struct berval derefval;
270 #endif
271
272 #ifdef LDAP_CONTROL_X_DIRSYNC
273 static int dirSync;
274 static int dirSyncFlags;
275 static int dirSyncMaxAttrCount;
276 static struct berval dirSyncCookie;
277 #endif
278
279 #ifdef LDAP_CONTROL_X_EXTENDED_DN
280 static int extendedDn;
281 static int extendedDnFlag;
282 #endif
283
284 #ifdef LDAP_CONTROL_X_SHOW_DELETED
285 static int showDeleted;
286 #endif
287
288 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
289 static int serverNotif;
290 #endif
291
292 static int
ctrl_add(void)293 ctrl_add( void )
294 {
295 LDAPControl *tmpc;
296
297 nctrls++;
298 tmpc = realloc( c, sizeof( LDAPControl ) * nctrls );
299 if ( tmpc == NULL ) {
300 nctrls--;
301 fprintf( stderr,
302 _("unable to make room for control; out of memory?\n"));
303 return -1;
304 }
305 c = tmpc;
306
307 return 0;
308 }
309
310 static void
urlize(char * url)311 urlize(char *url)
312 {
313 char *p;
314
315 if (*LDAP_DIRSEP != '/') {
316 for (p = url; *p; p++) {
317 if (*p == *LDAP_DIRSEP)
318 *p = '/';
319 }
320 }
321 }
322
323 static int
parse_vlv(char * cvalue)324 parse_vlv(char *cvalue)
325 {
326 char *keyp, *key2;
327 int num1, num2;
328
329 keyp = cvalue;
330 if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
331 fprintf( stderr,
332 _("VLV control value \"%s\" invalid\n"),
333 cvalue );
334 return -1;
335 }
336 vlvInfo.ldvlv_before_count = num1;
337 vlvInfo.ldvlv_after_count = num2;
338 keyp = strchr( keyp, '/' ) + 1;
339 key2 = strchr( keyp, '/' );
340 if ( key2 ) {
341 keyp = key2 + 1;
342 if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
343 fprintf( stderr,
344 _("VLV control value \"%s\" invalid\n"),
345 cvalue );
346 return -1;
347 }
348 vlvInfo.ldvlv_offset = num1;
349 vlvInfo.ldvlv_count = num2;
350 vlvInfo.ldvlv_attrvalue = NULL;
351 } else {
352 key2 = strchr( keyp, ':' );
353 if ( !key2 ) {
354 fprintf( stderr,
355 _("VLV control value \"%s\" invalid\n"),
356 cvalue );
357 return -1;
358 }
359 ber_str2bv( key2+1, 0, 0, &vlvValue );
360 vlvInfo.ldvlv_attrvalue = &vlvValue;
361 }
362 return 0;
363 }
364
365 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
366 "Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
367
368 int
handle_private_option(int i)369 handle_private_option( int i )
370 {
371 int crit, ival;
372 char *cvalue, *next;
373 switch ( i ) {
374 case 'a': /* set alias deref option */
375 if ( strcasecmp( optarg, "never" ) == 0 ) {
376 deref = LDAP_DEREF_NEVER;
377 } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
378 deref = LDAP_DEREF_SEARCHING;
379 } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
380 deref = LDAP_DEREF_FINDING;
381 } else if ( strcasecmp( optarg, "always" ) == 0 ) {
382 deref = LDAP_DEREF_ALWAYS;
383 } else {
384 fprintf( stderr,
385 _("alias deref should be never, search, find, or always\n") );
386 usage();
387 }
388 break;
389 case 'A': /* retrieve attribute names only -- no values */
390 ++attrsonly;
391 break;
392 case 'b': /* search base */
393 base = optarg;
394 break;
395 case 'E': /* search extensions */
396 if( protocol == LDAP_VERSION2 ) {
397 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
398 prog, protocol );
399 exit( EXIT_FAILURE );
400 }
401
402 /* should be extended to support comma separated list of
403 * [!]key[=value] parameters, e.g. -E !foo,bar=567
404 */
405
406 crit = 0;
407 cvalue = NULL;
408 while ( optarg[0] == '!' ) {
409 crit++;
410 optarg++;
411 }
412
413 control = optarg;
414 if ( (cvalue = strchr( control, '=' )) != NULL ) {
415 *cvalue++ = '\0';
416 }
417
418 if ( strcasecmp( control, "mv" ) == 0 ) {
419 /* ValuesReturnFilter control */
420 if( valuesReturnFilter ) {
421 fprintf( stderr,
422 _("ValuesReturnFilter previously specified\n"));
423 exit( EXIT_FAILURE );
424 }
425 valuesReturnFilter= 1 + crit;
426
427 if ( cvalue == NULL ) {
428 fprintf( stderr,
429 _("missing filter in ValuesReturnFilter control\n"));
430 exit( EXIT_FAILURE );
431 }
432
433 vrFilter = cvalue;
434 protocol = LDAP_VERSION3;
435
436 } else if ( strcasecmp( control, "pr" ) == 0 ) {
437 int num, tmp;
438 /* PagedResults control */
439 if ( pagedResults != 0 ) {
440 fprintf( stderr,
441 _("PagedResultsControl previously specified\n") );
442 exit( EXIT_FAILURE );
443 }
444 if ( vlv != 0 ) {
445 fprintf( stderr,
446 _("PagedResultsControl incompatible with VLV\n") );
447 exit( EXIT_FAILURE );
448 }
449
450 if( cvalue != NULL ) {
451 char *promptp;
452
453 promptp = strchr( cvalue, '/' );
454 if ( promptp != NULL ) {
455 *promptp++ = '\0';
456 if ( strcasecmp( promptp, "prompt" ) == 0 ) {
457 pagePrompt = 1;
458 } else if ( strcasecmp( promptp, "noprompt" ) == 0) {
459 pagePrompt = 0;
460 } else {
461 fprintf( stderr,
462 _("Invalid value for PagedResultsControl,"
463 " %s/%s.\n"), cvalue, promptp );
464 exit( EXIT_FAILURE );
465 }
466 }
467 num = sscanf( cvalue, "%d", &tmp );
468 if ( num != 1 ) {
469 fprintf( stderr,
470 _("Invalid value for PagedResultsControl, %s.\n"),
471 cvalue );
472 exit( EXIT_FAILURE );
473 }
474 } else {
475 fprintf(stderr, _("Invalid value for PagedResultsControl.\n"));
476 exit( EXIT_FAILURE );
477 }
478 pageSize = (ber_int_t) tmp;
479 pagedResults = 1 + crit;
480
481 } else if ( strcasecmp( control, "ps" ) == 0 ) {
482 int num;
483 /* PersistentSearch control */
484 if ( psearch != 0 ) {
485 fprintf( stderr,
486 _("PersistentSearch previously specified\n") );
487 exit( EXIT_FAILURE );
488 }
489 if( cvalue != NULL ) {
490 num = sscanf( cvalue, "%i/%d/%d", &ps_chgtypes, &ps_chgsonly, &ps_echg_ctrls );
491 if ( num != 3 ) {
492 fprintf( stderr,
493 _("Invalid value for PersistentSearch, %s.\n"),
494 cvalue );
495 exit( EXIT_FAILURE );
496 }
497 } else {
498 fprintf(stderr, _("Invalid value for PersistentSearch.\n"));
499 exit( EXIT_FAILURE );
500 }
501 psearch = 1 + crit;
502
503 #ifdef LDAP_CONTROL_DONTUSECOPY
504 } else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
505 if( dontUseCopy ) {
506 fprintf( stderr,
507 _("dontUseCopy control previously specified\n"));
508 exit( EXIT_FAILURE );
509 }
510 if( cvalue != NULL ) {
511 fprintf( stderr,
512 _("dontUseCopy: no control value expected\n") );
513 usage();
514 }
515 if( !crit ) {
516 fprintf( stderr,
517 _("dontUseCopy: critical flag required\n") );
518 usage();
519 }
520
521 dontUseCopy = 1 + crit;
522 #endif
523 } else if ( strcasecmp( control, "domainScope" ) == 0 ) {
524 if( domainScope ) {
525 fprintf( stderr,
526 _("domainScope control previously specified\n"));
527 exit( EXIT_FAILURE );
528 }
529 if( cvalue != NULL ) {
530 fprintf( stderr,
531 _("domainScope: no control value expected\n") );
532 usage();
533 }
534
535 domainScope = 1 + crit;
536
537 } else if ( strcasecmp( control, "sss" ) == 0 ) {
538 char *keyp;
539 if( sss ) {
540 fprintf( stderr,
541 _("server side sorting control previously specified\n"));
542 exit( EXIT_FAILURE );
543 }
544 if( cvalue == NULL ) {
545 fprintf( stderr,
546 _("missing specification of sss control\n") );
547 exit( EXIT_FAILURE );
548 }
549 keyp = cvalue;
550 while ( ( keyp = strchr(keyp, '/') ) != NULL ) {
551 *keyp++ = ' ';
552 }
553 if ( ldap_create_sort_keylist( &sss_keys, cvalue )) {
554 fprintf( stderr,
555 _("server side sorting control value \"%s\" invalid\n"),
556 cvalue );
557 exit( EXIT_FAILURE );
558 }
559
560 sss = 1 + crit;
561
562 } else if ( strcasecmp( control, "subentries" ) == 0 ) {
563 if( subentries ) {
564 fprintf( stderr,
565 _("subentries control previously specified\n"));
566 exit( EXIT_FAILURE );
567 }
568 if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) {
569 subentries = 2;
570 } else if ( strcasecmp( cvalue, "false") == 0 ) {
571 subentries = 1;
572 } else {
573 fprintf( stderr,
574 _("subentries control value \"%s\" invalid\n"),
575 cvalue );
576 exit( EXIT_FAILURE );
577 }
578 if( crit ) subentries *= -1;
579
580 } else if ( strcasecmp( control, "sync" ) == 0 ) {
581 char *cookiep;
582 char *slimitp;
583 if ( ldapsync ) {
584 fprintf( stderr, _("sync control previously specified\n") );
585 exit( EXIT_FAILURE );
586 }
587 if ( cvalue == NULL ) {
588 fprintf( stderr, _("missing specification of sync control\n"));
589 exit( EXIT_FAILURE );
590 }
591 if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
592 ldapsync = LDAP_SYNC_REFRESH_ONLY;
593 cookiep = strchr( cvalue, '/' );
594 if ( cookiep != NULL ) {
595 cookiep++;
596 if ( *cookiep != '\0' ) {
597 ber_str2bv( cookiep, 0, 0, &sync_cookie );
598 }
599 }
600 } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
601 ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
602 cookiep = strchr( cvalue, '/' );
603 if ( cookiep != NULL ) {
604 *cookiep++ = '\0';
605 cvalue = cookiep;
606 }
607 slimitp = strchr( cvalue, '/' );
608 if ( slimitp != NULL ) {
609 *slimitp++ = '\0';
610 }
611 if ( cookiep != NULL && *cookiep != '\0' )
612 ber_str2bv( cookiep, 0, 0, &sync_cookie );
613 if ( slimitp != NULL && *slimitp != '\0' ) {
614 ival = strtol( slimitp, &next, 10 );
615 if ( next == NULL || next[0] != '\0' ) {
616 fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp );
617 exit( EXIT_FAILURE );
618 }
619 sync_slimit = ival;
620 }
621 } else {
622 fprintf( stderr, _("sync control value \"%s\" invalid\n"),
623 cvalue );
624 exit( EXIT_FAILURE );
625 }
626 if ( crit ) ldapsync *= -1;
627
628 } else if ( strcasecmp( control, "vlv" ) == 0 ) {
629 if( vlv ) {
630 fprintf( stderr,
631 _("virtual list view control previously specified\n"));
632 exit( EXIT_FAILURE );
633 }
634 if ( pagedResults != 0 ) {
635 fprintf( stderr,
636 _("PagedResultsControl incompatible with VLV\n") );
637 exit( EXIT_FAILURE );
638 }
639 if( cvalue == NULL ) {
640 fprintf( stderr,
641 _("missing specification of vlv control\n") );
642 exit( EXIT_FAILURE );
643 }
644 if ( parse_vlv( cvalue ))
645 exit( EXIT_FAILURE );
646
647 vlv = 1 + crit;
648
649 #ifdef LDAP_CONTROL_X_DEREF
650 } else if ( strcasecmp( control, "deref" ) == 0 ) {
651 int ispecs;
652 char **specs;
653
654 /* cvalue is something like
655 *
656 * derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]"
657 */
658
659 specs = ldap_str2charray( cvalue, ";" );
660 if ( specs == NULL ) {
661 fprintf( stderr, _("deref specs \"%s\" invalid\n"),
662 cvalue );
663 exit( EXIT_FAILURE );
664 }
665 for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
666 /* count'em */ ;
667
668 ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
669 if ( ds == NULL ) {
670 perror( "malloc" );
671 exit( EXIT_FAILURE );
672 }
673
674 for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
675 char *ptr;
676
677 ptr = strchr( specs[ ispecs ], ':' );
678 if ( ptr == NULL ) {
679 fprintf( stderr, _("deref specs \"%s\" invalid\n"),
680 cvalue );
681 exit( EXIT_FAILURE );
682 }
683
684 ds[ ispecs ].derefAttr = specs[ ispecs ];
685 *ptr++ = '\0';
686 ds[ ispecs ].attributes = ldap_str2charray( ptr, "," );
687 }
688
689 derefcrit = 1 + crit;
690
691 ldap_memfree( specs );
692 #endif /* LDAP_CONTROL_X_DEREF */
693
694 #ifdef LDAP_CONTROL_X_DIRSYNC
695 } else if ( strcasecmp( control, "dirSync" ) == 0 ) {
696 char *maxattrp;
697 char *cookiep;
698 int num, tmp;
699 if( dirSync ) {
700 fprintf( stderr,
701 _("dirSync control previously specified\n"));
702 exit( EXIT_FAILURE );
703 }
704 if ( cvalue == NULL ) {
705 fprintf( stderr, _("missing specification of dirSync control\n"));
706 exit( EXIT_FAILURE );
707 }
708 if( !crit ) {
709 fprintf( stderr,
710 _("dirSync: critical flag required\n") );
711 usage();
712 }
713 maxattrp = strchr( cvalue, '/' );
714 if ( maxattrp == NULL ) {
715 fprintf( stderr, _("dirSync control value \"%s\" invalid\n"),
716 cvalue );
717 exit( EXIT_FAILURE );
718 }
719 *maxattrp++ = '\0';
720 cookiep = strchr( maxattrp, '/' );
721 if ( cookiep != NULL ) {
722 if ( cookiep[1] != '\0' ) {
723 struct berval type;
724 int freeval;
725 char save1, save2;
726
727 /* dummy type "x"
728 * to use ldif_parse_line2() */
729 save1 = cookiep[ -1 ];
730 save2 = cookiep[ -2 ];
731 cookiep[ -2 ] = 'x';
732 cookiep[ -1 ] = ':';
733 cookiep[ 0 ] = ':';
734 ldif_parse_line2( &cookiep[ -2 ], &type,
735 &dirSyncCookie, &freeval );
736 cookiep[ -1 ] = save1;
737 cookiep[ -2 ] = save2;
738 }
739 *cookiep = '\0';
740 }
741 num = sscanf( cvalue, "%i", &tmp );
742 if ( num != 1 ) {
743 fprintf( stderr,
744 _("Invalid value for dirSync, %s.\n"),
745 cvalue );
746 exit( EXIT_FAILURE );
747 }
748 dirSyncFlags = tmp;
749
750 num = sscanf( maxattrp, "%d", &tmp );
751 if ( num != 1 ) {
752 fprintf( stderr,
753 _("Invalid value for dirSync, %s.\n"),
754 maxattrp );
755 exit( EXIT_FAILURE );
756 }
757 dirSyncMaxAttrCount = tmp;
758
759 dirSync = 1 + crit;
760 #endif /* LDAP_CONTROL_X_DIRSYNC */
761
762 #ifdef LDAP_CONTROL_X_EXTENDED_DN
763 } else if ( strcasecmp( control, "extendedDn" ) == 0 ) {
764 int num, tmp;
765 if( extendedDn ) {
766 fprintf( stderr,
767 _("extendedDn control previously specified\n"));
768 exit( EXIT_FAILURE );
769 }
770 if ( cvalue == NULL ) {
771 fprintf( stderr, _("missing specification of extendedDn control\n"));
772 exit( EXIT_FAILURE );
773 }
774 num = sscanf( cvalue, "%d", &tmp );
775 if ( num != 1 ) {
776 fprintf( stderr,
777 _("Invalid value for extendedDn, %s.\n"),
778 cvalue );
779 exit( EXIT_FAILURE );
780 }
781
782 extendedDnFlag = tmp;
783 extendedDn = 1 + crit;
784 #endif /* LDAP_CONTROL_X_EXTENDED_DN */
785
786 #ifdef LDAP_CONTROL_X_SHOW_DELETED
787 } else if ( strcasecmp( control, "showDeleted" ) == 0 ) {
788 if( showDeleted ) {
789 fprintf( stderr,
790 _("showDeleted control previously specified\n"));
791 exit( EXIT_FAILURE );
792 }
793 if ( cvalue != NULL ) {
794 fprintf( stderr,
795 _("showDeleted: no control value expected\n") );
796 usage();
797 }
798
799 showDeleted = 1 + crit;
800 #endif /* LDAP_CONTROL_X_SHOW_DELETED */
801
802 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
803 } else if ( strcasecmp( control, "serverNotif" ) == 0 ) {
804 if( serverNotif ) {
805 fprintf( stderr,
806 _("serverNotif control previously specified\n"));
807 exit( EXIT_FAILURE );
808 }
809 if ( cvalue != NULL ) {
810 fprintf( stderr,
811 _("serverNotif: no control value expected\n") );
812 usage();
813 }
814
815 serverNotif = 1 + crit;
816 #endif /* LDAP_CONTROL_X_SERVER_NOTIFICATION */
817
818 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
819 } else if ( strcasecmp( control, "accountUsability" ) == 0 ) {
820 if( accountUsability ) {
821 fprintf( stderr,
822 _("accountUsability control previously specified\n"));
823 exit( EXIT_FAILURE );
824 }
825 if( cvalue != NULL ) {
826 fprintf( stderr,
827 _("accountUsability: no control value expected\n") );
828 usage();
829 }
830
831 accountUsability = 1 + crit;
832 #endif /* LDAP_CONTROL_X_ACCOUNT_USABILITY */
833
834 } else if ( tool_is_oid( control ) ) {
835 if ( c != NULL ) {
836 int i;
837 for ( i = 0; i < nctrls; i++ ) {
838 if ( strcmp( control, c[ i ].ldctl_oid ) == 0 ) {
839 fprintf( stderr, "%s control previously specified\n", control );
840 exit( EXIT_FAILURE );
841 }
842 }
843 }
844
845 if ( ctrl_add() ) {
846 exit( EXIT_FAILURE );
847 }
848
849 /* OID */
850 c[ nctrls - 1 ].ldctl_oid = control;
851
852 /* value */
853 if ( cvalue == NULL ) {
854 c[ nctrls - 1 ].ldctl_value.bv_val = NULL;
855 c[ nctrls - 1 ].ldctl_value.bv_len = 0;
856
857 } else if ( cvalue[ 0 ] == ':' ) {
858 struct berval type;
859 struct berval value;
860 int freeval;
861 char save_c;
862
863 cvalue++;
864
865 /* dummy type "x"
866 * to use ldif_parse_line2() */
867 save_c = cvalue[ -2 ];
868 cvalue[ -2 ] = 'x';
869 ldif_parse_line2( &cvalue[ -2 ], &type,
870 &value, &freeval );
871 cvalue[ -2 ] = save_c;
872
873 if ( freeval ) {
874 c[ nctrls - 1 ].ldctl_value = value;
875
876 } else {
877 ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value );
878 }
879
880 } else {
881 fprintf( stderr, "unable to parse %s control value\n", control );
882 exit( EXIT_FAILURE );
883
884 }
885
886 /* criticality */
887 c[ nctrls - 1 ].ldctl_iscritical = crit;
888
889 } else {
890 fprintf( stderr, _("Invalid search extension name: %s\n"),
891 control );
892 usage();
893 }
894 break;
895 case 'F': /* uri prefix */
896 if( urlpre ) free( urlpre );
897 urlpre = optarg;
898 break;
899 case 'l': /* time limit */
900 if ( strcasecmp( optarg, "none" ) == 0 ) {
901 timelimit = 0;
902
903 } else if ( strcasecmp( optarg, "max" ) == 0 ) {
904 timelimit = LDAP_MAXINT;
905
906 } else {
907 ival = strtol( optarg, &next, 10 );
908 if ( next == NULL || next[0] != '\0' ) {
909 fprintf( stderr,
910 _("Unable to parse time limit \"%s\"\n"), optarg );
911 exit( EXIT_FAILURE );
912 }
913 timelimit = ival;
914 }
915 if( timelimit < 0 || timelimit > LDAP_MAXINT ) {
916 fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"),
917 prog, timelimit );
918 exit( EXIT_FAILURE );
919 }
920 break;
921 case 'L': /* print entries in LDIF format */
922 ++ldif;
923 break;
924 case 's': /* search scope */
925 if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) {
926 scope = LDAP_SCOPE_BASE;
927 } else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) {
928 scope = LDAP_SCOPE_ONELEVEL;
929 } else if (( strcasecmp( optarg, "subordinate" ) == 0 )
930 || ( strcasecmp( optarg, "children" ) == 0 ))
931 {
932 scope = LDAP_SCOPE_SUBORDINATE;
933 } else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) {
934 scope = LDAP_SCOPE_SUBTREE;
935 } else {
936 fprintf( stderr, _("scope should be base, one, or sub\n") );
937 usage();
938 }
939 break;
940 case 'S': /* sort attribute */
941 sortattr = optarg;
942 break;
943 case 't': /* write attribute values to TMPDIR files */
944 ++vals2tmp;
945 break;
946 case 'T': /* tmpdir */
947 if( tmpdir ) free( tmpdir );
948 tmpdir = optarg;
949 break;
950 case 'u': /* include UFN */
951 ++includeufn;
952 break;
953 case 'z': /* size limit */
954 if ( strcasecmp( optarg, "none" ) == 0 ) {
955 sizelimit = 0;
956
957 } else if ( strcasecmp( optarg, "max" ) == 0 ) {
958 sizelimit = LDAP_MAXINT;
959
960 } else {
961 ival = strtol( optarg, &next, 10 );
962 if ( next == NULL || next[0] != '\0' ) {
963 fprintf( stderr,
964 _("Unable to parse size limit \"%s\"\n"), optarg );
965 exit( EXIT_FAILURE );
966 }
967 sizelimit = ival;
968 }
969 if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) {
970 fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"),
971 prog, sizelimit );
972 exit( EXIT_FAILURE );
973 }
974 break;
975 default:
976 return 0;
977 }
978 return 1;
979 }
980
981
982 static void
private_conn_setup(LDAP * ld)983 private_conn_setup( LDAP *ld )
984 {
985 if (deref != -1 &&
986 ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref )
987 != LDAP_OPT_SUCCESS )
988 {
989 fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref );
990 tool_exit( ld, EXIT_FAILURE );
991 }
992 }
993
994 int
main(int argc,char ** argv)995 main( int argc, char **argv )
996 {
997 char *filtpattern, **attrs = NULL, line[BUFSIZ];
998 FILE *fp = NULL;
999 int rc, rc1, i, first;
1000 LDAP *ld = NULL;
1001 BerElement *seber = NULL, *vrber = NULL;
1002
1003 BerElement *syncber = NULL;
1004 struct berval *syncbvalp = NULL;
1005 int err;
1006
1007 tool_init( TOOL_SEARCH );
1008
1009 npagedresponses = npagedentries = npagedreferences =
1010 npagedextended = npagedpartial = 0;
1011
1012 prog = lutil_progname( "ldapsearch", argc, argv );
1013
1014 if((def_tmpdir = getenv("TMPDIR")) == NULL &&
1015 (def_tmpdir = getenv("TMP")) == NULL &&
1016 (def_tmpdir = getenv("TEMP")) == NULL )
1017 {
1018 def_tmpdir = LDAP_TMPDIR;
1019 }
1020
1021 if ( !*def_tmpdir )
1022 def_tmpdir = LDAP_TMPDIR;
1023
1024 def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
1025
1026 if( def_urlpre == NULL ) {
1027 perror( "malloc" );
1028 return EXIT_FAILURE;
1029 }
1030
1031 sprintf( def_urlpre, "file:///%s/",
1032 def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
1033
1034 urlize( def_urlpre );
1035
1036 tool_args( argc, argv );
1037
1038 if ( vlv && !sss ) {
1039 fprintf( stderr,
1040 _("VLV control requires server side sort control\n" ));
1041 return EXIT_FAILURE;
1042 }
1043
1044 if (( argc - optind < 1 ) ||
1045 ( *argv[optind] != '(' /*')'*/ &&
1046 ( strchr( argv[optind], '=' ) == NULL ) ) )
1047 {
1048 filtpattern = "(objectclass=*)";
1049 } else {
1050 filtpattern = argv[optind++];
1051 }
1052
1053 if ( argv[optind] != NULL ) {
1054 attrs = &argv[optind];
1055 }
1056
1057 if ( infile != NULL ) {
1058 int percent = 0;
1059
1060 if ( infile[0] == '-' && infile[1] == '\0' ) {
1061 fp = stdin;
1062 } else if (( fp = fopen( infile, "r" )) == NULL ) {
1063 perror( infile );
1064 return EXIT_FAILURE;
1065 }
1066
1067 for( i=0 ; filtpattern[i] ; i++ ) {
1068 if( filtpattern[i] == '%' ) {
1069 if( percent ) {
1070 fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
1071 filtpattern );
1072 return EXIT_FAILURE;
1073 }
1074
1075 percent++;
1076
1077 if( filtpattern[i+1] != 's' ) {
1078 fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
1079 filtpattern );
1080 return EXIT_FAILURE;
1081 }
1082 }
1083 }
1084 }
1085
1086 if ( tmpdir == NULL ) {
1087 tmpdir = def_tmpdir;
1088
1089 if ( urlpre == NULL )
1090 urlpre = def_urlpre;
1091 }
1092
1093 if( urlpre == NULL ) {
1094 urlpre = malloc( sizeof("file:////") + strlen(tmpdir) );
1095
1096 if( urlpre == NULL ) {
1097 perror( "malloc" );
1098 return EXIT_FAILURE;
1099 }
1100
1101 sprintf( urlpre, "file:///%s/",
1102 tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir );
1103
1104 urlize( urlpre );
1105 }
1106
1107 if ( debug )
1108 ldif_debug = debug;
1109
1110 ld = tool_conn_setup( 0, &private_conn_setup );
1111
1112 tool_bind( ld );
1113
1114 getNextPage:
1115 /* fp may have been closed, need to reopen if code jumps
1116 * back here to getNextPage.
1117 */
1118 if ( !fp && infile ) {
1119 if (( fp = fopen( infile, "r" )) == NULL ) {
1120 perror( infile );
1121 tool_exit( ld, EXIT_FAILURE );
1122 }
1123 }
1124 save_nctrls = nctrls;
1125 i = nctrls;
1126 if ( nctrls > 0
1127 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
1128 || accountUsability
1129 #endif
1130 #ifdef LDAP_CONTROL_DONTUSECOPY
1131 || dontUseCopy
1132 #endif
1133 #ifdef LDAP_CONTROL_X_DEREF
1134 || derefcrit
1135 #endif
1136 #ifdef LDAP_CONTROL_X_DIRSYNC
1137 || dirSync
1138 #endif
1139 #ifdef LDAP_CONTROL_X_EXTENDED_DN
1140 || extendedDn
1141 #endif
1142 #ifdef LDAP_CONTROL_X_SHOW_DELETED
1143 || showDeleted
1144 #endif
1145 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
1146 || serverNotif
1147 #endif
1148 || domainScope
1149 || pagedResults
1150 || psearch
1151 || ldapsync
1152 || sss
1153 || subentries
1154 || valuesReturnFilter
1155 || vlv )
1156 {
1157
1158 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
1159 if ( accountUsability ) {
1160 if ( ctrl_add() ) {
1161 tool_exit( ld, EXIT_FAILURE );
1162 }
1163
1164 c[i].ldctl_oid = LDAP_CONTROL_X_ACCOUNT_USABILITY;
1165 c[i].ldctl_value.bv_val = NULL;
1166 c[i].ldctl_value.bv_len = 0;
1167 c[i].ldctl_iscritical = accountUsability == 2;
1168 i++;
1169 }
1170 #endif
1171
1172 #ifdef LDAP_CONTROL_DONTUSECOPY
1173 if ( dontUseCopy ) {
1174 if ( ctrl_add() ) {
1175 tool_exit( ld, EXIT_FAILURE );
1176 }
1177
1178 c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
1179 c[i].ldctl_value.bv_val = NULL;
1180 c[i].ldctl_value.bv_len = 0;
1181 c[i].ldctl_iscritical = dontUseCopy == 2;
1182 i++;
1183 }
1184 #endif
1185
1186 if ( domainScope ) {
1187 if ( ctrl_add() ) {
1188 tool_exit( ld, EXIT_FAILURE );
1189 }
1190
1191 c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
1192 c[i].ldctl_value.bv_val = NULL;
1193 c[i].ldctl_value.bv_len = 0;
1194 c[i].ldctl_iscritical = domainScope > 1;
1195 i++;
1196 }
1197
1198 if ( subentries ) {
1199 if ( ctrl_add() ) {
1200 tool_exit( ld, EXIT_FAILURE );
1201 }
1202
1203 if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
1204 tool_exit( ld, EXIT_FAILURE );
1205 }
1206
1207 err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
1208 if ( err == -1 ) {
1209 ber_free( seber, 1 );
1210 fprintf( stderr, _("Subentries control encoding error!\n") );
1211 tool_exit( ld, EXIT_FAILURE );
1212 }
1213
1214 if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) {
1215 tool_exit( ld, EXIT_FAILURE );
1216 }
1217
1218 c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES;
1219 c[i].ldctl_iscritical = subentries < 1;
1220 i++;
1221 }
1222
1223 if ( ldapsync ) {
1224 if ( ctrl_add() ) {
1225 tool_exit( ld, EXIT_FAILURE );
1226 }
1227
1228 if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
1229 tool_exit( ld, EXIT_FAILURE );
1230 }
1231
1232 if ( sync_cookie.bv_len == 0 ) {
1233 err = ber_printf( syncber, "{e}", abs(ldapsync) );
1234 } else {
1235 err = ber_printf( syncber, "{eO}", abs(ldapsync),
1236 &sync_cookie );
1237 }
1238
1239 if ( err == -1 ) {
1240 ber_free( syncber, 1 );
1241 fprintf( stderr, _("ldap sync control encoding error!\n") );
1242 tool_exit( ld, EXIT_FAILURE );
1243 }
1244
1245 if ( ber_flatten( syncber, &syncbvalp ) == -1 ) {
1246 tool_exit( ld, EXIT_FAILURE );
1247 }
1248
1249 c[i].ldctl_oid = LDAP_CONTROL_SYNC;
1250 c[i].ldctl_value = (*syncbvalp);
1251 c[i].ldctl_iscritical = ldapsync < 0;
1252 i++;
1253 }
1254
1255 if ( valuesReturnFilter ) {
1256 if ( ctrl_add() ) {
1257 tool_exit( ld, EXIT_FAILURE );
1258 }
1259
1260 if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
1261 tool_exit( ld, EXIT_FAILURE );
1262 }
1263
1264 if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) {
1265 ber_free( vrber, 1 );
1266 fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter );
1267 tool_exit( ld, EXIT_FAILURE );
1268 }
1269
1270 if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) {
1271 tool_exit( ld, EXIT_FAILURE );
1272 }
1273
1274 c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
1275 c[i].ldctl_iscritical = valuesReturnFilter > 1;
1276 i++;
1277 }
1278
1279 if ( pagedResults ) {
1280 if ( ctrl_add() ) {
1281 tool_exit( ld, EXIT_FAILURE );
1282 }
1283
1284 if ( ldap_create_page_control_value( ld,
1285 pageSize, &pr_cookie, &c[i].ldctl_value ) )
1286 {
1287 tool_exit( ld, EXIT_FAILURE );
1288 }
1289
1290 if ( pr_cookie.bv_val != NULL ) {
1291 ber_memfree( pr_cookie.bv_val );
1292 pr_cookie.bv_val = NULL;
1293 pr_cookie.bv_len = 0;
1294 }
1295
1296 c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
1297 c[i].ldctl_iscritical = pagedResults > 1;
1298 i++;
1299 }
1300
1301 if ( psearch ) {
1302 if ( ctrl_add() ) {
1303 tool_exit( ld, EXIT_FAILURE );
1304 }
1305
1306 if ( ldap_create_persistentsearch_control_value( ld,
1307 ps_chgtypes, ps_chgsonly, ps_echg_ctrls, &c[i].ldctl_value ) )
1308 {
1309 tool_exit( ld, EXIT_FAILURE );
1310 }
1311
1312 c[i].ldctl_oid = LDAP_CONTROL_PERSIST_REQUEST;
1313 c[i].ldctl_iscritical = psearch > 1;
1314 i++;
1315 }
1316
1317 if ( sss ) {
1318 if ( ctrl_add() ) {
1319 tool_exit( ld, EXIT_FAILURE );
1320 }
1321
1322 if ( ldap_create_sort_control_value( ld,
1323 sss_keys, &c[i].ldctl_value ) )
1324 {
1325 tool_exit( ld, EXIT_FAILURE );
1326 }
1327
1328 c[i].ldctl_oid = LDAP_CONTROL_SORTREQUEST;
1329 c[i].ldctl_iscritical = sss > 1;
1330 i++;
1331 }
1332
1333 if ( vlv ) {
1334 if ( ctrl_add() ) {
1335 tool_exit( ld, EXIT_FAILURE );
1336 }
1337
1338 if ( ldap_create_vlv_control_value( ld,
1339 &vlvInfo, &c[i].ldctl_value ) )
1340 {
1341 tool_exit( ld, EXIT_FAILURE );
1342 }
1343
1344 c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
1345 c[i].ldctl_iscritical = vlv > 1;
1346 i++;
1347 }
1348 #ifdef LDAP_CONTROL_X_DEREF
1349 if ( derefcrit ) {
1350 if ( derefval.bv_val == NULL ) {
1351 int i;
1352
1353 assert( ds != NULL );
1354
1355 if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
1356 tool_exit( ld, EXIT_FAILURE );
1357 }
1358
1359 for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) {
1360 ldap_memfree( ds[ i ].derefAttr );
1361 ldap_charray_free( ds[ i ].attributes );
1362 }
1363 ldap_memfree( ds );
1364 ds = NULL;
1365 }
1366
1367 if ( ctrl_add() ) {
1368 tool_exit( ld, EXIT_FAILURE );
1369 }
1370
1371 c[ i ].ldctl_iscritical = derefcrit > 1;
1372 c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF;
1373 c[ i ].ldctl_value = derefval;
1374 i++;
1375 }
1376 #endif /* LDAP_CONTROL_X_DEREF */
1377 #ifdef LDAP_CONTROL_X_DIRSYNC
1378 if ( dirSync ) {
1379 if ( ctrl_add() ) {
1380 tool_exit( ld, EXIT_FAILURE );
1381 }
1382
1383 if ( ldap_create_dirsync_value( ld,
1384 dirSyncFlags, dirSyncMaxAttrCount, &dirSyncCookie,
1385 &c[i].ldctl_value ) )
1386 {
1387 tool_exit( ld, EXIT_FAILURE );
1388 }
1389
1390 c[i].ldctl_oid = LDAP_CONTROL_X_DIRSYNC;
1391 c[i].ldctl_iscritical = dirSync > 1;
1392 i++;
1393 }
1394 #endif
1395 #ifdef LDAP_CONTROL_X_EXTENDED_DN
1396 if ( extendedDn ) {
1397 if ( ctrl_add() ) {
1398 tool_exit( ld, EXIT_FAILURE );
1399 }
1400
1401 if ( ldap_create_extended_dn_value( ld,
1402 extendedDnFlag, &c[i].ldctl_value ) )
1403 {
1404 tool_exit( ld, EXIT_FAILURE );
1405 }
1406
1407 c[i].ldctl_oid = LDAP_CONTROL_X_EXTENDED_DN;
1408 c[i].ldctl_iscritical = extendedDn > 1;
1409 i++;
1410 }
1411 #endif
1412 #ifdef LDAP_CONTROL_X_SHOW_DELETED
1413 if ( showDeleted ) {
1414 if ( ctrl_add() ) {
1415 tool_exit( ld, EXIT_FAILURE );
1416 }
1417
1418 c[i].ldctl_oid = LDAP_CONTROL_X_SHOW_DELETED;
1419 c[i].ldctl_value.bv_val = NULL;
1420 c[i].ldctl_value.bv_len = 0;
1421 c[i].ldctl_iscritical = showDeleted > 1;
1422 i++;
1423 }
1424 #endif
1425 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
1426 if ( serverNotif ) {
1427 if ( ctrl_add() ) {
1428 tool_exit( ld, EXIT_FAILURE );
1429 }
1430
1431 c[i].ldctl_oid = LDAP_CONTROL_X_SERVER_NOTIFICATION;
1432 c[i].ldctl_value.bv_val = NULL;
1433 c[i].ldctl_value.bv_len = 0;
1434 c[i].ldctl_iscritical = serverNotif > 1;
1435 i++;
1436 }
1437 #endif
1438 }
1439
1440 tool_server_controls( ld, c, i );
1441
1442 if ( seber ) ber_free( seber, 1 );
1443 if ( vrber ) ber_free( vrber, 1 );
1444
1445 /* step back to the original number of controls, so that
1446 * those set while parsing args are preserved */
1447 nctrls = save_nctrls;
1448
1449 if ( verbose ) {
1450 fprintf( stderr, _("filter%s: %s\nrequesting: "),
1451 infile != NULL ? _(" pattern") : "",
1452 filtpattern );
1453
1454 if ( attrs == NULL ) {
1455 fprintf( stderr, _("All userApplication attributes") );
1456 } else {
1457 for ( i = 0; attrs[ i ] != NULL; ++i ) {
1458 fprintf( stderr, "%s ", attrs[ i ] );
1459 }
1460 }
1461 fprintf( stderr, "\n" );
1462 }
1463
1464 if ( ldif == 0 ) {
1465 printf( _("# extended LDIF\n") );
1466 } else if ( ldif < 3 ) {
1467 printf( _("version: %d\n\n"), 1 );
1468 }
1469
1470 if (ldif < 2 ) {
1471 char *realbase = base;
1472
1473 if ( realbase == NULL ) {
1474 ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase );
1475 }
1476
1477 printf( "#\n" );
1478 printf(_("# LDAPv%d\n"), protocol);
1479 printf(_("# base <%s>%s with scope %s\n"),
1480 realbase ? realbase : "",
1481 ( realbase == NULL || realbase != base ) ? " (default)" : "",
1482 ((scope == LDAP_SCOPE_BASE) ? "baseObject"
1483 : ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
1484 : ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
1485 : "subtree" ))));
1486 printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "",
1487 filtpattern);
1488 printf(_("# requesting: "));
1489
1490 if ( attrs == NULL ) {
1491 printf( _("ALL") );
1492 } else {
1493 for ( i = 0; attrs[ i ] != NULL; ++i ) {
1494 printf( "%s ", attrs[ i ] );
1495 }
1496 }
1497
1498 if ( manageDSAit ) {
1499 printf(_("\n# with manageDSAit %scontrol"),
1500 manageDSAit > 1 ? _("critical ") : "" );
1501 }
1502 if ( noop ) {
1503 printf(_("\n# with noop %scontrol"),
1504 noop > 1 ? _("critical ") : "" );
1505 }
1506 if ( subentries ) {
1507 printf(_("\n# with subentries %scontrol: %s"),
1508 subentries < 0 ? _("critical ") : "",
1509 abs(subentries) == 1 ? "false" : "true" );
1510 }
1511 if ( valuesReturnFilter ) {
1512 printf(_("\n# with valuesReturnFilter %scontrol: %s"),
1513 valuesReturnFilter > 1 ? _("critical ") : "", vrFilter );
1514 }
1515 if ( pagedResults ) {
1516 printf(_("\n# with pagedResults %scontrol: size=%d"),
1517 (pagedResults > 1) ? _("critical ") : "",
1518 pageSize );
1519 }
1520 if ( sss ) {
1521 printf(_("\n# with server side sorting %scontrol"),
1522 sss > 1 ? _("critical ") : "" );
1523 }
1524 if ( vlv ) {
1525 printf(_("\n# with virtual list view %scontrol: %d/%d"),
1526 vlv > 1 ? _("critical ") : "",
1527 vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count);
1528 if ( vlvInfo.ldvlv_attrvalue )
1529 printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val );
1530 else
1531 printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count );
1532 }
1533 #ifdef LDAP_CONTROL_X_DEREF
1534 if ( derefcrit ) {
1535 printf(_("\n# with dereference %scontrol"),
1536 derefcrit > 1 ? _("critical ") : "" );
1537 }
1538 #endif
1539
1540 printf( _("\n#\n\n") );
1541
1542 if ( realbase && realbase != base ) {
1543 ldap_memfree( realbase );
1544 }
1545 }
1546
1547 if ( infile == NULL ) {
1548 rc = dosearch( ld, base, scope, NULL, filtpattern,
1549 attrs, attrsonly, NULL, NULL, NULL, sizelimit );
1550
1551 } else {
1552 rc = 0;
1553 first = 1;
1554 while ( fgets( line, sizeof( line ), fp ) != NULL ) {
1555 line[ strlen( line ) - 1 ] = '\0';
1556 if ( !first ) {
1557 putchar( '\n' );
1558 } else {
1559 first = 0;
1560 }
1561 rc1 = dosearch( ld, base, scope, filtpattern, line,
1562 attrs, attrsonly, NULL, NULL, NULL, sizelimit );
1563
1564 if ( rc1 != 0 ) {
1565 rc = rc1;
1566 if ( !contoper )
1567 break;
1568 }
1569 }
1570 if ( fp != stdin ) {
1571 fclose( fp );
1572 fp = NULL;
1573 }
1574 }
1575
1576 if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) {
1577 char buf[12];
1578 int i, moreEntries, tmpSize;
1579
1580 /* Loop to get the next pages when
1581 * enter is pressed on the terminal.
1582 */
1583 if ( pagePrompt != 0 ) {
1584 if ( entriesLeft > 0 ) {
1585 printf( _("Estimate entries: %d\n"), entriesLeft );
1586 }
1587 printf( _("Press [size] Enter for the next {%d|size} entries.\n"),
1588 (int)pageSize );
1589 i = 0;
1590 moreEntries = getchar();
1591 while ( moreEntries != EOF && moreEntries != '\n' ) {
1592 if ( i < (int)sizeof(buf) - 1 ) {
1593 buf[i] = moreEntries;
1594 i++;
1595 }
1596 moreEntries = getchar();
1597 }
1598 buf[i] = '\0';
1599
1600 if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) {
1601 int num = sscanf( buf, "%d", &tmpSize );
1602 if ( num != 1 ) {
1603 fprintf( stderr,
1604 _("Invalid value for PagedResultsControl, %s.\n"), buf);
1605 tool_exit( ld, EXIT_FAILURE );
1606
1607 }
1608 pageSize = (ber_int_t)tmpSize;
1609 }
1610 }
1611
1612 goto getNextPage;
1613 }
1614
1615 if (( rc == LDAP_SUCCESS ) && vlv ) {
1616 char buf[BUFSIZ];
1617 int i, moreEntries;
1618
1619 /* Loop to get the next window when
1620 * enter is pressed on the terminal.
1621 */
1622 printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n"));
1623 i = 0;
1624 moreEntries = getchar();
1625 while ( moreEntries != EOF && moreEntries != '\n' ) {
1626 if ( i < (int)sizeof(buf) - 1 ) {
1627 buf[i] = moreEntries;
1628 i++;
1629 }
1630 moreEntries = getchar();
1631 }
1632 buf[i] = '\0';
1633 if ( buf[0] ) {
1634 i = parse_vlv( strdup( buf ));
1635 if ( i )
1636 tool_exit( ld, EXIT_FAILURE );
1637 } else {
1638 vlvInfo.ldvlv_attrvalue = NULL;
1639 vlvInfo.ldvlv_count = vlvCount;
1640 vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count;
1641 }
1642
1643 if ( vlvInfo.ldvlv_context )
1644 ber_bvfree( vlvInfo.ldvlv_context );
1645 vlvInfo.ldvlv_context = vlvContext;
1646
1647 goto getNextPage;
1648 }
1649
1650 if ( sss_keys != NULL ) {
1651 ldap_free_sort_keylist( sss_keys );
1652 }
1653 if ( derefval.bv_val != NULL ) {
1654 ldap_memfree( derefval.bv_val );
1655 }
1656 if ( urlpre != NULL ) {
1657 if ( def_urlpre != urlpre )
1658 free( def_urlpre );
1659 free( urlpre );
1660 }
1661
1662 if ( c ) {
1663 for ( ; save_nctrls-- > 0; ) {
1664 ber_memfree( c[ save_nctrls ].ldctl_value.bv_val );
1665 }
1666 free( c );
1667 c = NULL;
1668 }
1669
1670 tool_exit( ld, rc );
1671 }
1672
1673
dosearch(LDAP * ld,char * base,int scope,char * filtpatt,char * value,char ** attrs,int attrsonly,LDAPControl ** sctrls,LDAPControl ** cctrls,struct timeval * timeout,int sizelimit)1674 static int dosearch(
1675 LDAP *ld,
1676 char *base,
1677 int scope,
1678 char *filtpatt,
1679 char *value,
1680 char **attrs,
1681 int attrsonly,
1682 LDAPControl **sctrls,
1683 LDAPControl **cctrls,
1684 struct timeval *timeout,
1685 int sizelimit )
1686 {
1687 char *filter;
1688 int rc, rc2 = LDAP_OTHER;
1689 int nresponses;
1690 int nentries;
1691 int nreferences;
1692 int nextended;
1693 int npartial;
1694 LDAPMessage *res, *msg;
1695 ber_int_t msgid;
1696 char *retoid = NULL;
1697 struct berval *retdata = NULL;
1698 int nresponses_psearch = -1;
1699 int cancel_msgid = -1;
1700 struct timeval tv, *tvp = NULL;
1701 struct timeval tv_timelimit, *tv_timelimitp = NULL;
1702
1703 if( filtpatt != NULL ) {
1704 size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1, outlen;
1705 filter = malloc( max_fsize );
1706 if( filter == NULL ) {
1707 perror( "malloc" );
1708 return EXIT_FAILURE;
1709 }
1710
1711 outlen = snprintf( filter, max_fsize, filtpatt, value );
1712 if( outlen >= max_fsize ) {
1713 fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt );
1714 free( filter );
1715 return EXIT_FAILURE;
1716 }
1717
1718 if ( verbose ) {
1719 fprintf( stderr, _("filter: %s\n"), filter );
1720 }
1721
1722 if( ldif < 2 ) {
1723 printf( _("#\n# filter: %s\n#\n"), filter );
1724 }
1725
1726 } else {
1727 filter = value;
1728 }
1729
1730 if ( dont ) {
1731 if ( filtpatt != NULL ) {
1732 free( filter );
1733 }
1734 return LDAP_SUCCESS;
1735 }
1736
1737 if ( timelimit > 0 ) {
1738 tv_timelimit.tv_sec = timelimit;
1739 tv_timelimit.tv_usec = 0;
1740 tv_timelimitp = &tv_timelimit;
1741 }
1742
1743 again:
1744 rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
1745 sctrls, cctrls, tv_timelimitp, sizelimit, &msgid );
1746
1747 if ( filtpatt != NULL ) {
1748 free( filter );
1749 }
1750
1751 if( rc != LDAP_SUCCESS ) {
1752 tool_perror( "ldap_search_ext", rc, NULL, NULL, NULL, NULL );
1753 return( rc );
1754 }
1755
1756 nresponses = nentries = nreferences = nextended = npartial = 0;
1757
1758 res = NULL;
1759
1760 if ( timelimit > 0 ) {
1761 /* disable timeout */
1762 tv.tv_sec = -1;
1763 tv.tv_usec = 0;
1764 tvp = &tv;
1765 }
1766
1767 if ( backlog == 1 ) {
1768 printf( _("\nWaiting for responses to accumulate, press Enter to continue: "));
1769 fflush( stdout );
1770 getchar();
1771 printf( _("Abandoning msgid %d\n"), msgid );
1772 ldap_abandon_ext( ld, msgid, NULL, NULL );
1773 /* turn off syncrepl control */
1774 ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
1775 backlog = 2;
1776 scope = LDAP_SCOPE_BASE;
1777 goto again;
1778 } else if ( backlog == 2 ) {
1779 tv.tv_sec = timelimit;
1780 }
1781
1782 while ((rc = ldap_result( ld, LDAP_RES_ANY,
1783 sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE,
1784 tvp, &res )) > 0 )
1785 {
1786 if ( tool_check_abandon( ld, msgid ) ) {
1787 return -1;
1788 }
1789
1790 if( sortattr ) {
1791 (void) ldap_sort_entries( ld, &res,
1792 ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
1793 }
1794
1795 for ( msg = ldap_first_message( ld, res );
1796 msg != NULL;
1797 msg = ldap_next_message( ld, msg ) )
1798 {
1799 if ( nresponses++ ) putchar('\n');
1800 if ( nresponses_psearch >= 0 )
1801 nresponses_psearch++;
1802
1803 switch( ldap_msgtype( msg ) ) {
1804 case LDAP_RES_SEARCH_ENTRY:
1805 nentries++;
1806 print_entry( ld, msg, attrsonly );
1807 break;
1808
1809 case LDAP_RES_SEARCH_REFERENCE:
1810 nreferences++;
1811 print_reference( ld, msg );
1812 break;
1813
1814 case LDAP_RES_EXTENDED:
1815 nextended++;
1816 print_extended( ld, msg );
1817
1818 if ( ldap_msgid( msg ) == 0 ) {
1819 /* unsolicited extended operation */
1820 goto done;
1821 }
1822
1823 if ( cancel_msgid != -1 &&
1824 cancel_msgid == ldap_msgid( msg ) ) {
1825 printf(_("Cancelled \n"));
1826 printf(_("cancel_msgid = %d\n"), cancel_msgid);
1827 goto done;
1828 }
1829 break;
1830
1831 case LDAP_RES_SEARCH_RESULT:
1832 /* pagedResults stuff is dealt with
1833 * in tool_print_ctrls(), called by
1834 * print_results(). */
1835 rc2 = print_result( ld, msg, 1 );
1836 if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
1837 break;
1838 }
1839
1840 goto done;
1841
1842 case LDAP_RES_INTERMEDIATE:
1843 npartial++;
1844 ldap_parse_intermediate( ld, msg,
1845 &retoid, &retdata, NULL, 0 );
1846
1847 nresponses_psearch = 0;
1848
1849 if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) {
1850 if ( ldif < 1 ) {
1851 print_syncinfo( retdata );
1852 } else if ( ldif < 2 ) {
1853 printf(_("# SyncInfo Received\n"));
1854 }
1855 ldap_memfree( retoid );
1856 ber_bvfree( retdata );
1857 break;
1858 }
1859
1860 print_partial( ld, msg );
1861 ldap_memfree( retoid );
1862 ber_bvfree( retdata );
1863 goto done;
1864 }
1865
1866 if ( ldapsync && sync_slimit != -1 &&
1867 nresponses_psearch >= sync_slimit ) {
1868 BerElement *msgidber = NULL;
1869 struct berval *msgidvalp = NULL;
1870 msgidber = ber_alloc_t(LBER_USE_DER);
1871 ber_printf(msgidber, "{i}", msgid);
1872 ber_flatten(msgidber, &msgidvalp);
1873 ldap_extended_operation(ld, LDAP_EXOP_CANCEL,
1874 msgidvalp, NULL, NULL, &cancel_msgid);
1875 nresponses_psearch = -1;
1876 }
1877 }
1878
1879 ldap_msgfree( res );
1880 fflush( stdout );
1881 }
1882
1883 done:
1884 if ( tvp == NULL && rc != LDAP_RES_SEARCH_RESULT ) {
1885 ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&rc2 );
1886 }
1887
1888 ldap_msgfree( res );
1889
1890 if ( pagedResults ) {
1891 npagedresponses += nresponses;
1892 npagedentries += nentries;
1893 npagedextended += nextended;
1894 npagedpartial += npartial;
1895 npagedreferences += nreferences;
1896 if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) {
1897 printf( _("\n# numResponses: %d\n"), npagedresponses );
1898 if( npagedentries ) {
1899 printf( _("# numEntries: %d\n"), npagedentries );
1900 }
1901 if( npagedextended ) {
1902 printf( _("# numExtended: %d\n"), npagedextended );
1903 }
1904 if( npagedpartial ) {
1905 printf( _("# numPartial: %d\n"), npagedpartial );
1906 }
1907 if( npagedreferences ) {
1908 printf( _("# numReferences: %d\n"), npagedreferences );
1909 }
1910 }
1911 } else if ( ldif < 2 ) {
1912 printf( _("\n# numResponses: %d\n"), nresponses );
1913 if( nentries ) printf( _("# numEntries: %d\n"), nentries );
1914 if( nextended ) printf( _("# numExtended: %d\n"), nextended );
1915 if( npartial ) printf( _("# numPartial: %d\n"), npartial );
1916 if( nreferences ) printf( _("# numReferences: %d\n"), nreferences );
1917 }
1918
1919 if ( rc != LDAP_RES_SEARCH_RESULT ) {
1920 tool_perror( "ldap_result", rc2, NULL, NULL, NULL, NULL );
1921 }
1922
1923 return( rc2 );
1924 }
1925
1926 /* This is the proposed new way of doing things.
1927 * It is more efficient, but the API is non-standard.
1928 */
1929 static void
print_entry(LDAP * ld,LDAPMessage * entry,int attrsonly)1930 print_entry(
1931 LDAP *ld,
1932 LDAPMessage *entry,
1933 int attrsonly)
1934 {
1935 char *ufn = NULL;
1936 char tmpfname[ 256 ];
1937 char url[ 256 ];
1938 int i, rc;
1939 BerElement *ber = NULL;
1940 struct berval bv, *bvals, **bvp = &bvals;
1941 LDAPControl **ctrls = NULL;
1942 FILE *tmpfp;
1943
1944 rc = ldap_get_dn_ber( ld, entry, &ber, &bv );
1945
1946 if ( ldif < 2 ) {
1947 ufn = ldap_dn2ufn( bv.bv_val );
1948 tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 );
1949 }
1950 tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
1951
1952 rc = ldap_get_entry_controls( ld, entry, &ctrls );
1953 if( rc != LDAP_SUCCESS ) {
1954 fprintf(stderr, _("print_entry: %d\n"), rc );
1955 tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL );
1956 tool_exit( ld, EXIT_FAILURE );
1957 }
1958
1959 if( ctrls ) {
1960 tool_print_ctrls( ld, ctrls );
1961 ldap_controls_free( ctrls );
1962 }
1963
1964 if ( includeufn ) {
1965 if( ufn == NULL ) {
1966 ufn = ldap_dn2ufn( bv.bv_val );
1967 }
1968 tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 );
1969 }
1970
1971 if( ufn != NULL ) ldap_memfree( ufn );
1972
1973 if ( attrsonly ) bvp = NULL;
1974
1975 for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp );
1976 rc == LDAP_SUCCESS;
1977 rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) )
1978 {
1979 if (bv.bv_val == NULL) break;
1980
1981 if ( attrsonly ) {
1982 tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 );
1983
1984 } else if ( bvals ) {
1985 for ( i = 0; bvals[i].bv_val != NULL; i++ ) {
1986 if ( vals2tmp > 1 || ( vals2tmp &&
1987 ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len )))
1988 {
1989 int tmpfd;
1990 /* write value to file */
1991 snprintf( tmpfname, sizeof tmpfname,
1992 "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
1993 tmpdir, bv.bv_val );
1994 tmpfp = NULL;
1995
1996 tmpfd = mkstemp( tmpfname );
1997
1998 if ( tmpfd < 0 ) {
1999 perror( tmpfname );
2000 continue;
2001 }
2002
2003 if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) {
2004 perror( tmpfname );
2005 continue;
2006 }
2007
2008 if ( fwrite( bvals[ i ].bv_val,
2009 bvals[ i ].bv_len, 1, tmpfp ) == 0 )
2010 {
2011 perror( tmpfname );
2012 fclose( tmpfp );
2013 continue;
2014 }
2015
2016 fclose( tmpfp );
2017
2018 snprintf( url, sizeof url, "%s%s", urlpre,
2019 &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
2020
2021 urlize( url );
2022 tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url ));
2023
2024 } else {
2025 tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val,
2026 bvals[ i ].bv_val, bvals[ i ].bv_len );
2027 }
2028 }
2029 ber_memfree( bvals );
2030 }
2031 }
2032
2033 if( ber != NULL ) {
2034 ber_free( ber, 0 );
2035 }
2036 }
2037
print_reference(LDAP * ld,LDAPMessage * reference)2038 static void print_reference(
2039 LDAP *ld,
2040 LDAPMessage *reference )
2041 {
2042 int rc;
2043 char **refs = NULL;
2044 LDAPControl **ctrls;
2045
2046 if( ldif < 2 ) {
2047 printf(_("# search reference\n"));
2048 }
2049
2050 rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 );
2051
2052 if( rc != LDAP_SUCCESS ) {
2053 tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL );
2054 tool_exit( ld, EXIT_FAILURE );
2055 }
2056
2057 if( refs ) {
2058 int i;
2059 for( i=0; refs[i] != NULL; i++ ) {
2060 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2061 "ref", refs[i], strlen(refs[i]) );
2062 }
2063 ber_memvfree( (void **) refs );
2064 }
2065
2066 if( ctrls ) {
2067 tool_print_ctrls( ld, ctrls );
2068 ldap_controls_free( ctrls );
2069 }
2070 }
2071
print_extended(LDAP * ld,LDAPMessage * extended)2072 static void print_extended(
2073 LDAP *ld,
2074 LDAPMessage *extended )
2075 {
2076 int rc;
2077 char *retoid = NULL;
2078 struct berval *retdata = NULL;
2079
2080 if( ldif < 2 ) {
2081 printf(_("# extended result response\n"));
2082 }
2083
2084 rc = ldap_parse_extended_result( ld, extended,
2085 &retoid, &retdata, 0 );
2086
2087 if( rc != LDAP_SUCCESS ) {
2088 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
2089 tool_exit( ld, EXIT_FAILURE );
2090 }
2091
2092 if ( ldif < 2 ) {
2093 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2094 "extended", retoid, retoid ? strlen(retoid) : 0 );
2095 }
2096 ber_memfree( retoid );
2097
2098 if(retdata) {
2099 if ( ldif < 2 ) {
2100 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
2101 "data", retdata->bv_val, retdata->bv_len );
2102 }
2103 ber_bvfree( retdata );
2104 }
2105
2106 print_result( ld, extended, 0 );
2107 }
2108
print_syncinfo(BerValue * data)2109 static void print_syncinfo(
2110 BerValue *data )
2111 {
2112 BerElement *syncinfo;
2113 struct berval bv, cookie;
2114 ber_tag_t tag;
2115 ber_len_t len;
2116
2117 if ( (syncinfo = ber_alloc()) == NULL ) {
2118 return;
2119 }
2120 ber_init2( syncinfo, data, 0 );
2121
2122 printf(_("# SyncInfo Received: "));
2123 tag = ber_peek_tag( syncinfo, &len );
2124 switch (tag) {
2125 case LDAP_TAG_SYNC_NEW_COOKIE: {
2126 printf(_("new cookie\n"));
2127 ber_scanf( syncinfo, "m", &cookie );
2128
2129 if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2130 bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2131 cookie.bv_len ) + 1;
2132 bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2133
2134 bv.bv_len = lutil_b64_ntop(
2135 (unsigned char *) cookie.bv_val,
2136 cookie.bv_len,
2137 bv.bv_val, bv.bv_len );
2138
2139 printf(_("# cookie:: %s\n"), bv.bv_val );
2140 ber_memfree( bv.bv_val );
2141 } else {
2142 printf(_("# cookie: %s\n"), cookie.bv_val );
2143 }
2144 } break;
2145 case LDAP_TAG_SYNC_REFRESH_DELETE: {
2146 ber_int_t done = 1;
2147
2148 printf(_("refresh delete\n"));
2149 /* Skip sequence tag first */
2150 ber_skip_tag( syncinfo, &len );
2151
2152 tag = ber_peek_tag( syncinfo, &len );
2153 if ( tag == LDAP_TAG_SYNC_COOKIE ) {
2154 ber_scanf( syncinfo, "m", &cookie );
2155
2156 if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2157 bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2158 cookie.bv_len ) + 1;
2159 bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2160
2161 bv.bv_len = lutil_b64_ntop(
2162 (unsigned char *) cookie.bv_val,
2163 cookie.bv_len,
2164 bv.bv_val, bv.bv_len );
2165
2166 printf(_("# cookie:: %s\n"), bv.bv_val );
2167 ber_memfree( bv.bv_val );
2168 } else {
2169 printf(_("# cookie: %s\n"), cookie.bv_val );
2170 }
2171
2172 tag = ber_peek_tag( syncinfo, &len );
2173 }
2174 if ( tag == LDAP_TAG_REFRESHDONE ) {
2175 ber_get_boolean( syncinfo, &done );
2176 }
2177 if ( done )
2178 printf(_("# refresh done, switching to persist stage\n"));
2179 } break;
2180 case LDAP_TAG_SYNC_REFRESH_PRESENT: {
2181 ber_int_t done = 1;
2182
2183 printf(_("refresh present\n"));
2184 /* Skip sequence tag first */
2185 ber_skip_tag( syncinfo, &len );
2186
2187 tag = ber_peek_tag( syncinfo, &len );
2188 if ( tag == LDAP_TAG_SYNC_COOKIE ) {
2189 ber_scanf( syncinfo, "m", &cookie );
2190
2191 if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2192 bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2193 cookie.bv_len ) + 1;
2194 bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2195
2196 bv.bv_len = lutil_b64_ntop(
2197 (unsigned char *) cookie.bv_val,
2198 cookie.bv_len,
2199 bv.bv_val, bv.bv_len );
2200
2201 printf(_("# cookie:: %s\n"), bv.bv_val );
2202 ber_memfree( bv.bv_val );
2203 } else {
2204 printf(_("# cookie: %s\n"), cookie.bv_val );
2205 }
2206
2207 tag = ber_peek_tag( syncinfo, &len );
2208 }
2209 if ( tag == LDAP_TAG_REFRESHDONE ) {
2210 ber_get_boolean( syncinfo, &done );
2211 }
2212 if ( done )
2213 printf(_("# refresh done, switching to persist stage\n"));
2214 } break;
2215 case LDAP_TAG_SYNC_ID_SET: {
2216 ber_int_t refreshDeletes = 0;
2217 BerVarray uuids;
2218
2219 printf(_("ID Set\n"));
2220 /* Skip sequence tag first */
2221 ber_skip_tag( syncinfo, &len );
2222
2223 tag = ber_peek_tag( syncinfo, &len );
2224 if ( tag == LDAP_TAG_SYNC_COOKIE ) {
2225 ber_scanf( syncinfo, "m", &cookie );
2226
2227 if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
2228 bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
2229 cookie.bv_len ) + 1;
2230 bv.bv_val = ber_memalloc( bv.bv_len + 1 );
2231
2232 bv.bv_len = lutil_b64_ntop(
2233 (unsigned char *) cookie.bv_val,
2234 cookie.bv_len,
2235 bv.bv_val, bv.bv_len );
2236
2237 printf(_("# cookie:: %s\n"), bv.bv_val );
2238 ber_memfree( bv.bv_val );
2239 } else {
2240 printf(_("# cookie: %s\n"), cookie.bv_val );
2241 }
2242
2243 tag = ber_peek_tag( syncinfo, &len );
2244 }
2245 if ( tag == LDAP_TAG_REFRESHDELETES ) {
2246 ber_get_boolean( syncinfo, &refreshDeletes );
2247 tag = ber_peek_tag( syncinfo, &len );
2248 }
2249 if ( refreshDeletes ) {
2250 printf(_("# following UUIDs no longer match the search\n"));
2251 }
2252
2253 printf(_("# syncUUIDs:\n"));
2254 ber_scanf( syncinfo, "[W]", &uuids );
2255 if ( uuids ) {
2256 char buf[LDAP_LUTIL_UUIDSTR_BUFSIZE];
2257 int i;
2258
2259 for ( i=0; !BER_BVISNULL( &uuids[i] ); i++ ) {
2260 int rc = lutil_uuidstr_from_normalized(
2261 uuids[i].bv_val, uuids[i].bv_len,
2262 buf, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2263 if ( rc <= 0 || rc >= LDAP_LUTIL_UUIDSTR_BUFSIZE ) {
2264 printf(_("#\t(UUID malformed)\n"));
2265 } else {
2266 printf(_("#\t%s\n"), buf);
2267 }
2268 }
2269 ber_bvarray_free( uuids );
2270 }
2271 } break;
2272 case LBER_DEFAULT:
2273 printf(_("empty SyncInfoValue\n"));
2274 default:
2275 printf(_("SyncInfoValue unknown\n"));
2276 break;
2277 }
2278 ber_free( syncinfo, 0 );
2279 }
2280
print_partial(LDAP * ld,LDAPMessage * partial)2281 static void print_partial(
2282 LDAP *ld,
2283 LDAPMessage *partial )
2284 {
2285 int rc;
2286 char *retoid = NULL;
2287 struct berval *retdata = NULL;
2288 LDAPControl **ctrls = NULL;
2289
2290 if( ldif < 2 ) {
2291 printf(_("# extended partial response\n"));
2292 }
2293
2294 rc = ldap_parse_intermediate( ld, partial,
2295 &retoid, &retdata, &ctrls, 0 );
2296
2297 if( rc != LDAP_SUCCESS ) {
2298 tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL );
2299 tool_exit( ld, EXIT_FAILURE );
2300 }
2301
2302 if ( ldif < 2 ) {
2303 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
2304 "partial", retoid, retoid ? strlen(retoid) : 0 );
2305 }
2306
2307 ber_memfree( retoid );
2308
2309 if( retdata ) {
2310 if ( ldif < 2 ) {
2311 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
2312 "data", retdata->bv_val, retdata->bv_len );
2313 }
2314
2315 ber_bvfree( retdata );
2316 }
2317
2318 if( ctrls ) {
2319 tool_print_ctrls( ld, ctrls );
2320 ldap_controls_free( ctrls );
2321 }
2322 }
2323
print_result(LDAP * ld,LDAPMessage * result,int search)2324 static int print_result(
2325 LDAP *ld,
2326 LDAPMessage *result, int search )
2327 {
2328 int rc;
2329 int err;
2330 char *matcheddn = NULL;
2331 char *text = NULL;
2332 char **refs = NULL;
2333 LDAPControl **ctrls = NULL;
2334
2335 if( search ) {
2336 if ( ldif < 2 ) {
2337 printf(_("# search result\n"));
2338 }
2339 if ( ldif < 1 ) {
2340 printf("%s: %d\n", _("search"), ldap_msgid(result) );
2341 }
2342 }
2343
2344 rc = ldap_parse_result( ld, result,
2345 &err, &matcheddn, &text, &refs, &ctrls, 0 );
2346
2347 if( rc != LDAP_SUCCESS ) {
2348 tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
2349 tool_exit( ld, EXIT_FAILURE );
2350 }
2351
2352
2353 if( !ldif ) {
2354 printf( _("result: %d %s\n"), err, ldap_err2string(err) );
2355
2356 } else if ( err != LDAP_SUCCESS ) {
2357 fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err );
2358 }
2359
2360 if( matcheddn ) {
2361 if( *matcheddn ) {
2362 if( !ldif ) {
2363 tool_write_ldif( LDIF_PUT_VALUE,
2364 "matchedDN", matcheddn, strlen(matcheddn) );
2365 } else {
2366 fprintf( stderr, _("Matched DN: %s\n"), matcheddn );
2367 }
2368 }
2369
2370 ber_memfree( matcheddn );
2371 }
2372
2373 if( text ) {
2374 if( *text ) {
2375 if( !ldif ) {
2376 if ( err == LDAP_PARTIAL_RESULTS ) {
2377 char *line;
2378
2379 for ( line = text; line != NULL; ) {
2380 char *next = strchr( line, '\n' );
2381
2382 tool_write_ldif( LDIF_PUT_TEXT,
2383 "text", line,
2384 next ? (size_t) (next - line) : strlen( line ));
2385
2386 line = next ? next + 1 : NULL;
2387 }
2388
2389 } else {
2390 tool_write_ldif( LDIF_PUT_TEXT, "text",
2391 text, strlen(text) );
2392 }
2393 } else {
2394 fprintf( stderr, _("Additional information: %s\n"), text );
2395 }
2396 }
2397
2398 ber_memfree( text );
2399 }
2400
2401 if( refs ) {
2402 int i;
2403 for( i=0; refs[i] != NULL; i++ ) {
2404 if( !ldif ) {
2405 tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) );
2406 } else {
2407 fprintf( stderr, _("Referral: %s\n"), refs[i] );
2408 }
2409 }
2410
2411 ber_memvfree( (void **) refs );
2412 }
2413
2414 pr_morePagedResults = 0;
2415
2416 if( ctrls ) {
2417 tool_print_ctrls( ld, ctrls );
2418 ldap_controls_free( ctrls );
2419 }
2420
2421 return err;
2422 }
2423