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