]> git.sur5r.net Git - openldap/blob - clients/tools/common.c
Improve error reporting
[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, ival;
151                 char *control, *cvalue, *next;
152                 switch( i ) {
153                 case 'c':       /* continuous operation mode */
154                         contoper++;
155                         break;
156                 case 'C':
157                         referrals++;
158                         break;
159                 case 'd':
160                         ival = strtol( optarg, &next, 10 );
161                         if (next == NULL || next[0] != '\0') {
162                                 fprintf( stderr, "%s: unable to parse debug value \"%s\"\n", prog, optarg);
163                                 exit(EXIT_FAILURE);
164                         }
165                         debug |= ival;
166                         break;
167                 case 'D':       /* bind DN */
168                         if( binddn != NULL ) {
169                                 fprintf( stderr, "%s: -D previously specified\n", prog );
170                                 exit( EXIT_FAILURE );
171                         }
172                         binddn = ber_strdup( optarg );
173                         break;
174                 case 'e': /* general extensions (controls and such) */
175                         /* should be extended to support comma separated list of
176                          *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
177                          */
178
179                         crit = 0;
180                         cvalue = NULL;
181                         if( optarg[0] == '!' ) {
182                                 crit = 1;
183                                 optarg++;
184                         }
185
186                         control = ber_strdup( optarg );
187                         if ( (cvalue = strchr( control, '=' )) != NULL ) {
188                                 *cvalue++ = '\0';
189                         }
190
191                         if ( strcasecmp( control, "assert" ) == 0 ) {
192                                 if( assertctl ) {
193                                         fprintf( stderr, "assert control previously specified\n");
194                                         exit( EXIT_FAILURE );
195                                 }
196                                 if( cvalue == NULL ) {
197                                         fprintf( stderr, "assert: control value expected\n" );
198                                         usage();
199                                 }
200
201                                 assertctl = 1 + crit;
202
203                                 assert( assertion == NULL );
204                                 assertion = cvalue;
205
206                         } else if ( strcasecmp( control, "authzid" ) == 0 ) {
207                                 if( authzid != NULL ) {
208                                         fprintf( stderr, "authzid control previously specified\n");
209                                         exit( EXIT_FAILURE );
210                                 }
211                                 if( cvalue == NULL ) {
212                                         fprintf( stderr, "authzid: control value expected\n" );
213                                         usage();
214                                 }
215                                 if( !crit ) {
216                                         fprintf( stderr, "authzid: must be marked critical\n" );
217                                         usage();
218                                 }
219
220                                 assert( authzid == NULL );
221                                 authzid = cvalue;
222
223                         } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
224                                 if( manageDSAit ) {
225                                         fprintf( stderr,
226                                                 "manageDSAit control previously specified\n");
227                                         exit( EXIT_FAILURE );
228                                 }
229                                 if( cvalue != NULL ) {
230                                         fprintf( stderr,
231                                                 "manageDSAit: no control value expected\n" );
232                                         usage();
233                                 }
234
235                                 manageDSAit = 1 + crit;
236
237                         } else if ( strcasecmp( control, "noop" ) == 0 ) {
238                                 if( noop ) {
239                                         fprintf( stderr, "noop control previously specified\n");
240                                         exit( EXIT_FAILURE );
241                                 }
242                                 if( cvalue != NULL ) {
243                                         fprintf( stderr, "noop: no control value expected\n" );
244                                         usage();
245                                 }
246
247                                 noop = 1 + crit;
248
249                         } else if ( strcasecmp( control, "preread" ) == 0 ) {
250                                 if( preread ) {
251                                         fprintf( stderr, "preread control previously specified\n");
252                                         exit( EXIT_FAILURE );
253                                 }
254
255                                 preread = 1 + crit;
256                                 preread_attrs = cvalue;
257
258                         } else if ( strcasecmp( control, "postread" ) == 0 ) {
259                                 if( postread ) {
260                                         fprintf( stderr, "postread control previously specified\n");
261                                         exit( EXIT_FAILURE );
262                                 }
263
264                                 postread = 1 + crit;
265                                 postread_attrs = cvalue;
266
267                         } else {
268                                 fprintf( stderr, "Invalid general control name: %s\n",
269                                         control );
270                                 usage();
271                         }
272                         break;
273                 case 'f':       /* read from file */
274                         if( infile != NULL ) {
275                                 fprintf( stderr, "%s: -f previously specified\n", prog );
276                                 exit( EXIT_FAILURE );
277                         }
278                         infile = ber_strdup( optarg );
279                         break;
280                 case 'h':       /* ldap host */
281                         if( ldaphost != NULL ) {
282                                 fprintf( stderr, "%s: -h previously specified\n", prog );
283                                 exit( EXIT_FAILURE );
284                         }
285                         ldaphost = ber_strdup( optarg );
286                         break;
287                 case 'H':       /* ldap URI */
288                         if( ldapuri != NULL ) {
289                                 fprintf( stderr, "%s: -H previously specified\n", prog );
290                                 exit( EXIT_FAILURE );
291                         }
292                         ldapuri = ber_strdup( optarg );
293                         break;
294                 case 'I':
295 #ifdef HAVE_CYRUS_SASL
296                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
297                                 fprintf( stderr, "%s: incompatible previous "
298                                         "authentication choice\n",
299                                         prog );
300                                 exit( EXIT_FAILURE );
301                         }
302                         authmethod = LDAP_AUTH_SASL;
303                         sasl_flags = LDAP_SASL_INTERACTIVE;
304                         break;
305 #else
306                         fprintf( stderr, "%s: was not compiled with SASL support\n",
307                                 prog );
308                         exit( EXIT_FAILURE );
309 #endif
310                 case 'k':       /* kerberos bind */
311 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
312                         if( authmethod != -1 ) {
313                                 fprintf( stderr, "%s: -k incompatible with previous "
314                                         "authentication choice\n", prog );
315                                 exit( EXIT_FAILURE );
316                         }
317                         authmethod = LDAP_AUTH_KRBV4;
318 #else
319                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
320                         exit( EXIT_FAILURE );
321 #endif
322                         break;
323                 case 'K':       /* kerberos bind, part one only */
324 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
325                         if( authmethod != -1 ) {
326                                 fprintf( stderr, "%s: incompatible with previous "
327                                         "authentication choice\n", prog );
328                                 exit( EXIT_FAILURE );
329                         }
330                         authmethod = LDAP_AUTH_KRBV41;
331 #else
332                         fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
333                         exit( EXIT_FAILURE );
334 #endif
335                         break;
336                 case 'M':
337                         /* enable Manage DSA IT */
338                         manageDSAit++;
339                         break;
340                 case 'n':       /* print operations, don't actually do them */
341                         not++;
342                         break;
343                 case 'O':
344 #ifdef HAVE_CYRUS_SASL
345                         if( sasl_secprops != NULL ) {
346                                 fprintf( stderr, "%s: -O previously specified\n", prog );
347                                 exit( EXIT_FAILURE );
348                         }
349                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
350                                 fprintf( stderr, "%s: incompatible previous "
351                                         "authentication choice\n", prog );
352                                 exit( EXIT_FAILURE );
353                         }
354                         authmethod = LDAP_AUTH_SASL;
355                         sasl_secprops = ber_strdup( optarg );
356 #else
357                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
358                         exit( EXIT_FAILURE );
359 #endif
360                         break;
361                 case 'p':
362                         if( ldapport ) {
363                                 fprintf( stderr, "%s: -p previously specified\n", prog );
364                                 exit( EXIT_FAILURE );
365                         }
366                         ival = strtol( optarg, &next, 10 );
367                         if ( next == NULL || next[0] != '\0' ) {
368                                 fprintf( stderr, "%s: unable to parse port number \"%s\"\n", prog, optarg );
369                                 exit( EXIT_FAILURE );
370                         }
371                         ldapport = ival;
372                         break;
373                 case 'P':
374                         ival = strtol( optarg, &next, 10 );
375                         if ( next == NULL || next[0] != '\0' ) {
376                                 fprintf( stderr, "%s: unabel to parse protocol version \"%s\"\n", prog, optarg );
377                                 exit( EXIT_FAILURE );
378                         }
379                         switch( ival ) {
380                         case 2:
381                                 if( protocol == LDAP_VERSION3 ) {
382                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
383                                                 prog, protocol );
384                                         exit( EXIT_FAILURE );
385                                 }
386                                 protocol = LDAP_VERSION2;
387                                 break;
388                         case 3:
389                                 if( protocol == LDAP_VERSION2 ) {
390                                         fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
391                                                 prog, protocol );
392                                         exit( EXIT_FAILURE );
393                                 }
394                                 protocol = LDAP_VERSION3;
395                                 break;
396                         default:
397                                 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
398                                         prog );
399                                 usage();
400                         }
401                         break;
402                 case 'Q':
403 #ifdef HAVE_CYRUS_SASL
404                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
405                                 fprintf( stderr, "%s: incompatible previous "
406                                         "authentication choice\n",
407                                         prog );
408                                 exit( EXIT_FAILURE );
409                         }
410                         authmethod = LDAP_AUTH_SASL;
411                         sasl_flags = LDAP_SASL_QUIET;
412                         break;
413 #else
414                         fprintf( stderr, "%s: not compiled with SASL support\n",
415                                 prog );
416                         exit( EXIT_FAILURE );
417 #endif
418                 case 'R':
419 #ifdef HAVE_CYRUS_SASL
420                         if( sasl_realm != NULL ) {
421                                 fprintf( stderr, "%s: -R previously specified\n", prog );
422                                 exit( EXIT_FAILURE );
423                         }
424                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
425                                 fprintf( stderr, "%s: incompatible previous "
426                                         "authentication choice\n",
427                                         prog );
428                                 exit( EXIT_FAILURE );
429                         }
430                         authmethod = LDAP_AUTH_SASL;
431                         sasl_realm = ber_strdup( optarg );
432 #else
433                         fprintf( stderr, "%s: not compiled with SASL support\n",
434                                 prog );
435                         exit( EXIT_FAILURE );
436 #endif
437                         break;
438                 case 'U':
439 #ifdef HAVE_CYRUS_SASL
440                         if( sasl_authc_id != NULL ) {
441                                 fprintf( stderr, "%s: -U previously specified\n", prog );
442                                 exit( EXIT_FAILURE );
443                         }
444                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
445                                 fprintf( stderr, "%s: incompatible previous "
446                                         "authentication choice\n",
447                                         prog );
448                                 exit( EXIT_FAILURE );
449                         }
450                         authmethod = LDAP_AUTH_SASL;
451                         sasl_authc_id = ber_strdup( optarg );
452 #else
453                         fprintf( stderr, "%s: not compiled with SASL support\n",
454                                 prog );
455                         exit( EXIT_FAILURE );
456 #endif
457                         break;
458                 case 'v':       /* verbose mode */
459                         verbose++;
460                         break;
461                 case 'V':       /* version */
462                         version++;
463                         break;
464                 case 'w':       /* password */
465                         passwd.bv_val = ber_strdup( optarg );
466                         {
467                                 char* p;
468
469                                 for( p = optarg; *p != '\0'; p++ ) {
470                                         *p = '\0';
471                                 }
472                         }
473                         passwd.bv_len = strlen( passwd.bv_val );
474                         break;
475                 case 'W':
476                         want_bindpw++;
477                         break;
478                 case 'y':
479                         pw_file = optarg;
480                         break;
481                 case 'Y':
482 #ifdef HAVE_CYRUS_SASL
483                         if( sasl_mech != NULL ) {
484                                 fprintf( stderr, "%s: -Y previously specified\n", prog );
485                                 exit( EXIT_FAILURE );
486                         }
487                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
488                                 fprintf( stderr,
489                                         "%s: incompatible with authentication choice\n", prog );
490                                 exit( EXIT_FAILURE );
491                         }
492                         authmethod = LDAP_AUTH_SASL;
493                         sasl_mech = ber_strdup( optarg );
494 #else
495                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
496                         exit( EXIT_FAILURE );
497 #endif
498                         break;
499                 case 'x':
500                         if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
501                                 fprintf( stderr, "%s: incompatible with previous "
502                                         "authentication choice\n", prog );
503                                 exit( EXIT_FAILURE );
504                         }
505                         authmethod = LDAP_AUTH_SIMPLE;
506                         break;
507                 case 'X':
508 #ifdef HAVE_CYRUS_SASL
509                         if( sasl_authz_id != NULL ) {
510                                 fprintf( stderr, "%s: -X previously specified\n", prog );
511                                 exit( EXIT_FAILURE );
512                         }
513                         if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
514                                 fprintf( stderr, "%s: -X incompatible with "
515                                         "authentication choice\n", prog );
516                                 exit( EXIT_FAILURE );
517                         }
518                         authmethod = LDAP_AUTH_SASL;
519                         sasl_authz_id = ber_strdup( optarg );
520 #else
521                         fprintf( stderr, "%s: not compiled with SASL support\n", prog );
522                         exit( EXIT_FAILURE );
523 #endif
524                         break;
525                 case 'Z':
526 #ifdef HAVE_TLS
527                         use_tls++;
528 #else
529                         fprintf( stderr, "%s: not compiled with TLS support\n", prog );
530                         exit( EXIT_FAILURE );
531 #endif
532                         break;
533                 default:
534                         if( handle_private_option( i ) ) break;
535                         fprintf( stderr, "%s: unrecognized option -%c\n",
536                                 prog, optopt );
537                         usage();
538                 }
539         }
540
541         {
542                 /* prevent bad linking */
543                 LDAPAPIInfo api;
544                 api.ldapai_info_version = LDAP_API_INFO_VERSION;
545
546                 if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
547                         != LDAP_OPT_SUCCESS )
548                 {
549                         fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
550                         exit( EXIT_FAILURE );
551                 }
552
553                 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
554                         fprintf( stderr, "LDAP APIInfo version mismatch: "
555                                 "got %d, expected %d\n",
556                                 api.ldapai_info_version, LDAP_API_INFO_VERSION );
557                         exit( EXIT_FAILURE );
558                 }
559
560                 if( api.ldapai_api_version != LDAP_API_VERSION ) {
561                         fprintf( stderr, "LDAP API version mismatch: "
562                                 "got %d, expected %d\n",
563                                 api.ldapai_api_version, LDAP_API_VERSION );
564                         exit( EXIT_FAILURE );
565                 }
566
567                 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
568                         fprintf( stderr, "LDAP vendor name mismatch: "
569                                 "got %s, expected %s\n",
570                                 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
571                         exit( EXIT_FAILURE );
572                 }
573
574                 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
575                         fprintf( stderr, "LDAP vendor version mismatch: "
576                                 "got %d, expected %d\n",
577                                 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
578                         exit( EXIT_FAILURE );
579                 }
580
581                 if (version) {
582                         fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
583                                 prog, __Version,
584                                 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
585                         if (version > 1) exit( EXIT_SUCCESS );
586                 }
587         }
588
589         if (protocol == -1)
590                 protocol = LDAP_VERSION3;
591
592         if (authmethod == -1 && protocol > LDAP_VERSION2) {
593 #ifdef HAVE_CYRUS_SASL
594                 authmethod = LDAP_AUTH_SASL;
595 #else
596                 authmethod = LDAP_AUTH_SIMPLE;
597 #endif
598         }
599
600         if( ldapuri == NULL ) {
601                 if( ldapport && ( ldaphost == NULL )) {
602                         fprintf( stderr, "%s: -p without -h is invalid.\n", prog );
603                         exit( EXIT_FAILURE );
604                 }
605         } else {
606                 if( ldaphost != NULL ) {
607                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
608                         exit( EXIT_FAILURE );
609                 }
610                 if( ldapport ) {
611                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
612                         exit( EXIT_FAILURE );
613                 }
614         }
615         if( protocol == LDAP_VERSION2 ) {
616                 if( authzid || manageDSAit || noop ) {
617                         fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
618                         exit( EXIT_FAILURE );
619                 }
620 #ifdef HAVE_TLS
621                 if( use_tls ) {
622                         fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
623                         exit( EXIT_FAILURE );
624                 }
625 #endif
626 #ifdef HAVE_CYRUS_SASL
627                 if( authmethod == LDAP_AUTH_SASL ) {
628                         fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
629                                 prog );
630                         exit( EXIT_FAILURE );
631                 }
632 #endif
633         } else {
634 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
635                 if ( authmethod == LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
636                         fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
637                                 prog, protocol );
638                         exit( EXIT_FAILURE );
639                 }
640 #endif
641         }
642 }
643
644
645 LDAP *
646 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
647 {
648         LDAP *ld = NULL;
649
650         if ( debug ) {
651                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
652                         != LBER_OPT_SUCCESS )
653                 {
654                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
655                 }
656                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
657                         != LDAP_OPT_SUCCESS )
658                 {
659                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
660                 }
661         }
662
663 #ifdef SIGPIPE
664         (void) SIGNAL( SIGPIPE, SIG_IGN );
665 #endif
666
667         if ( !not ) {
668                 int rc;
669
670                 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
671                         /* construct URL */
672                         LDAPURLDesc url;
673                         memset( &url, 0, sizeof(url));
674
675                         url.lud_scheme = "ldap";
676                         url.lud_host = ldaphost;
677                         url.lud_port = ldapport;
678                         url.lud_scope = LDAP_SCOPE_DEFAULT;
679
680                         ldapuri = ldap_url_desc2str( &url );
681                 }
682
683                 if ( verbose ) {
684                         fprintf( stderr, "ldap_initialize( %s )\n",
685                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
686                 }
687                 rc = ldap_initialize( &ld, ldapuri );
688                 if( rc != LDAP_SUCCESS ) {
689                         fprintf( stderr,
690                                 "Could not create LDAP session handle for URI=%s %d): %s\n",
691                                 ldapuri, rc, ldap_err2string(rc) );
692                         exit( EXIT_FAILURE );
693                 }
694
695                 if( private_setup ) private_setup( ld );
696
697                 /* referrals */
698                 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
699                         referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
700                 {
701                         fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
702                                 referrals ? "on" : "off" );
703                         exit( EXIT_FAILURE );
704                 }
705
706                 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
707                         != LDAP_OPT_SUCCESS )
708                 {
709                         fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
710                                 protocol );
711                         exit( EXIT_FAILURE );
712                 }
713
714                 if ( use_tls &&
715                         ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ))
716                 {
717                         ldap_perror( ld, "ldap_start_tls" );
718                         if ( use_tls > 1 ) {
719                                 exit( EXIT_FAILURE );
720                         }
721                 }
722         }
723
724         return ld;
725 }
726
727
728 void
729 tool_bind( LDAP *ld )
730 {
731         if ( authmethod == LDAP_AUTH_SASL ) {
732 #ifdef HAVE_CYRUS_SASL
733                 void *defaults;
734                 int rc;
735
736                 if( sasl_secprops != NULL ) {
737                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
738                                 (void *) sasl_secprops );
739
740                         if( rc != LDAP_OPT_SUCCESS ) {
741                                 fprintf( stderr,
742                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
743                                         sasl_secprops );
744                                 exit( EXIT_FAILURE );
745                         }
746                 }
747
748                 defaults = lutil_sasl_defaults( ld,
749                         sasl_mech,
750                         sasl_realm,
751                         sasl_authc_id,
752                         passwd.bv_val,
753                         sasl_authz_id );
754
755                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
756                         sasl_mech, NULL, NULL,
757                         sasl_flags, lutil_sasl_interact, defaults );
758
759                 lutil_sasl_freedefs( defaults );
760                 if( rc != LDAP_SUCCESS ) {
761                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
762                         exit( EXIT_FAILURE );
763                 }
764 #else
765                 fprintf( stderr, "%s: not compiled with SASL support\n",
766                         prog );
767                 exit( EXIT_FAILURE );
768 #endif
769         } else {
770                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
771                         != LDAP_SUCCESS )
772                 {
773                         ldap_perror( ld, "ldap_bind" );
774                         exit( EXIT_FAILURE );
775                 }
776         }
777 }
778
779
780 /* Set server controls.  Add controls extra_c[0..count-1], if set. */
781 void
782 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
783 {
784         int i = 0, j, crit = 0, err;
785         LDAPControl c[6], **ctrls;
786
787         ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
788         if ( ctrls == NULL ) {
789                 fprintf( stderr, "No memory\n" );
790                 exit( EXIT_FAILURE );
791         }
792
793         if ( assertctl ) {
794                 BerElementBuffer berbuf;
795                 BerElement *ber = (BerElement *)&berbuf;
796                 
797                 if( assertion == NULL || *assertion == '\0' ) {
798                         fprintf( stderr, "Assertion=<empty>\n" );
799                         exit( EXIT_FAILURE );
800                 }
801
802                 ber_init2( ber, NULL, LBER_USE_DER );
803
804                 err = ldap_pvt_put_filter( ber, assertion );
805                 if( err < 0 ) {
806                         fprintf( stderr, "assertion encode failed (%d)\n", err );
807                         exit( EXIT_FAILURE );
808                 }
809
810                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
811                 if( err < 0 ) {
812                         fprintf( stderr, "assertion flatten failed (%d)\n", err );
813                         exit( EXIT_FAILURE );
814                 }
815
816                 c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
817                 c[i].ldctl_iscritical = assertctl > 1;
818                 ctrls[i] = &c[i];
819                 i++;
820         }
821
822         if ( authzid ) {
823                 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
824                 c[i].ldctl_value.bv_val = authzid;
825                 c[i].ldctl_value.bv_len = strlen( authzid );
826                 c[i].ldctl_iscritical = 1;
827                 ctrls[i] = &c[i];
828                 i++;
829         }
830
831         if ( manageDSAit ) {
832                 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
833                 c[i].ldctl_value.bv_val = NULL;
834                 c[i].ldctl_value.bv_len = 0;
835                 c[i].ldctl_iscritical = manageDSAit > 1;
836                 ctrls[i] = &c[i];
837                 i++;
838         }
839
840         if ( noop ) {
841                 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
842                 c[i].ldctl_value.bv_val = NULL;
843                 c[i].ldctl_value.bv_len = 0;
844                 c[i].ldctl_iscritical = noop > 1;
845                 ctrls[i] = &c[i];
846                 i++;
847         }
848         
849         if ( preread ) {
850                 char berbuf[LBER_ELEMENT_SIZEOF];
851                 BerElement *ber = (BerElement *)berbuf;
852                 char **attrs = NULL;
853
854                 if( preread_attrs ) {
855                         attrs = ldap_str2charray( preread_attrs, "," );
856                 }
857
858                 ber_init2( ber, NULL, LBER_USE_DER );
859
860                 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
861                         fprintf( stderr, "preread attrs encode failed.\n" );
862                         exit( EXIT_FAILURE );
863                 }
864
865                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
866                 if( err < 0 ) {
867                         fprintf( stderr, "preread flatten failed (%d)\n", err );
868                         exit( EXIT_FAILURE );
869                 }
870
871                 c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
872                 c[i].ldctl_iscritical = preread > 1;
873                 ctrls[i] = &c[i];
874                 i++;
875
876                 if( attrs ) ldap_charray_free( attrs );
877         }
878
879         if ( postread ) {
880                 char berbuf[LBER_ELEMENT_SIZEOF];
881                 BerElement *ber = (BerElement *)berbuf;
882                 char **attrs = NULL;
883
884                 if( postread_attrs ) {
885                         attrs = ldap_str2charray( postread_attrs, "," );
886                 }
887
888                 ber_init2( ber, NULL, LBER_USE_DER );
889
890                 if( ber_printf( ber, "{v}", attrs ) == -1 ) {
891                         fprintf( stderr, "postread attrs encode failed.\n" );
892                         exit( EXIT_FAILURE );
893                 }
894
895                 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
896                 if( err < 0 ) {
897                         fprintf( stderr, "postread flatten failed (%d)\n", err );
898                         exit( EXIT_FAILURE );
899                 }
900
901                 c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
902                 c[i].ldctl_iscritical = postread > 1;
903                 ctrls[i] = &c[i];
904                 i++;
905
906                 if( attrs ) ldap_charray_free( attrs );
907         }
908
909         while ( count-- ) {
910                 ctrls[i++] = extra_c++;
911         }
912         ctrls[i] = NULL;
913
914         err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
915
916         if ( err != LDAP_OPT_SUCCESS ) {
917                 for ( j = 0; j < i; j++ ) {
918                         if ( ctrls[j]->ldctl_iscritical ) crit = 1;
919                 }
920                 fprintf( stderr, "Could not set %scontrols\n",
921                         crit ? "critical " : "" );
922         }
923
924         free( ctrls );
925         if ( crit ) {
926                 exit( EXIT_FAILURE );
927         }
928 }