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