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