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