]> git.sur5r.net Git - openldap/blob - clients/tools/ldapsearch.c
Use autoconf defines
[openldap] / clients / tools / ldapsearch.c
1 #include "portable.h"
2
3 #include <stdio.h>
4 #include <ctype.h>
5
6 #include <ac/socket.h>
7 #include <ac/string.h>
8 #include <ac/time.h>
9 #include <ac/unistd.h>
10
11 #include <lber.h>
12 #include <ldap.h>
13 #include <ldif.h>
14
15 #include "ldapconfig.h"
16
17 #define DEFSEP          "="
18
19 #ifdef LDAP_DEBUG
20 extern int ldap_debug, lber_debug;
21 #endif /* LDAP_DEBUG */
22
23
24 static void usage( s )
25 char    *s;
26 {
27     fprintf( stderr, "usage: %s [options] filter [attributes...]\nwhere:\n", s );
28     fprintf( stderr, "    filter\tRFC-1558 compliant LDAP search filter\n" );
29     fprintf( stderr, "    attributes\twhitespace-separated list of attributes to retrieve\n" );
30     fprintf( stderr, "\t\t(if no attribute list is given, all are retrieved)\n" );
31     fprintf( stderr, "options:\n" );
32     fprintf( stderr, "    -n\t\tshow what would be done but don't actually search\n" );
33     fprintf( stderr, "    -v\t\trun in verbose mode (diagnostics to standard output)\n" );
34     fprintf( stderr, "    -t\t\twrite values to files in /tmp\n" );
35     fprintf( stderr, "    -u\t\tinclude User Friendly entry names in the output\n" );
36     fprintf( stderr, "    -A\t\tretrieve attribute names only (no values)\n" );
37     fprintf( stderr, "    -B\t\tdo not suppress printing of non-ASCII values\n" );
38     fprintf( stderr, "    -L\t\tprint entries in LDIF format (-B is implied)\n" );
39 #ifdef LDAP_REFERRALS
40     fprintf( stderr, "    -R\t\tdo not automatically follow referrals\n" );
41 #endif /* LDAP_REFERRALS */
42     fprintf( stderr, "    -d level\tset LDAP debugging level to `level'\n" );
43     fprintf( stderr, "    -F sep\tprint `sep' instead of `=' between attribute names and values\n" );
44     fprintf( stderr, "    -S attr\tsort the results by attribute `attr'\n" );
45     fprintf( stderr, "    -f file\tperform sequence of searches listed in `file'\n" );
46     fprintf( stderr, "    -b basedn\tbase dn for search\n" );
47     fprintf( stderr, "    -s scope\tone of base, one, or sub (search scope)\n" );
48     fprintf( stderr, "    -a deref\tone of never, always, search, or find (alias dereferencing)\n" );
49     fprintf( stderr, "    -l time lim\ttime limit (in seconds) for search\n" );
50     fprintf( stderr, "    -z size lim\tsize limit (in entries) for search\n" );
51     fprintf( stderr, "    -D binddn\tbind dn\n" );
52     fprintf( stderr, "    -w passwd\tbind passwd (for simple authentication)\n" );
53 #ifdef HAVE_KERBEROS
54     fprintf( stderr, "    -k\t\tuse Kerberos instead of Simple Password authentication\n" );
55 #endif
56     fprintf( stderr, "    -h host\tldap server\n" );
57     fprintf( stderr, "    -p port\tport on ldap server\n" );
58     exit( 1 );
59 }
60
61 static void print_entry LDAP_P((
62     LDAP        *ld,
63     LDAPMessage *entry,
64     int         attrsonly));
65
66 static int write_ldif_value LDAP_P((
67         char *type,
68         char *value,
69         unsigned long vallen ));
70
71 static int dosearch LDAP_P((
72         LDAP    *ld,
73     char        *base,
74     int         scope,
75     char        **attrs,
76     int         attrsonly,
77     char        *filtpatt,
78     char        *value));
79
80 static char     *binddn = LDAPSEARCH_BINDDN;
81 static char     *passwd = LDAPSEARCH_BIND_CRED;
82 static char     *base = LDAPSEARCH_BASE;
83 static char     *ldaphost = LDAPHOST;
84 static int      ldapport = LDAP_PORT;
85 static char     *sep = DEFSEP;
86 static char     *sortattr = NULL;
87 static int      skipsortattr = 0;
88 static int      verbose, not, includeufn, allow_binary, vals2tmp, ldif;
89
90 main( argc, argv )
91 int     argc;
92 char    **argv;
93 {
94     char                *infile, *filtpattern, **attrs, line[ BUFSIZ ];
95     FILE                *fp;
96     int                 rc, i, first, scope, kerberos, deref, attrsonly;
97     int                 ldap_options, timelimit, sizelimit, authmethod;
98     LDAP                *ld;
99     extern char         *optarg;
100     extern int          optind;
101
102     infile = NULL;
103     deref = verbose = allow_binary = not = kerberos = vals2tmp =
104             attrsonly = ldif = 0;
105 #ifdef LDAP_REFERRALS
106     ldap_options = LDAP_OPT_REFERRALS;
107 #else /* LDAP_REFERRALS */
108     ldap_options = 0;
109 #endif /* LDAP_REFERRALS */
110     sizelimit = timelimit = 0;
111     scope = LDAP_SCOPE_SUBTREE;
112
113     while (( i = getopt( argc, argv,
114 #ifdef HAVE_KERBEROS
115             "KknuvtRABLD:s:f:h:b:d:p:F:a:w:l:z:S:"
116 #else
117             "nuvtRABLD:s:f:h:b:d:p:F:a:w:l:z:S:"
118 #endif
119             )) != EOF ) {
120         switch( i ) {
121         case 'n':       /* do Not do any searches */
122             ++not;
123             break;
124         case 'v':       /* verbose mode */
125             ++verbose;
126             break;
127         case 'd':
128 #ifdef LDAP_DEBUG
129             ldap_debug = lber_debug = atoi( optarg );   /* */
130 #else /* LDAP_DEBUG */
131             fprintf( stderr, "compile with -DLDAP_DEBUG for debugging\n" );
132 #endif /* LDAP_DEBUG */
133             break;
134 #ifdef HAVE_KERBEROS
135         case 'k':       /* use kerberos bind */
136             kerberos = 2;
137             break;
138         case 'K':       /* use kerberos bind, 1st part only */
139             kerberos = 1;
140             break;
141 #endif
142         case 'u':       /* include UFN */
143             ++includeufn;
144             break;
145         case 't':       /* write attribute values to /tmp files */
146             ++vals2tmp;
147             break;
148         case 'R':       /* don't automatically chase referrals */
149 #ifdef LDAP_REFERRALS
150             ldap_options &= ~LDAP_OPT_REFERRALS;
151 #else /* LDAP_REFERRALS */
152             fprintf( stderr,
153                     "compile with -DLDAP_REFERRALS for referral support\n" );
154 #endif /* LDAP_REFERRALS */
155             break;
156         case 'A':       /* retrieve attribute names only -- no values */
157             ++attrsonly;
158             break;
159         case 'L':       /* print entries in LDIF format */
160             ++ldif;
161             /* fall through -- always allow binary when outputting LDIF */
162         case 'B':       /* allow binary values to be printed */
163             ++allow_binary;
164             break;
165         case 's':       /* search scope */
166             if ( strncasecmp( optarg, "base", 4 ) == 0 ) {
167                 scope = LDAP_SCOPE_BASE;
168             } else if ( strncasecmp( optarg, "one", 3 ) == 0 ) {
169                 scope = LDAP_SCOPE_ONELEVEL;
170             } else if ( strncasecmp( optarg, "sub", 3 ) == 0 ) {
171                 scope = LDAP_SCOPE_SUBTREE;
172             } else {
173                 fprintf( stderr, "scope should be base, one, or sub\n" );
174                 usage( argv[ 0 ] );
175             }
176             break;
177
178         case 'a':       /* set alias deref option */
179             if ( strncasecmp( optarg, "never", 5 ) == 0 ) {
180                 deref = LDAP_DEREF_NEVER;
181             } else if ( strncasecmp( optarg, "search", 5 ) == 0 ) {
182                 deref = LDAP_DEREF_SEARCHING;
183             } else if ( strncasecmp( optarg, "find", 4 ) == 0 ) {
184                 deref = LDAP_DEREF_FINDING;
185             } else if ( strncasecmp( optarg, "always", 6 ) == 0 ) {
186                 deref = LDAP_DEREF_ALWAYS;
187             } else {
188                 fprintf( stderr, "alias deref should be never, search, find, or always\n" );
189                 usage( argv[ 0 ] );
190             }
191             break;
192             
193         case 'F':       /* field separator */
194             sep = strdup( optarg );
195             break;
196         case 'f':       /* input file */
197             infile = strdup( optarg );
198             break;
199         case 'h':       /* ldap host */
200             ldaphost = strdup( optarg );
201             break;
202         case 'b':       /* searchbase */
203             base = strdup( optarg );
204             break;
205         case 'D':       /* bind DN */
206             binddn = strdup( optarg );
207             break;
208         case 'p':       /* ldap port */
209             ldapport = atoi( optarg );
210             break;
211         case 'w':       /* bind password */
212             passwd = strdup( optarg );
213             break;
214         case 'l':       /* time limit */
215             timelimit = atoi( optarg );
216             break;
217         case 'z':       /* size limit */
218             sizelimit = atoi( optarg );
219             break;
220         case 'S':       /* sort attribute */
221             sortattr = strdup( optarg );
222             break;
223         default:
224             usage( argv[0] );
225         }
226     }
227
228     if ( argc - optind < 1 ) {
229         usage( argv[ 0 ] );
230     }
231     filtpattern = strdup( argv[ optind ] );
232     if ( argv[ optind + 1 ] == NULL ) {
233         attrs = NULL;
234     } else if ( sortattr == NULL || *sortattr == '\0' ) {
235         attrs = &argv[ optind + 1 ];
236     } else {
237         for ( i = optind + 1; i < argc; i++ ) {
238             if ( strcasecmp( argv[ i ], sortattr ) == 0 ) {
239                 break;
240             }
241         }
242         if ( i == argc ) {
243                 skipsortattr = 1;
244                 argv[ optind ] = sortattr;
245         } else {
246                 optind++;
247         }
248         attrs = &argv[ optind ];
249     }
250
251     if ( infile != NULL ) {
252         if ( infile[0] == '-' && infile[1] == '\0' ) {
253             fp = stdin;
254         } else if (( fp = fopen( infile, "r" )) == NULL ) {
255             perror( infile );
256             exit( 1 );
257         }
258     }
259
260     if ( verbose ) {
261         printf( "ldap_open( %s, %d )\n", ldaphost, ldapport );
262     }
263
264     if (( ld = ldap_open( ldaphost, ldapport )) == NULL ) {
265         perror( ldaphost );
266         exit( 1 );
267     }
268
269     ld->ld_deref = deref;
270     ld->ld_timelimit = timelimit;
271     ld->ld_sizelimit = sizelimit;
272     ld->ld_options = ldap_options;
273
274     if ( !kerberos ) {
275         authmethod = LDAP_AUTH_SIMPLE;
276     } else if ( kerberos == 1 ) {
277         authmethod = LDAP_AUTH_KRBV41;
278     } else {
279         authmethod =  LDAP_AUTH_KRBV4;
280     }
281     if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) {
282         ldap_perror( ld, "ldap_bind" );
283         exit( 1 );
284     }
285
286     if ( verbose ) {
287         printf( "filter pattern: %s\nreturning: ", filtpattern );
288         if ( attrs == NULL ) {
289             printf( "ALL" );
290         } else {
291             for ( i = 0; attrs[ i ] != NULL; ++i ) {
292                 printf( "%s ", attrs[ i ] );
293             }
294         }
295         putchar( '\n' );
296     }
297
298     if ( infile == NULL ) {
299         rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern, "" );
300     } else {
301         rc = 0;
302         first = 1;
303         while ( rc == 0 && fgets( line, sizeof( line ), fp ) != NULL ) {
304             line[ strlen( line ) - 1 ] = '\0';
305             if ( !first ) {
306                 putchar( '\n' );
307             } else {
308                 first = 0;
309             }
310             rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern,
311                     line );
312         }
313         if ( fp != stdin ) {
314             fclose( fp );
315         }
316     }
317
318     ldap_unbind( ld );
319     exit( rc );
320 }
321
322
323 static int dosearch(
324         LDAP    *ld,
325     char        *base,
326     int         scope,
327     char        **attrs,
328     int         attrsonly,
329     char        *filtpatt,
330     char        *value)
331 {
332     char                filter[ BUFSIZ ];
333     int                 rc, first, matches;
334     LDAPMessage         *res, *e;
335
336     sprintf( filter, filtpatt, value );
337
338     if ( verbose ) {
339         printf( "filter is: (%s)\n", filter );
340     }
341
342     if ( not ) {
343         return( LDAP_SUCCESS );
344     }
345
346     if ( ldap_search( ld, base, scope, filter, attrs, attrsonly ) == -1 ) {
347         ldap_perror( ld, "ldap_search" );
348         return( ld->ld_errno );
349     }
350
351     matches = 0;
352     first = 1;
353     while ( (rc = ldap_result( ld, LDAP_RES_ANY, sortattr ? 1 : 0, NULL, &res ))
354             == LDAP_RES_SEARCH_ENTRY ) {
355         matches++;
356         e = ldap_first_entry( ld, res );
357         if ( !first ) {
358             putchar( '\n' );
359         } else {
360             first = 0;
361         }
362         print_entry( ld, e, attrsonly );
363         ldap_msgfree( res );
364     }
365     if ( rc == -1 ) {
366         ldap_perror( ld, "ldap_result" );
367         return( rc );
368     }
369     if (( rc = ldap_result2error( ld, res, 0 )) != LDAP_SUCCESS ) {
370         ldap_perror( ld, "ldap_search" );
371     }
372     if ( sortattr != NULL ) {
373             extern int  strcasecmp();
374
375             (void) ldap_sort_entries( ld, &res,
376                     ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
377             matches = 0;
378             first = 1;
379             for ( e = ldap_first_entry( ld, res ); e != NULLMSG;
380                     e = ldap_next_entry( ld, e ) ) {
381                 matches++;
382                 if ( !first ) {
383                     putchar( '\n' );
384                 } else {
385                     first = 0;
386                 }
387                 print_entry( ld, e, attrsonly );
388             }
389     }
390
391     if ( verbose ) {
392         printf( "%d matches\n", matches );
393     }
394
395     ldap_msgfree( res );
396     return( rc );
397 }
398
399
400 void print_entry(
401     LDAP        *ld,
402     LDAPMessage *entry,
403     int         attrsonly)
404 {
405     char                *a, *dn, *ufn, tmpfname[ 64 ];
406     int                 i, j, notascii;
407     BerElement          *ber;
408     struct berval       **bvals;
409     FILE                *tmpfp;
410     extern char         *mktemp();
411
412     dn = ldap_get_dn( ld, entry );
413     if ( ldif ) {
414         write_ldif_value( "dn", dn, strlen( dn ));
415     } else {
416         printf( "%s\n", dn );
417     }
418     if ( includeufn ) {
419         ufn = ldap_dn2ufn( dn );
420         if ( ldif ) {
421             write_ldif_value( "ufn", ufn, strlen( ufn ));
422         } else {
423             printf( "%s\n", ufn );
424         }
425         free( ufn );
426     }
427     free( dn );
428
429     for ( a = ldap_first_attribute( ld, entry, &ber ); a != NULL;
430             a = ldap_next_attribute( ld, entry, ber ) ) {
431         if ( skipsortattr && strcasecmp( a, sortattr ) == 0 ) {
432             continue;
433         }
434         if ( attrsonly ) {
435             if ( ldif ) {
436                 write_ldif_value( a, "", 0 );
437             } else {
438                 printf( "%s\n", a );
439             }
440         } else if (( bvals = ldap_get_values_len( ld, entry, a )) != NULL ) {
441             for ( i = 0; bvals[i] != NULL; i++ ) {
442                 if ( vals2tmp ) {
443                     sprintf( tmpfname, "/tmp/ldapsearch-%s-XXXXXX", a );
444                     tmpfp = NULL;
445
446                     if ( mktemp( tmpfname ) == NULL ) {
447                         perror( tmpfname );
448                     } else if (( tmpfp = fopen( tmpfname, "w")) == NULL ) {
449                         perror( tmpfname );
450                     } else if ( fwrite( bvals[ i ]->bv_val,
451                             bvals[ i ]->bv_len, 1, tmpfp ) == 0 ) {
452                         perror( tmpfname );
453                     } else if ( ldif ) {
454                         write_ldif_value( a, tmpfname, strlen( tmpfname ));
455                     } else {
456                         printf( "%s%s%s\n", a, sep, tmpfname );
457                     }
458
459                     if ( tmpfp != NULL ) {
460                         fclose( tmpfp );
461                     }
462                 } else {
463                     notascii = 0;
464                     if ( !allow_binary ) {
465                         for ( j = 0; (unsigned long) j < bvals[ i ]->bv_len; ++j ) {
466                             if ( !isascii( bvals[ i ]->bv_val[ j ] )) {
467                                 notascii = 1;
468                                 break;
469                             }
470                         }
471                     }
472
473                     if ( ldif ) {
474                         write_ldif_value( a, bvals[ i ]->bv_val,
475                                 bvals[ i ]->bv_len );
476                     } else {
477                         printf( "%s%s%s\n", a, sep,
478                                 notascii ? "NOT ASCII" : bvals[ i ]->bv_val );
479                     }
480                 }
481             }
482             ber_bvecfree( bvals );
483         }
484     }
485 }
486
487
488 int
489 write_ldif_value( char *type, char *value, unsigned long vallen )
490 {
491     char        *ldif;
492
493     if (( ldif = ldif_type_and_value( type, value, (int)vallen )) == NULL ) {
494         return( -1 );
495     }
496
497     fputs( ldif, stdout );
498     free( ldif );
499
500     return( 0 );
501 }