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