]> git.sur5r.net Git - openldap/blob - clients/tools/ldapsearch.c
ab700a729b9bbf287dd902275d0b588c3cd2d139
[openldap] / clients / tools / ldapsearch.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/ctype.h>
14 #include <ac/signal.h>
15 #include <ac/string.h>
16 #include <ac/unistd.h>
17
18 #ifdef HAVE_IO_H
19 #include <io.h>
20 #endif
21
22 #include <ldap.h>
23
24 #include "ldif.h"
25 #include "ldap_defaults.h"
26
27 #define DEFSEP          "="
28
29 static void
30 usage( const char *s )
31 {
32         fprintf( stderr,
33 "usage: %s [options] filter [attributes...]\nwhere:\n"
34 "       filter\tRFC-1558 compliant LDAP search filter\n"
35 "       attributes\twhitespace-separated list of attributes to retrieve\n"
36 "\t\t1.1                -- no attributes\n"
37 "\t\t*            -- all user attributes\n"
38 "\t\t+            -- all operational attributes\n"
39 "\t\tempty list -- all non-operational attributes\n"
40 "options:\n"
41 "       -a deref\tone of `never', `always', `search', or `find' (alias\n"
42 "               \tdereferencing)\n"
43 "       -A\t\tretrieve attribute names only (no values)\n"
44 "       -b basedn\tbase dn for search\n"
45 "       -B\t\tdo not suppress printing of binary values\n"
46 "       -d level\tset LDAP debugging level to `level'\n"
47 "       -D binddn\tbind DN\n"
48 "       -E\t\trequest SASL privacy (-EE to make it critical)\n"
49 "       -f file\t\tperform sequence of searches listed in `file'\n"
50 "       -F sep\t\tprint `sep' instead of `=' between attribute names and\n"
51 "               \tvalues\n"
52 "       -h host\t\tLDAP server\n"
53 "       -I\t\trequest SASL integrity checking (-II to make it\n"
54 "               \tcritical)\n"
55 "       -k\t\tuse Kerberos authentication\n"
56 "       -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
57 "       -l limit\ttime limit (in seconds) for search\n"
58 "       -L\t\tprint entries in LDIF format (implies -B)\n"
59 "       -LL\t\tprint entries in LDIF format without comments\n"
60 "       -LLL\t\tprint entries in LDIF format without comments and\n"
61 "               \tversion\n"
62 "       -M\t\tenable Manage DSA IT control (-MM to make critical)\n"
63 "       -n\t\tshow what would be done but don't actually search\n"
64 "       -p port\t\tport on LDAP server\n"
65 "       -P version\tprocotol version (2 or 3)\n"
66 "       -R\t\tdo not automatically follow referrals\n"
67 "       -s scope\tone of base, one, or sub (search scope)\n"
68 "       -S attr\t\tsort the results by attribute `attr'\n"
69 "       -t\t\twrite binary values to files in TMPDIR\n"
70 "       -tt\t\twrite all values to files in TMPDIR\n"
71 "       -T path\t\twrite files to directory specified by path (default:\n"
72 "               \t\"/tmp\")\n"
73 "       -u\t\tinclude User Friendly entry names in the output\n"
74 "       -U user\t\tSASL authentication identity (username)\n"
75 "       -v\t\trun in verbose mode (diagnostics to standard output)\n"
76 "       -V prefix\tURL prefix for files (default: \"file://tmp/\")\n"
77 "       -w passwd\tbind passwd (for simple authentication)\n"
78 "       -W\t\tprompt for bind passwd\n"
79 "       -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
80 "       -Y mech\t\tSASL mechanism\n"
81 "       -z limit\tsize limit (in entries) for search\n"
82 "       -Z\t\trequest the use of TLS (-ZZ to make it critical)\n"
83 ,               s );
84
85         exit( EXIT_FAILURE );
86 }
87
88 static void print_entry LDAP_P((
89         LDAP    *ld,
90         LDAPMessage     *entry,
91         int             attrsonly));
92
93 static int write_ldif LDAP_P((
94         int type,
95         char *name,
96         char *value,
97         ber_len_t vallen ));
98
99 static int dosearch LDAP_P((
100         LDAP    *ld,
101         char    *base,
102         int             scope,
103         char    **attrs,
104         int             attrsonly,
105         char    *filtpatt,
106         char    *value));
107
108 #define TMPDIR "/tmp"
109 #define URLPRE "file:/tmp/"
110
111 static char *tmpdir = NULL;
112 static char *urlpre = NULL;
113
114 static char     *binddn = NULL;
115 static char     *passwd = NULL;
116 static char     *base = NULL;
117 static char     *ldaphost = NULL;
118 static int      ldapport = 0;
119 #ifdef HAVE_CYRUS_SASL
120 static char     *sasl_authc_id = NULL;
121 static char     *sasl_authz_id = NULL;
122 static char     *sasl_mech = NULL;
123 static int      sasl_integrity = 0;
124 static int      sasl_privacy = 0;
125 #endif
126 static int      use_tls = 0;
127 static char     *sep = DEFSEP;
128 static char     *sortattr = NULL;
129 static int      skipsortattr = 0;
130 static int      verbose, not, includeufn, binary, vals2tmp, ldif;
131
132 int
133 main( int argc, char **argv )
134 {
135         char            *infile, *filtpattern, **attrs, line[ BUFSIZ ];
136         FILE            *fp = NULL;
137         int                     rc, i, first, scope, deref, attrsonly, manageDSAit;
138         int                     referrals, timelimit, sizelimit, debug;
139         int             authmethod, version, want_bindpw;
140         LDAP            *ld;
141
142         infile = NULL;
143         debug = verbose = binary = not = vals2tmp =
144                 attrsonly = manageDSAit = ldif = want_bindpw = 0;
145
146         deref = referrals = sizelimit = timelimit = version = -1;
147
148         scope = LDAP_SCOPE_SUBTREE;
149         authmethod = LDAP_AUTH_SIMPLE;
150
151         while (( i = getopt( argc, argv,
152                 "Aa:Bb:D:d:EF:f:h:IKkLl:MnP:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF )
153         {
154         switch( i ) {
155         case 'n':       /* do Not do any searches */
156                 ++not;
157                 break;
158         case 'v':       /* verbose mode */
159                 ++verbose;
160                 break;
161         case 'd':
162                 debug |= atoi( optarg );
163                 break;
164         case 'k':       /* use kerberos bind */
165 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
166                 authmethod = LDAP_AUTH_KRBV4;
167 #else
168                 fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
169                 return( EXIT_FAILURE );
170 #endif
171                 break;
172         case 'K':       /* use kerberos bind, 1st part only */
173 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
174                 authmethod = LDAP_AUTH_KRBV41;
175 #else
176                 fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
177                 return( EXIT_FAILURE );
178 #endif
179                 break;
180                 break;
181         case 'u':       /* include UFN */
182                 ++includeufn;
183                 break;
184         case 't':       /* write attribute values to /tmp files */
185                 ++vals2tmp;
186                 break;
187         case 'M':
188                 /* enable Manage DSA IT */
189                 manageDSAit++;
190                 break;
191         case 'R':       /* don't automatically chase referrals */
192                 referrals = (int) LDAP_OPT_OFF;
193                 break;
194         case 'A':       /* retrieve attribute names only -- no values */
195                 ++attrsonly;
196                 break;
197         case 'L':       /* print entries in LDIF format */
198                 ++ldif;
199                 /* fall through -- always allow binary when outputting LDIF */
200         case 'B':       /* allow binary values to be printed */
201                 ++binary;
202                 break;
203         case 's':       /* search scope */
204                 if ( strcasecmp( optarg, "base" ) == 0 ) {
205                 scope = LDAP_SCOPE_BASE;
206                 } else if ( strcasecmp( optarg, "one" ) == 0 ) {
207                 scope = LDAP_SCOPE_ONELEVEL;
208                 } else if ( strcasecmp( optarg, "sub" ) == 0 ) {
209                 scope = LDAP_SCOPE_SUBTREE;
210                 } else {
211                 fprintf( stderr, "scope should be base, one, or sub\n" );
212                 usage( argv[ 0 ] );
213                 }
214                 break;
215
216         case 'a':       /* set alias deref option */
217                 if ( strcasecmp( optarg, "never" ) == 0 ) {
218                 deref = LDAP_DEREF_NEVER;
219                 } else if ( strcasecmp( optarg, "search" ) == 0 ) {
220                 deref = LDAP_DEREF_SEARCHING;
221                 } else if ( strcasecmp( optarg, "find" ) == 0 ) {
222                 deref = LDAP_DEREF_FINDING;
223                 } else if ( strcasecmp( optarg, "always" ) == 0 ) {
224                 deref = LDAP_DEREF_ALWAYS;
225                 } else {
226                 fprintf( stderr, "alias deref should be never, search, find, or always\n" );
227                 usage( argv[ 0 ] );
228                 }
229                 break;
230                 
231         case 'T':       /* field separator */
232                 if( tmpdir ) free( tmpdir );
233                 tmpdir = strdup( optarg );
234                 break;
235         case 'V':       /* field separator */
236                 if( urlpre ) free( urlpre );
237                 urlpre = strdup( optarg );
238                 break;
239         case 'F':       /* field separator */
240                 sep = strdup( optarg );
241                 break;
242         case 'f':       /* input file */
243                 infile = strdup( optarg );
244                 break;
245         case 'h':       /* ldap host */
246                 ldaphost = strdup( optarg );
247                 break;
248         case 'b':       /* searchbase */
249                 base = strdup( optarg );
250                 break;
251         case 'D':       /* bind DN */
252                 binddn = strdup( optarg );
253                 break;
254         case 'p':       /* ldap port */
255                 ldapport = atoi( optarg );
256                 break;
257         case 'w':       /* bind password */
258                 passwd = strdup( optarg );
259                 {
260                         char* p;
261
262                         for( p = optarg; *p == '\0'; p++ ) {
263                                 *p = '*';
264                         }
265                 }
266                 break;
267         case 'l':       /* time limit */
268                 timelimit = atoi( optarg );
269                 break;
270         case 'z':       /* size limit */
271                 sizelimit = atoi( optarg );
272                 break;
273         case 'S':       /* sort attribute */
274                 sortattr = strdup( optarg );
275                 break;
276         case 'W':
277                 want_bindpw++;
278                 break;
279         case 'P':
280                 switch( atoi( optarg ) )
281                 {
282                 case 2:
283                         version = LDAP_VERSION2;
284                         break;
285                 case 3:
286                         version = LDAP_VERSION3;
287                         break;
288                 default:
289                         fprintf( stderr, "protocol version should be 2 or 3\n" );
290                         usage( argv[0] );
291                 }
292                 break;
293         case 'I':
294 #ifdef HAVE_CYRUS_SASL
295                 sasl_integrity++;
296                 authmethod = LDAP_AUTH_SASL;
297 #else
298                 fprintf( stderr, "%s was not compiled with SASL support\n",
299                         argv[0] );
300                 return( EXIT_FAILURE );
301 #endif
302                 break;
303         case 'E':
304 #ifdef HAVE_CYRUS_SASL
305                 sasl_privacy++;
306                 authmethod = LDAP_AUTH_SASL;
307 #else
308                 fprintf( stderr, "%s was not compiled with SASL support\n",
309                         argv[0] );
310                 return( EXIT_FAILURE );
311 #endif
312                 break;
313         case 'Y':
314 #ifdef HAVE_CYRUS_SASL
315                 if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
316                         sasl_mech = strdup( optarg );
317                 }
318                 authmethod = LDAP_AUTH_SASL;
319 #else
320                 fprintf( stderr, "%s was not compiled with SASL support\n",
321                         argv[0] );
322                 return( EXIT_FAILURE );
323 #endif
324                 break;
325         case 'U':
326 #ifdef HAVE_CYRUS_SASL
327                 sasl_authc_id = strdup( optarg );
328                 authmethod = LDAP_AUTH_SASL;
329 #else
330                 fprintf( stderr, "%s was not compiled with SASL support\n",
331                         argv[0] );
332                 return( EXIT_FAILURE );
333 #endif
334                 break;
335         case 'X':
336 #ifdef HAVE_CYRUS_SASL
337                 sasl_authz_id = strdup( optarg );
338                 authmethod = LDAP_AUTH_SASL;
339 #else
340                 fprintf( stderr, "%s was not compiled with SASL support\n",
341                         argv[0] );
342                 return( EXIT_FAILURE );
343 #endif
344                 break;
345         case 'Z':
346 #ifdef HAVE_TLS
347                 use_tls++;
348 #else
349                 fprintf( stderr, "%s was not compiled with TLS support\n",
350                         argv[0] );
351                 return( EXIT_FAILURE );
352 #endif
353                 break;
354         default:
355                 usage( argv[0] );
356         }
357         }
358
359 #ifdef LDAP_LDIF
360         /* no alternative format */
361         if( ldif < 1 ) ldif = 1;
362 #endif
363
364         if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
365                         LDAP_AUTH_KRBV41 ) ) {
366                 if( version != LDAP_VERSION2 ) {
367
368                         fprintf( stderr, "Kerberos requires LDAPv2\n" );
369                         return( EXIT_FAILURE );
370                 }
371         }
372         else if ( authmethod == LDAP_AUTH_SASL ) {
373                 if( version != LDAP_VERSION3 ) {
374                         fprintf( stderr, "SASL requires LDAPv3\n" );
375                         return( EXIT_FAILURE );
376                 }
377         }
378
379         if( manageDSAit ) {
380                 if( version != LDAP_VERSION3 ) {
381                         fprintf(stderr, "manage DSA control requires LDAPv3\n");
382                         return EXIT_FAILURE;
383                 }
384         }
385
386         if ( argc - optind < 1 ) {
387                 usage( argv[ 0 ] );
388         }
389
390         filtpattern = strdup( argv[ optind ] );
391
392         if ( argv[ optind + 1 ] == NULL ) {
393                 attrs = NULL;
394         } else if ( sortattr == NULL || *sortattr == '\0' ) {
395                 attrs = &argv[ optind + 1 ];
396         } else {
397                 for ( i = optind + 1; i < argc; i++ ) {
398                         if ( strcasecmp( argv[ i ], sortattr ) == 0 ) {
399                                 break;
400                         }
401                 }
402                 if ( i == argc ) {
403                         skipsortattr = 1;
404                         argv[ optind ] = sortattr;
405                 } else {
406                         optind++;
407                 }
408                 attrs = &argv[ optind ];
409         }
410
411         if ( infile != NULL ) {
412                 if ( infile[0] == '-' && infile[1] == '\0' ) {
413                         fp = stdin;
414                 } else if (( fp = fopen( infile, "r" )) == NULL ) {
415                         perror( infile );
416                         return EXIT_FAILURE;
417                 }
418         }
419
420         if( tmpdir == NULL
421                 && (tmpdir = getenv("TMPDIR")) == NULL
422                 && (tmpdir = getenv("TMP")) == NULL
423                 && (tmpdir = getenv("TEMP")) == NULL )
424         {
425                 tmpdir = "/tmp";
426         }
427
428         if( urlpre == NULL ) {
429                 urlpre = malloc( sizeof("file:///") + strlen(tmpdir) );
430
431                 if( urlpre == NULL ) {
432                         perror( "malloc" );
433                         return EXIT_FAILURE;
434                 }
435
436                 sprintf( urlpre, "file:///%s/",
437                         tmpdir[0] == '/' ? &tmpdir[1] : tmpdir );
438
439                 /* urlpre should be URLized.... */
440         }
441
442         if ( debug ) {
443                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
444                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
445                 }
446                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
447                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
448                 }
449                 ldif_debug = debug;
450         }
451
452 #ifdef SIGPIPE
453         (void) SIGNAL( SIGPIPE, SIG_IGN );
454 #endif
455
456         if ( verbose ) {
457                 fprintf( stderr,
458                         (ldapport ? "ldap_init( %s, %d )\n" : "ldap_init( %s, <DEFAULT> )\n"),
459                         (ldaphost != NULL) ? ldaphost : "<DEFAULT>",
460                         ldapport );
461         }
462
463         if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
464                 perror( "ldap_init" );
465                 return( EXIT_FAILURE );
466         }
467
468         if (deref != -1 &&
469                 ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS )
470         {
471                 fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref );
472         }
473         if (timelimit != -1 &&
474                 ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
475         {
476                 fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
477         }
478         if (sizelimit != -1 &&
479                 ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
480         {
481                 fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
482         }
483         if (referrals != -1 &&
484                 ldap_set_option( ld, LDAP_OPT_REFERRALS,
485                                  (referrals ? LDAP_OPT_ON : LDAP_OPT_OFF) ) != LDAP_OPT_SUCCESS )
486         {
487                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
488                         referrals ? "on" : "off" );
489         }
490
491         if (version != -1 &&
492                 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS )
493         {
494                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
495         }
496
497         if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) {
498                 if ( use_tls > 1 ) {
499                         ldap_perror( ld, "ldap_start_tls" );
500                         return( EXIT_FAILURE );
501                 }
502         }
503
504         if (want_bindpw) {
505                 passwd = getpass("Enter LDAP Password: ");
506         }
507
508         if ( authmethod == LDAP_AUTH_SASL ) {
509 #ifdef HAVE_CYRUS_SASL
510                 int     minssf = 0, maxssf = 0;
511
512                 if ( sasl_integrity > 0 )
513                         maxssf = 1;
514                 if ( sasl_integrity > 1 )
515                         minssf = 1;
516                 if ( sasl_privacy > 0 )
517                         maxssf = 100000; /* Something big value */
518                 if ( sasl_privacy > 1 )
519                         minssf = 56;
520                 
521                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
522                                 (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
523                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
524                                 "%d\n", minssf);
525                         return( EXIT_FAILURE );
526                 }
527                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
528                                 (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
529                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
530                                 "%d\n", maxssf);
531                         return( EXIT_FAILURE );
532                 }
533                 
534                 if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
535                                 sasl_authz_id, sasl_mech, NULL, NULL, NULL )
536                                         != LDAP_SUCCESS ) {
537                         ldap_perror( ld, "ldap_sasl_bind" );
538                         return( EXIT_FAILURE );
539                 }
540 #else
541                 fprintf( stderr, "%s was not compiled with SASL support\n",
542                         argv[0] );
543                 return( EXIT_FAILURE );
544 #endif
545         }
546         else {
547                 if ( ldap_bind_s( ld, binddn, passwd, authmethod )
548                                 != LDAP_SUCCESS ) {
549                         ldap_perror( ld, "ldap_bind" );
550                         return( EXIT_FAILURE );
551                 }
552         }
553
554         if ( manageDSAit ) {
555                 int err;
556                 LDAPControl c;
557                 LDAPControl *ctrls[2];
558                 ctrls[0] = &c;
559                 ctrls[1] = NULL;
560
561                 c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
562                 c.ldctl_value.bv_val = NULL;
563                 c.ldctl_value.bv_len = 0;
564                 c.ldctl_iscritical = manageDSAit > 1;
565
566                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
567
568                 if( err != LDAP_OPT_SUCCESS ) {
569                         fprintf( stderr, "Could not set Manage DSA IT Control\n" );
570                         if( c.ldctl_iscritical ) {
571                                 exit( EXIT_FAILURE );
572                         }
573                 }
574         }
575
576         if ( verbose ) {
577                 fprintf( stderr, "filter%s: %s\nreturning: ",
578                         infile != NULL ? " pattern" : "",
579                         filtpattern );
580
581                 if ( attrs == NULL ) {
582                         fprintf( stderr, "ALL" );
583                 } else {
584                         for ( i = 0; attrs[ i ] != NULL; ++i ) {
585                                 fprintf( stderr, "%s ", attrs[ i ] );
586                         }
587                 }
588                 fprintf( stderr, "\n" );
589         }
590
591         if ( ldif ) {
592                 if (ldif < 3 ) {
593                         printf( "version: 1\n\n");
594                 }
595
596                 if (ldif < 2 ) {
597                         printf( "#\n# filter%s: %s\n# returning: ",
598                                 infile != NULL ? " pattern" : "",
599                                 filtpattern );
600
601                         if ( attrs == NULL ) {
602                                 printf( "ALL" );
603                         } else {
604                                 for ( i = 0; attrs[ i ] != NULL; ++i ) {
605                                         printf( "%s ", attrs[ i ] );
606                                 }
607                         }
608                         printf( "\n#\n\n" );
609                 }
610         }
611
612         if ( infile == NULL ) {
613                 rc = dosearch( ld, base, scope, attrs, attrsonly, NULL, filtpattern );
614
615         } else {
616                 rc = 0;
617                 first = 1;
618                 while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) {
619                         line[ strlen( line ) - 1 ] = '\0';
620                         if ( !first ) {
621                                 putchar( '\n' );
622                         } else {
623                                 first = 0;
624                         }
625                         rc = dosearch( ld, base, scope, attrs, attrsonly,
626                                 filtpattern, line );
627                 }
628                 if ( fp != stdin ) {
629                         fclose( fp );
630                 }
631         }
632
633         ldap_unbind( ld );
634         return( rc );
635 }
636
637
638 static int dosearch(
639         LDAP    *ld,
640         char    *base,
641         int             scope,
642         char    **attrs,
643         int             attrsonly,
644         char    *filtpatt,
645         char    *value)
646 {
647         char            filter[ BUFSIZ ];
648         int                     rc, first, matches;
649         LDAPMessage             *res, *e;
650
651         if( filtpatt != NULL ) {
652                 sprintf( filter, filtpatt, value );
653
654                 if ( verbose ) {
655                         fprintf( stderr, "filter is: (%s)\n", filter );
656                 }
657
658                 if( ldif == 1 ) {
659                         printf( "#\n# filter: %s\n#\n", filter );
660                 }
661
662         } else {
663                 sprintf( filter, "%s", value );
664         }
665
666         if ( not ) {
667                 return( LDAP_SUCCESS );
668         }
669
670         if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) {
671                 int ld_errno;
672                 ldap_perror( ld, "ldap_search" );
673
674                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
675                 return( ld_errno );
676         }
677
678         matches = 0;
679         first = 1;
680         res = NULL;
681         while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res ))
682                 == LDAP_RES_SEARCH_ENTRY ) {
683         matches++;
684         e = ldap_first_entry( ld, res );
685         if ( !first ) {
686                 putchar( '\n' );
687         } else {
688                 first = 0;
689         }
690         print_entry( ld, e, attrsonly );
691         ldap_msgfree( res );
692         res = NULL;
693         }
694         if ( rc == -1 ) {
695         ldap_perror( ld, "ldap_result" );
696         return( rc );
697         }
698         if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) {
699                 ldap_perror( ld, "ldap_search" );
700         }
701         if ( sortattr != NULL ) {
702                 (void) ldap_sort_entries( ld, &res,
703                         ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
704                 matches = 0;
705                 first = 1;
706                 for ( e = ldap_first_entry( ld, res ); e != NULL;
707                         e = ldap_next_entry( ld, e ) ) {
708                 matches++;
709                 if ( !first ) {
710                         putchar( '\n' );
711                 } else {
712                         first = 0;
713                 }
714                 print_entry( ld, e, attrsonly );
715                 }
716         }
717
718         if ( verbose ) {
719                 printf( "%d matches\n", matches );
720         }
721
722         ldap_msgfree( res );
723         return( rc );
724 }
725
726
727 static void
728 print_entry(
729         LDAP    *ld,
730         LDAPMessage     *entry,
731         int             attrsonly)
732 {
733         char            *a, *dn, *ufn;
734         char    tmpfname[ 256 ];
735         char    url[ 256 ];
736         int                     i;
737         BerElement              *ber = NULL;
738         struct berval   **bvals;
739         FILE            *tmpfp;
740
741         dn = ldap_get_dn( ld, entry );
742         ufn = NULL;
743
744         if ( ldif == 1 ) {
745                 ufn = ldap_dn2ufn( dn );
746                 write_ldif( LDIF_PUT_COMMENT, NULL, ufn, strlen( ufn ));
747         }
748         if ( ldif ) {
749                 write_ldif( LDIF_PUT_VALUE, "dn", dn, strlen( dn ));
750         } else {
751                 printf( "%s\n", dn );
752         }
753
754         if ( includeufn ) {
755                 if( ufn == NULL ) {
756                         ufn = ldap_dn2ufn( dn );
757                 }
758                 if ( ldif ) {
759                         write_ldif( LDIF_PUT_VALUE, "ufn", ufn, strlen( ufn ));
760                 } else {
761                         printf( "%s\n", ufn );
762                 }
763         }
764
765         if( ufn != NULL ) ldap_memfree( ufn );
766         ldap_memfree( dn );
767
768         for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL;
769                 a = ldap_next_attribute( ld, entry, ber ) )
770         {
771                 if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) {
772                         continue;
773                 }
774
775                 if ( attrsonly ) {
776                         if ( ldif ) {
777                                 write_ldif( LDIF_PUT_NOVALUE, a, NULL, 0 );
778                         } else {
779                                 printf( "%s\n", a );
780                         }
781
782                 } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) {
783                         for ( i = 0; bvals[i] != NULL; i++ ) {
784                                 if ( vals2tmp > 1 || ( vals2tmp
785                                         && ldif_is_not_printable( bvals[i]->bv_val, bvals[i]->bv_len ) ))
786                                 {
787                                         /* write value to file */
788                                         sprintf( tmpfname, "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
789                                                 tmpdir, a );
790                                         tmpfp = NULL;
791
792                                         if ( mktemp( tmpfname ) == NULL ) {
793                                                 perror( tmpfname );
794                                                 continue;
795                                         }
796
797                                         if (( tmpfp = fopen( tmpfname, "w")) == NULL ) {
798                                                 perror( tmpfname );
799                                                 continue;
800                                         }
801
802                                         if ( fwrite( bvals[ i ]->bv_val,
803                                                 bvals[ i ]->bv_len, 1, tmpfp ) == 0 )
804                                         {
805                                                 perror( tmpfname );
806                                                 fclose( tmpfp );
807                                                 continue;
808                                         }
809
810                                         fclose( tmpfp );
811
812                                         sprintf( url, "%s%s", urlpre,
813                                                 &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
814
815                                         if ( ldif ) {
816                                                 write_ldif( LDIF_PUT_URL, a, url, strlen( url ));
817                                         } else {
818                                                 printf( "%s%s%s\n", a, sep, url );
819                                         }
820
821
822                                 } else {
823                                         if ( ldif ) {
824                                                 write_ldif( LDIF_PUT_VALUE, a,
825                                                         bvals[ i ]->bv_val, bvals[ i ]->bv_len );
826
827                                         } else {
828                                                 int notprint = !binary && !vals2tmp
829                                                         && ldif_is_not_printable( bvals[i]->bv_val,
830                                                                 bvals[i]->bv_len ); 
831                                                 printf( "%s%s", a, sep );
832                                                 puts( notprint ? "NOT PRINTABLE" : bvals[ i ]->bv_val );
833                                         }
834                                 }
835                         }
836                         ber_bvecfree( bvals );
837                 }
838         }
839
840         if( ber != NULL ) {
841                 ber_free( ber, 0 );
842         }
843 }
844
845
846 static int
847 write_ldif( int type, char *name, char *value, ber_len_t vallen )
848 {
849         char    *ldif;
850
851         if (( ldif = ldif_put( type, name, value, vallen )) == NULL ) {
852                 return( -1 );
853         }
854
855         fputs( ldif, stdout );
856         ber_memfree( ldif );
857
858         return( 0 );
859 }