]> git.sur5r.net Git - openldap/blob - clients/tools/ldapsearch.c
2603107e438c491b710ce149772138cb9459b2c4
[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                         fprintf( stderr, "Kerberos requires LDAPv2\n" );
368                         return( EXIT_FAILURE );
369                 }
370                 version = LDAP_VERSION2;
371         }
372         else if ( authmethod == LDAP_AUTH_SASL ) {
373                 if( version != -1 || version != LDAP_VERSION3 ) {
374                         fprintf( stderr, "SASL requires LDAPv3\n" );
375                         return( EXIT_FAILURE );
376                 }
377                 version = LDAP_VERSION3;
378         }
379
380         if( manageDSAit ) {
381                 if( version != -1 || version != LDAP_VERSION3 ) {
382                         fprintf(stderr, "manage DSA control requires LDAPv3\n");
383                         return EXIT_FAILURE;
384                 }
385                 version = LDAP_VERSION3;
386         }
387
388         if( use_tls ) {
389                 if( version != -1 || version != LDAP_VERSION3 ) {
390                         fprintf(stderr, "Start TLS requires LDAPv3\n");
391                         return EXIT_FAILURE;
392                 }
393                 version = LDAP_VERSION3;
394         }
395
396         if ( argc - optind < 1 ) {
397                 usage( argv[ 0 ] );
398         }
399
400         filtpattern = strdup( argv[ optind ] );
401
402         if ( argv[ optind + 1 ] == NULL ) {
403                 attrs = NULL;
404         } else if ( sortattr == NULL || *sortattr == '\0' ) {
405                 attrs = &argv[ optind + 1 ];
406         } else {
407                 for ( i = optind + 1; i < argc; i++ ) {
408                         if ( strcasecmp( argv[ i ], sortattr ) == 0 ) {
409                                 break;
410                         }
411                 }
412                 if ( i == argc ) {
413                         skipsortattr = 1;
414                         argv[ optind ] = sortattr;
415                 } else {
416                         optind++;
417                 }
418                 attrs = &argv[ optind ];
419         }
420
421         if ( infile != NULL ) {
422                 if ( infile[0] == '-' && infile[1] == '\0' ) {
423                         fp = stdin;
424                 } else if (( fp = fopen( infile, "r" )) == NULL ) {
425                         perror( infile );
426                         return EXIT_FAILURE;
427                 }
428         }
429
430         if( tmpdir == NULL
431                 && (tmpdir = getenv("TMPDIR")) == NULL
432                 && (tmpdir = getenv("TMP")) == NULL
433                 && (tmpdir = getenv("TEMP")) == NULL )
434         {
435                 tmpdir = "/tmp";
436         }
437
438         if( urlpre == NULL ) {
439                 urlpre = malloc( sizeof("file:///") + strlen(tmpdir) );
440
441                 if( urlpre == NULL ) {
442                         perror( "malloc" );
443                         return EXIT_FAILURE;
444                 }
445
446                 sprintf( urlpre, "file:///%s/",
447                         tmpdir[0] == '/' ? &tmpdir[1] : tmpdir );
448
449                 /* urlpre should be URLized.... */
450         }
451
452         if ( debug ) {
453                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
454                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
455                 }
456                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
457                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
458                 }
459                 ldif_debug = debug;
460         }
461
462 #ifdef SIGPIPE
463         (void) SIGNAL( SIGPIPE, SIG_IGN );
464 #endif
465
466         if ( verbose ) {
467                 fprintf( stderr,
468                         (ldapport ? "ldap_init( %s, %d )\n" : "ldap_init( %s, <DEFAULT> )\n"),
469                         (ldaphost != NULL) ? ldaphost : "<DEFAULT>",
470                         ldapport );
471         }
472
473         if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
474                 perror( "ldap_init" );
475                 return( EXIT_FAILURE );
476         }
477
478         if (deref != -1 &&
479                 ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS )
480         {
481                 fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref );
482         }
483         if (timelimit != -1 &&
484                 ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
485         {
486                 fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
487         }
488         if (sizelimit != -1 &&
489                 ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
490         {
491                 fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
492         }
493         if (referrals != -1 &&
494                 ldap_set_option( ld, LDAP_OPT_REFERRALS,
495                                  (referrals ? LDAP_OPT_ON : LDAP_OPT_OFF) ) != LDAP_OPT_SUCCESS )
496         {
497                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
498                         referrals ? "on" : "off" );
499         }
500
501         if (version != -1 &&
502                 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS )
503         {
504                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
505         }
506
507         if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) {
508                 if ( use_tls > 1 ) {
509                         ldap_perror( ld, "ldap_start_tls" );
510                         return( EXIT_FAILURE );
511                 }
512         }
513
514         if (want_bindpw) {
515                 passwd = getpass("Enter LDAP Password: ");
516         }
517
518         if ( authmethod == LDAP_AUTH_SASL ) {
519 #ifdef HAVE_CYRUS_SASL
520                 int     minssf = 0, maxssf = 0;
521
522                 if ( sasl_integrity > 0 )
523                         maxssf = 1;
524                 if ( sasl_integrity > 1 )
525                         minssf = 1;
526                 if ( sasl_privacy > 0 )
527                         maxssf = 100000; /* Something big value */
528                 if ( sasl_privacy > 1 )
529                         minssf = 56;
530                 
531                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
532                                 (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
533                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
534                                 "%d\n", minssf);
535                         return( EXIT_FAILURE );
536                 }
537                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
538                                 (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
539                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
540                                 "%d\n", maxssf);
541                         return( EXIT_FAILURE );
542                 }
543                 
544                 if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
545                                 sasl_authz_id, sasl_mech, NULL, NULL, NULL )
546                                         != LDAP_SUCCESS ) {
547                         ldap_perror( ld, "ldap_sasl_bind" );
548                         return( EXIT_FAILURE );
549                 }
550 #else
551                 fprintf( stderr, "%s was not compiled with SASL support\n",
552                         argv[0] );
553                 return( EXIT_FAILURE );
554 #endif
555         }
556         else {
557                 if ( ldap_bind_s( ld, binddn, passwd, authmethod )
558                                 != LDAP_SUCCESS ) {
559                         ldap_perror( ld, "ldap_bind" );
560                         return( EXIT_FAILURE );
561                 }
562         }
563
564         if ( manageDSAit ) {
565                 int err;
566                 LDAPControl c;
567                 LDAPControl *ctrls[2];
568                 ctrls[0] = &c;
569                 ctrls[1] = NULL;
570
571                 c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
572                 c.ldctl_value.bv_val = NULL;
573                 c.ldctl_value.bv_len = 0;
574                 c.ldctl_iscritical = manageDSAit > 1;
575
576                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
577
578                 if( err != LDAP_OPT_SUCCESS ) {
579                         fprintf( stderr, "Could not set Manage DSA IT Control\n" );
580                         if( c.ldctl_iscritical ) {
581                                 exit( EXIT_FAILURE );
582                         }
583                 }
584         }
585
586         if ( verbose ) {
587                 fprintf( stderr, "filter%s: %s\nreturning: ",
588                         infile != NULL ? " pattern" : "",
589                         filtpattern );
590
591                 if ( attrs == NULL ) {
592                         fprintf( stderr, "ALL" );
593                 } else {
594                         for ( i = 0; attrs[ i ] != NULL; ++i ) {
595                                 fprintf( stderr, "%s ", attrs[ i ] );
596                         }
597                 }
598                 fprintf( stderr, "\n" );
599         }
600
601         if ( ldif ) {
602                 if (ldif < 3 ) {
603                         printf( "version: 1\n\n");
604                 }
605
606                 if (ldif < 2 ) {
607                         printf( "#\n# filter%s: %s\n# returning: ",
608                                 infile != NULL ? " pattern" : "",
609                                 filtpattern );
610
611                         if ( attrs == NULL ) {
612                                 printf( "ALL" );
613                         } else {
614                                 for ( i = 0; attrs[ i ] != NULL; ++i ) {
615                                         printf( "%s ", attrs[ i ] );
616                                 }
617                         }
618                         printf( "\n#\n\n" );
619                 }
620         }
621
622         if ( infile == NULL ) {
623                 rc = dosearch( ld, base, scope, attrs, attrsonly, NULL, filtpattern );
624
625         } else {
626                 rc = 0;
627                 first = 1;
628                 while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) {
629                         line[ strlen( line ) - 1 ] = '\0';
630                         if ( !first ) {
631                                 putchar( '\n' );
632                         } else {
633                                 first = 0;
634                         }
635                         rc = dosearch( ld, base, scope, attrs, attrsonly,
636                                 filtpattern, line );
637                 }
638                 if ( fp != stdin ) {
639                         fclose( fp );
640                 }
641         }
642
643         ldap_unbind( ld );
644         return( rc );
645 }
646
647
648 static int dosearch(
649         LDAP    *ld,
650         char    *base,
651         int             scope,
652         char    **attrs,
653         int             attrsonly,
654         char    *filtpatt,
655         char    *value)
656 {
657         char            filter[ BUFSIZ ];
658         int                     rc, first, matches;
659         LDAPMessage             *res, *e;
660
661         if( filtpatt != NULL ) {
662                 sprintf( filter, filtpatt, value );
663
664                 if ( verbose ) {
665                         fprintf( stderr, "filter is: (%s)\n", filter );
666                 }
667
668                 if( ldif == 1 ) {
669                         printf( "#\n# filter: %s\n#\n", filter );
670                 }
671
672         } else {
673                 sprintf( filter, "%s", value );
674         }
675
676         if ( not ) {
677                 return( LDAP_SUCCESS );
678         }
679
680         if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) {
681                 int ld_errno;
682                 ldap_perror( ld, "ldap_search" );
683
684                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
685                 return( ld_errno );
686         }
687
688         matches = 0;
689         first = 1;
690         res = NULL;
691         while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res ))
692                 == LDAP_RES_SEARCH_ENTRY ) {
693         matches++;
694         e = ldap_first_entry( ld, res );
695         if ( !first ) {
696                 putchar( '\n' );
697         } else {
698                 first = 0;
699         }
700         print_entry( ld, e, attrsonly );
701         ldap_msgfree( res );
702         res = NULL;
703         }
704         if ( rc == -1 ) {
705         ldap_perror( ld, "ldap_result" );
706         return( rc );
707         }
708         if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) {
709                 ldap_perror( ld, "ldap_search" );
710         }
711         if ( sortattr != NULL ) {
712                 (void) ldap_sort_entries( ld, &res,
713                         ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
714                 matches = 0;
715                 first = 1;
716                 for ( e = ldap_first_entry( ld, res ); e != NULL;
717                         e = ldap_next_entry( ld, e ) ) {
718                 matches++;
719                 if ( !first ) {
720                         putchar( '\n' );
721                 } else {
722                         first = 0;
723                 }
724                 print_entry( ld, e, attrsonly );
725                 }
726         }
727
728         if ( verbose ) {
729                 printf( "%d matches\n", matches );
730         }
731
732         ldap_msgfree( res );
733         return( rc );
734 }
735
736
737 static void
738 print_entry(
739         LDAP    *ld,
740         LDAPMessage     *entry,
741         int             attrsonly)
742 {
743         char            *a, *dn, *ufn;
744         char    tmpfname[ 256 ];
745         char    url[ 256 ];
746         int                     i;
747         BerElement              *ber = NULL;
748         struct berval   **bvals;
749         FILE            *tmpfp;
750
751         dn = ldap_get_dn( ld, entry );
752         ufn = NULL;
753
754         if ( ldif == 1 ) {
755                 ufn = ldap_dn2ufn( dn );
756                 write_ldif( LDIF_PUT_COMMENT, NULL, ufn, strlen( ufn ));
757         }
758         if ( ldif ) {
759                 write_ldif( LDIF_PUT_VALUE, "dn", dn, strlen( dn ));
760         } else {
761                 printf( "%s\n", dn );
762         }
763
764         if ( includeufn ) {
765                 if( ufn == NULL ) {
766                         ufn = ldap_dn2ufn( dn );
767                 }
768                 if ( ldif ) {
769                         write_ldif( LDIF_PUT_VALUE, "ufn", ufn, strlen( ufn ));
770                 } else {
771                         printf( "%s\n", ufn );
772                 }
773         }
774
775         if( ufn != NULL ) ldap_memfree( ufn );
776         ldap_memfree( dn );
777
778         for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL;
779                 a = ldap_next_attribute( ld, entry, ber ) )
780         {
781                 if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) {
782                         continue;
783                 }
784
785                 if ( attrsonly ) {
786                         if ( ldif ) {
787                                 write_ldif( LDIF_PUT_NOVALUE, a, NULL, 0 );
788                         } else {
789                                 printf( "%s\n", a );
790                         }
791
792                 } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) {
793                         for ( i = 0; bvals[i] != NULL; i++ ) {
794                                 if ( vals2tmp > 1 || ( vals2tmp
795                                         && ldif_is_not_printable( bvals[i]->bv_val, bvals[i]->bv_len ) ))
796                                 {
797                                         /* write value to file */
798                                         sprintf( tmpfname, "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
799                                                 tmpdir, a );
800                                         tmpfp = NULL;
801
802                                         if ( mktemp( tmpfname ) == NULL ) {
803                                                 perror( tmpfname );
804                                                 continue;
805                                         }
806
807                                         if (( tmpfp = fopen( tmpfname, "w")) == NULL ) {
808                                                 perror( tmpfname );
809                                                 continue;
810                                         }
811
812                                         if ( fwrite( bvals[ i ]->bv_val,
813                                                 bvals[ i ]->bv_len, 1, tmpfp ) == 0 )
814                                         {
815                                                 perror( tmpfname );
816                                                 fclose( tmpfp );
817                                                 continue;
818                                         }
819
820                                         fclose( tmpfp );
821
822                                         sprintf( url, "%s%s", urlpre,
823                                                 &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
824
825                                         if ( ldif ) {
826                                                 write_ldif( LDIF_PUT_URL, a, url, strlen( url ));
827                                         } else {
828                                                 printf( "%s%s%s\n", a, sep, url );
829                                         }
830
831
832                                 } else {
833                                         if ( ldif ) {
834                                                 write_ldif( LDIF_PUT_VALUE, a,
835                                                         bvals[ i ]->bv_val, bvals[ i ]->bv_len );
836
837                                         } else {
838                                                 int notprint = !binary && !vals2tmp
839                                                         && ldif_is_not_printable( bvals[i]->bv_val,
840                                                                 bvals[i]->bv_len ); 
841                                                 printf( "%s%s", a, sep );
842                                                 puts( notprint ? "NOT PRINTABLE" : bvals[ i ]->bv_val );
843                                         }
844                                 }
845                         }
846                         ber_bvecfree( bvals );
847                 }
848         }
849
850         if( ber != NULL ) {
851                 ber_free( ber, 0 );
852         }
853 }
854
855
856 static int
857 write_ldif( int type, char *name, char *value, ber_len_t vallen )
858 {
859         char    *ldif;
860
861         if (( ldif = ldif_put( type, name, value, vallen )) == NULL ) {
862                 return( -1 );
863         }
864
865         fputs( ldif, stdout );
866         ber_memfree( ldif );
867
868         return( 0 );
869 }