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