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