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