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