]> git.sur5r.net Git - openldap/blob - clients/tools/ldapcompare.c
f2e06e6e4c7a5d32716f1551cede8a5cdf0d45ce
[openldap] / clients / tools / ldapcompare.c
1 /*
2  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* $OpenLDAP$
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 #include <ac/errno.h>
18 #include <sys/stat.h>
19
20 #ifdef HAVE_FCNTL_H
21 #include <fcntl.h>
22 #endif
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #ifdef HAVE_IO_H
27 #include <io.h>
28 #endif
29
30 #include <ldap.h>
31
32 #include "ldif.h"
33 #include "lutil.h"
34 #include "lutil_ldap.h"
35 #include "ldap_defaults.h"
36
37 static void
38 usage( const char *s )
39 {
40         fprintf( stderr,
41 "usage: %s [options] DN <attr:value|attr::b64value>\n"
42 "where:\n"
43 "  DN\tDistinguished Name\n"
44 "  attr\tassertion attribute\n"
45 "  value\tassertion value\n"
46 "  b64value\tbase64 encoding of assertion value\n"
47
48 "Common options:\n"
49 "  -d level   set LDAP debugging level to `level'\n"
50 "  -D binddn  bind DN\n"
51 "  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
52 "             [!]manageDSAit   (alternate form, see -M)\n"
53 "             [!]noop\n"
54 "  -h host    LDAP server\n"
55 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
56 "  -I         use SASL Interactive mode\n"
57 "  -k         use Kerberos authentication\n"
58 "  -K         like -k, but do only step 1 of the Kerberos bind\n"
59 "  -M         enable Manage DSA IT control (-MM to make critical)\n"
60 "  -n         show what would be done but don't actually compare\n"
61 "  -O props   SASL security properties\n"
62 "  -p port    port on LDAP server\n"
63 "  -P version procotol version (default: 3)\n"
64 "  -z         Quiet mode, don't print anything, use return values\n"
65 "  -Q         use SASL Quiet mode\n"
66 "  -R realm   SASL realm\n"
67 "  -U authcid SASL authentication identity\n"
68 "  -v         run in verbose mode (diagnostics to standard output)\n"
69 "  -w passwd  bind passwd (for simple authentication)\n"
70 "  -W         prompt for bind passwd\n"
71 "  -x         Simple authentication\n"
72 "  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
73 "  -y file    Read passwd from file\n"
74 "  -Y mech    SASL mechanism\n"
75 "  -Z         Start TLS request (-ZZ to require successful response)\n"
76 , s );
77
78         exit( EXIT_FAILURE );
79 }
80
81 static int docompare LDAP_P((
82         LDAP *ld,
83         char *dn,
84         char *attr,
85         struct berval *bvalue,
86         int quiet,
87         LDAPControl **sctrls,
88         LDAPControl **cctrls));
89
90 static char *prog = NULL;
91 static char     *binddn = NULL;
92 static struct berval passwd = { 0, NULL };
93 static char     *ldaphost = NULL;
94 static char *ldapuri = NULL;
95 static int      ldapport = 0;
96 #ifdef HAVE_CYRUS_SASL
97 static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
98 static char     *sasl_realm = NULL;
99 static char     *sasl_authc_id = NULL;
100 static char     *sasl_authz_id = NULL;
101 static char     *sasl_mech = NULL;
102 static char     *sasl_secprops = NULL;
103 #endif
104 static int      use_tls = 0;
105 static int      verbose, not;
106
107 int
108 main( int argc, char **argv )
109 {
110         char    *compdn = NULL, *attrs = NULL;
111         char    *sep;
112         int             rc, i, crit, manageDSAit, noop, quiet;
113         int             referrals, debug;
114         int             authmethod, version, want_bindpw;
115         LDAP    *ld = NULL;
116         struct berval bvalue = { 0, NULL };
117         char    *pw_file = NULL;
118         char    *control, *cvalue;
119
120         debug = verbose = not = referrals = noop =
121                 manageDSAit = want_bindpw = quiet = 0;
122
123         version = -1;
124
125         authmethod = -1;
126
127         prog = lutil_progname( "ldapcompare", argc, argv );
128
129         while (( i = getopt( argc, argv,
130                 "Cd:D:e:h:H:IkKMnO:p:P:qQR:U:vw:WxX:y:Y:zZ")) != EOF )
131         {
132                 switch( i ) {
133         case 'E': /* compare controls */
134                 if( version == LDAP_VERSION2 ) {
135                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
136                                 prog, version );
137                         return EXIT_FAILURE;
138                 }
139
140                 /* should be extended to support comma separated list of
141                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
142                  */
143
144                 crit = 0;
145                 cvalue = NULL;
146                 if( optarg[0] == '!' ) {
147                         crit = 1;
148                         optarg++;
149                 }
150
151                 control = strdup( optarg );
152                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
153                         *cvalue++ = '\0';
154                 }
155                 fprintf( stderr, "Invalid compare control name: %s\n", control );
156                 usage(prog);
157                 return EXIT_FAILURE;
158
159                 /* Common Options */
160                 case 'C':
161                         referrals++;
162                         break;
163                 case 'd':
164                         debug |= atoi( optarg );
165                         break;
166                 case 'D':       /* bind DN */
167                         if( binddn != NULL ) {
168                                 fprintf( stderr, "%s: -D previously specified\n", prog );
169                                 return EXIT_FAILURE;
170                         }
171                         binddn = strdup( optarg );
172                         break;
173
174         case 'e': /* general controls */
175                 if( version == LDAP_VERSION2 ) {
176                         fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
177                                 prog, version );
178                         return EXIT_FAILURE;
179                 }
180
181                 /* should be extended to support comma separated list of
182                  *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
183                  */
184
185                 crit = 0;
186                 cvalue = NULL;
187                 if( optarg[0] == '!' ) {
188                         crit = 1;
189                         optarg++;
190                 }
191
192                 control = strdup( optarg );
193                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
194                         *cvalue++ = '\0';
195                 }
196
197                 if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
198                         if( cvalue != NULL ) {
199                                 fprintf( stderr, "manageDSAit: no control value expected" );
200                                 usage(prog);
201                                 return EXIT_FAILURE;
202                         }
203
204                         manageDSAit = 1 + crit;
205                         free( control );
206                         break;
207                         
208                 } else if ( strcasecmp( control, "noop" ) == 0 ) {
209                         if( cvalue != NULL ) {
210                                 fprintf( stderr, "noop: no control value expected" );
211                                 usage(prog);
212                                 return EXIT_FAILURE;
213                         }
214
215                         noop = 1 + crit;
216                         free( control );
217                         break;
218
219                 } else {
220                         fprintf( stderr, "Invalid general control name: %s\n", control );
221                         usage(prog);
222                         return EXIT_FAILURE;
223                 }
224                 case 'h':       /* ldap host */
225                         if( ldapuri != NULL ) {
226                                 fprintf( stderr, "%s: -h incompatible with -H\n", prog );
227                                 return EXIT_FAILURE;
228                         }
229                         if( ldaphost != NULL ) {
230                                 fprintf( stderr, "%s: -h previously specified\n", prog );
231                                 return EXIT_FAILURE;
232                         }
233                         ldaphost = strdup( optarg );
234                         break;
235                 case 'H':       /* ldap URI */
236                         if( ldaphost != NULL ) {
237                                 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
238                                 return EXIT_FAILURE;
239                         }
240                         if( ldapport ) {
241                                 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
242                                 return EXIT_FAILURE;
243                         }
244                         if( ldapuri != NULL ) {
245                                 fprintf( stderr, "%s: -H previously specified\n", prog );
246                                 return EXIT_FAILURE;
247                         }
248                         ldapuri = strdup( optarg );
249                         break;
250                 case 'I':
251 #ifdef HAVE_CYRUS_SASL
252                         if( version == LDAP_VERSION2 ) {
253                                 fprintf( stderr, "%s: -I incompatible with version %d\n",
254                                         prog, version );
255                                 return EXIT_FAILURE;
256                         }
257                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
258                                 fprintf( stderr, "%s: incompatible previous "
259                                         "authentication choice\n",
260                                         prog );
261                                 return EXIT_FAILURE;
262                         }
263                         authmethod = LDAP_AUTH_SASL;
264                         version = LDAP_VERSION3;
265                         sasl_flags = LDAP_SASL_INTERACTIVE;
266                         break;
267 #else
268                         fprintf( stderr, "%s: was not compiled with SASL support\n",
269                                 prog );
270                         return( EXIT_FAILURE );
271 #endif
272                 case 'k':       /* kerberos bind */
273 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
274                         if( version > LDAP_VERSION2 ) {
275                                 fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
276                                         prog, version );
277                                 return EXIT_FAILURE;
278                         }
279
280                         if( authmethod != -1 ) {
281                                 fprintf( stderr, "%s: -k incompatible with previous "
282                                         "authentication choice\n", prog );
283                                 return EXIT_FAILURE;
284                         }
285
286                         authmethod = LDAP_AUTH_KRBV4;
287 #else
288                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
289                         return EXIT_FAILURE;
290 #endif
291                         break;
292                 case 'K':       /* kerberos bind, part one only */
293 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
294                         if( version > LDAP_VERSION2 ) {
295                                 fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
296                                         prog, version );
297                                 return EXIT_FAILURE;
298                         }
299                         if( authmethod != -1 ) {
300                                 fprintf( stderr, "%s: incompatible with previous "
301                                         "authentication choice\n", prog );
302                                 return EXIT_FAILURE;
303                         }
304
305                         authmethod = LDAP_AUTH_KRBV41;
306 #else
307                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
308                         return( EXIT_FAILURE );
309 #endif
310                         break;
311                 case 'M':
312                         /* enable Manage DSA IT */
313                         if( version == LDAP_VERSION2 ) {
314                                 fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
315                                         prog, version );
316                                 return EXIT_FAILURE;
317                         }
318                         manageDSAit++;
319                         version = LDAP_VERSION3;
320                         break;
321                 case 'n':       /* print compares, don't actually do them */
322                         ++not;
323                         break;
324                 case 'O':
325 #ifdef HAVE_CYRUS_SASL
326                         if( sasl_secprops != NULL ) {
327                                 fprintf( stderr, "%s: -O previously specified\n", prog );
328                                 return EXIT_FAILURE;
329                         }
330                         if( version == LDAP_VERSION2 ) {
331                                 fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
332                                         prog, version );
333                                 return EXIT_FAILURE;
334                         }
335                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
336                                 fprintf( stderr, "%s: incompatible previous "
337                                         "authentication choice\n", prog );
338                                 return EXIT_FAILURE;
339                         }
340                         authmethod = LDAP_AUTH_SASL;
341                         version = LDAP_VERSION3;
342                         sasl_secprops = strdup( optarg );
343 #else
344                         fprintf( stderr, "%s: not compiled with SASL support\n",
345                                 prog );
346                         return( EXIT_FAILURE );
347 #endif
348                         break;
349                 case 'p':
350                         if( ldapport ) {
351                                 fprintf( stderr, "%s: -p previously specified\n", prog );
352                                 return EXIT_FAILURE;
353                         }
354                         ldapport = atoi( optarg );
355                         break;
356                 case 'P':
357                         switch( atoi(optarg) ) {
358                         case 2:
359                                 if( version == LDAP_VERSION3 ) {
360                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
361                                                 prog, version );
362                                         return EXIT_FAILURE;
363                                 }
364                                 version = LDAP_VERSION2;
365                                 break;
366                         case 3:
367                                 if( version == LDAP_VERSION2 ) {
368                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
369                                                 prog, version );
370                                         return EXIT_FAILURE;
371                                 }
372                                 version = LDAP_VERSION3;
373                                 break;
374                         default:
375                                 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
376                                         prog );
377                                 usage( prog );
378                                 return( EXIT_FAILURE );
379                         } break;
380                 case 'Q':
381 #ifdef HAVE_CYRUS_SASL
382                         if( version == LDAP_VERSION2 ) {
383                                 fprintf( stderr, "%s: -Q incompatible with version %d\n",
384                                         prog, version );
385                                 return EXIT_FAILURE;
386                         }
387                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
388                                 fprintf( stderr, "%s: incompatible previous "
389                                         "authentication choice\n",
390                                         prog );
391                                 return EXIT_FAILURE;
392                         }
393                         authmethod = LDAP_AUTH_SASL;
394                         version = LDAP_VERSION3;
395                         sasl_flags = LDAP_SASL_QUIET;
396                         break;
397 #else
398                         fprintf( stderr, "%s: not compiled with SASL support\n",
399                                 prog );
400                         return( EXIT_FAILURE );
401 #endif
402                 case 'R':
403 #ifdef HAVE_CYRUS_SASL
404                         if( sasl_realm != NULL ) {
405                                 fprintf( stderr, "%s: -R previously specified\n", prog );
406                                 return EXIT_FAILURE;
407                         }
408                         if( version == LDAP_VERSION2 ) {
409                                 fprintf( stderr, "%s: -R incompatible with version %d\n",
410                                         prog, version );
411                                 return EXIT_FAILURE;
412                         }
413                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
414                                 fprintf( stderr, "%s: incompatible previous "
415                                         "authentication choice\n",
416                                         prog );
417                                 return EXIT_FAILURE;
418                         }
419                         authmethod = LDAP_AUTH_SASL;
420                         version = LDAP_VERSION3;
421                         sasl_realm = strdup( optarg );
422 #else
423                         fprintf( stderr, "%s: not compiled with SASL support\n",
424                                 prog );
425                         return( EXIT_FAILURE );
426 #endif
427                         break;
428         case 'U':
429 #ifdef HAVE_CYRUS_SASL
430                         if( sasl_authc_id != NULL ) {
431                                 fprintf( stderr, "%s: -U previously specified\n", prog );
432                                 return EXIT_FAILURE;
433                         }
434                         if( version == LDAP_VERSION2 ) {
435                                 fprintf( stderr, "%s: -U incompatible with version %d\n",
436                                         prog, version );
437                                 return EXIT_FAILURE;
438                         }
439                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
440                                 fprintf( stderr, "%s: incompatible previous "
441                                         "authentication choice\n",
442                                         prog );
443                                 return EXIT_FAILURE;
444                         }
445                         authmethod = LDAP_AUTH_SASL;
446                         version = LDAP_VERSION3;
447                         sasl_authc_id = strdup( optarg );
448 #else
449                         fprintf( stderr, "%s: not compiled with SASL support\n",
450                                 prog );
451                         return( EXIT_FAILURE );
452 #endif
453                         break;
454                 case 'v':       /* verbose mode */
455                         verbose++;
456                         break;
457                 case 'w':       /* password */
458                         passwd.bv_val = strdup( optarg );
459                         {
460                                 char* p;
461
462                                 for( p = optarg; *p != '\0'; p++ ) {
463                                         *p = '\0';
464                                 }
465                         }
466                         passwd.bv_len = strlen( passwd.bv_val );
467                         break;
468                 case 'W':
469                         want_bindpw++;
470                         break;
471                 case 'y':
472                         pw_file = optarg;
473                         break;
474                 case 'Y':
475 #ifdef HAVE_CYRUS_SASL
476                         if( sasl_mech != NULL ) {
477                                 fprintf( stderr, "%s: -Y previously specified\n", prog );
478                                 return EXIT_FAILURE;
479                         }
480                         if( version == LDAP_VERSION2 ) {
481                                 fprintf( stderr, "%s: -Y incompatible with version %d\n",
482                                         prog, version );
483                                 return EXIT_FAILURE;
484                         }
485                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
486                                 fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
487                                 return EXIT_FAILURE;
488                         }
489                         authmethod = LDAP_AUTH_SASL;
490                         version = LDAP_VERSION3;
491                         sasl_mech = strdup( optarg );
492 #else
493                         fprintf( stderr, "%s: not compiled with SASL support\n",
494                                 prog );
495                         return( EXIT_FAILURE );
496 #endif
497                         break;
498                 case 'x':
499                         if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
500                                 fprintf( stderr, "%s: incompatible with previous "
501                                         "authentication choice\n", prog );
502                                 return EXIT_FAILURE;
503                         }
504                         authmethod = LDAP_AUTH_SIMPLE;
505                         break;
506                 case 'X':
507 #ifdef HAVE_CYRUS_SASL
508                         if( sasl_authz_id != NULL ) {
509                                 fprintf( stderr, "%s: -X previously specified\n", prog );
510                                 return EXIT_FAILURE;
511                         }
512                         if( version == LDAP_VERSION2 ) {
513                                 fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
514                                         prog, version );
515                                 return EXIT_FAILURE;
516                         }
517                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
518                                 fprintf( stderr, "%s: -X incompatible with "
519                                         "authentication choice\n", prog );
520                                 return EXIT_FAILURE;
521                         }
522                         authmethod = LDAP_AUTH_SASL;
523                         version = LDAP_VERSION3;
524                         sasl_authz_id = strdup( optarg );
525 #else
526                         fprintf( stderr, "%s: not compiled with SASL support\n",
527                                 prog );
528                         return( EXIT_FAILURE );
529 #endif
530                         break;
531                 case 'z':
532                         quiet++;
533                         break;
534                 case 'Z':
535 #ifdef HAVE_TLS
536                         if( version == LDAP_VERSION2 ) {
537                                 fprintf( stderr, "%s: -Z incompatible with version %d\n",
538                                         prog, version );
539                                 return EXIT_FAILURE;
540                         }
541                         version = LDAP_VERSION3;
542                         use_tls++;
543 #else
544                         fprintf( stderr, "%s: not compiled with TLS support\n",
545                                 prog );
546                         return( EXIT_FAILURE );
547 #endif
548                         break;
549                 default:
550                         fprintf( stderr, "%s: unrecognized option -%c\n",
551                                 prog, optopt );
552                         usage( argv[0] );
553                 }
554         }
555
556         if (version == -1) {
557                 version = LDAP_VERSION3;
558         }
559         if (authmethod == -1 && version > LDAP_VERSION2) {
560 #ifdef HAVE_CYRUS_SASL
561                 authmethod = LDAP_AUTH_SASL;
562 #else
563                 authmethod = LDAP_AUTH_SIMPLE;
564 #endif
565         }
566
567         if ( argc - optind != 2 ) {
568                 usage( argv[ 0 ] );
569         }
570
571         compdn = argv[optind++];
572         attrs = argv[optind++];
573
574         /* user passed in only 2 args, the last one better be in
575          * the form attr:value or attr::b64value
576          */
577         sep = strchr(attrs, ':');
578         if (!sep) {
579                 usage( argv[ 0 ] );
580         }
581
582         *sep++='\0';
583         if ( *sep != ':' ) {
584                 bvalue.bv_val = strdup( sep );
585                 bvalue.bv_len = strlen( bvalue.bv_val );
586
587         } else {
588                 /* it's base64 encoded. */
589                 bvalue.bv_val = malloc( strlen( &sep[1] ));
590                 bvalue.bv_len = lutil_b64_pton( &sep[1],
591                         bvalue.bv_val, strlen( &sep[1] ));
592
593                 if (bvalue.bv_len == -1) {
594                         fprintf(stderr, "base64 decode error\n");
595                         exit(-1);
596                 }
597         }
598
599         if ( debug ) {
600                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
601                         != LBER_OPT_SUCCESS )
602                 {
603                         fprintf( stderr,
604                                 "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
605                 }
606                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
607                         != LDAP_OPT_SUCCESS )
608                 {
609                         fprintf( stderr,
610                                 "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
611                 }
612                 ldif_debug = debug;
613         }
614
615 #ifdef SIGPIPE
616         (void) SIGNAL( SIGPIPE, SIG_IGN );
617 #endif
618
619         if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
620                 if ( verbose ) {
621                         fprintf( stderr, "ldap_init( %s, %d )\n",
622                                 ldaphost != NULL ? ldaphost : "<DEFAULT>",
623                                 ldapport );
624                 }
625
626                 ld = ldap_init( ldaphost, ldapport );
627                 if( ld == NULL ) {
628                         perror("ldapcompare: ldap_init");
629                         return EXIT_FAILURE;
630                 }
631
632         } else {
633                 if ( verbose ) {
634                         fprintf( stderr, "ldap_initialize( %s )\n",
635                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
636                 }
637
638                 rc = ldap_initialize( &ld, ldapuri );
639                 if( rc != LDAP_SUCCESS ) {
640                         fprintf( stderr,
641                                 "Could not create LDAP session handle (%d): %s\n",
642                                 rc, ldap_err2string(rc) );
643                         return EXIT_FAILURE;
644                 }
645         }
646
647
648         /* referrals */
649         if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
650                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
651         {
652                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
653                         referrals ? "on" : "off" );
654                 return EXIT_FAILURE;
655         }
656
657         if (version == -1 ) {
658                 version = LDAP_VERSION3;
659         }
660
661         if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
662                 != LDAP_OPT_SUCCESS )
663         {
664                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
665                         version );
666                 return EXIT_FAILURE;
667         }
668
669         if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
670                 ldap_perror( ld, "ldap_start_tls" );
671                 if ( use_tls > 1 ) {
672                         return EXIT_FAILURE;
673                 }
674         }
675
676         if ( pw_file || want_bindpw ) {
677                 if ( pw_file ) {
678                         rc = lutil_get_filed_password( pw_file, &passwd );
679                         if( rc ) return EXIT_FAILURE;
680                 } else {
681                         passwd.bv_val = getpassphrase( "Enter LDAP Password: " );
682                         passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
683                 }
684         }
685
686         if ( authmethod == LDAP_AUTH_SASL ) {
687 #ifdef HAVE_CYRUS_SASL
688                 void *defaults;
689
690                 if( sasl_secprops != NULL ) {
691                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
692                                 (void *) sasl_secprops );
693
694                         if( rc != LDAP_OPT_SUCCESS ) {
695                                 fprintf( stderr,
696                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
697                                         sasl_secprops );
698                                 return EXIT_FAILURE;
699                         }
700                 }
701
702                 defaults = lutil_sasl_defaults( ld,
703                         sasl_mech,
704                         sasl_realm,
705                         sasl_authc_id,
706                         passwd.bv_val,
707                         sasl_authz_id );
708
709                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
710                         sasl_mech, NULL, NULL,
711                         sasl_flags, lutil_sasl_interact, defaults );
712
713                 if( rc != LDAP_SUCCESS ) {
714                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
715                         return EXIT_FAILURE;
716                 }
717 #else
718                 fprintf( stderr, "%s: not compiled with SASL support\n",
719                         prog, argv[0] );
720                 return EXIT_FAILURE;
721 #endif
722         } else {
723                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
724                                 != LDAP_SUCCESS ) {
725                         ldap_perror( ld, "ldap_bind" );
726                         return EXIT_FAILURE;
727                 }
728         }
729
730         if ( manageDSAit || noop ) {
731                 int err, i = 0;
732                 LDAPControl c1, c2;
733                 LDAPControl *ctrls[3];
734
735                 if ( manageDSAit ) {
736                         ctrls[i++] = &c1;
737                         ctrls[i] = NULL;
738                         c1.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
739                         c1.ldctl_value.bv_val = NULL;
740                         c1.ldctl_value.bv_len = 0;
741                         c1.ldctl_iscritical = manageDSAit > 1;
742                 }
743
744                 if ( noop ) {
745                         ctrls[i++] = &c2;
746                         ctrls[i] = NULL;
747
748                         c2.ldctl_oid = LDAP_CONTROL_NOOP;
749                         c2.ldctl_value.bv_val = NULL;
750                         c2.ldctl_value.bv_len = 0;
751                         c2.ldctl_iscritical = noop > 1;
752                 }
753         
754                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
755
756                 if( err != LDAP_OPT_SUCCESS ) {
757                         fprintf( stderr, "Could not set %scontrols\n",
758                                 (c1.ldctl_iscritical || c2.ldctl_iscritical)
759                                 ? "critical " : "" );
760                         if ( c1.ldctl_iscritical && c2.ldctl_iscritical ) {
761                                 return EXIT_FAILURE;
762                         }
763                 }
764         }
765
766         if ( verbose ) {
767                 fprintf( stderr, "DN:%s, attr:%s, value:%s\n",
768                         compdn, attrs, sep );
769         }
770
771         rc = docompare( ld, compdn, attrs, &bvalue, quiet, NULL, NULL );
772
773         free( bvalue.bv_val );
774
775         ldap_unbind( ld );
776
777         return rc;
778 }
779
780
781 static int docompare(
782         LDAP *ld,
783         char *dn,
784         char *attr,
785         struct berval *bvalue,
786         int quiet,
787         LDAPControl **sctrls,
788         LDAPControl **cctrls )
789 {
790         int                     rc;
791
792         if ( not ) {
793                 return LDAP_SUCCESS;
794         }
795
796         rc = ldap_compare_ext_s( ld, dn, attr, bvalue,
797                 sctrls, cctrls );
798
799         if ( rc == -1 ) {
800                 ldap_perror( ld, "ldap_result" );
801                 return( rc );
802         }
803
804         /* if we were told to be quiet, use the return value. */
805         if ( !quiet ) {
806                 if ( rc == LDAP_COMPARE_TRUE ) {
807                         rc = 0;
808                         printf("TRUE\n");
809                 } else if ( rc == LDAP_COMPARE_FALSE ) {
810                         rc = 0;
811                         printf("FALSE\n");
812                 } else {
813                         ldap_perror( ld, "ldap_compare" );
814                 }
815         }
816
817         return( rc );
818 }
819