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