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