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