3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 /* common.c - common routines for the ldap client tools */
12 #include <ac/stdlib.h>
13 #include <ac/signal.h>
14 #include <ac/string.h>
15 #include <ac/unistd.h>
20 #include "lutil_ldap.h"
21 #include "ldap_defaults.h"
32 char *ldaphost = NULL;
34 #ifdef HAVE_CYRUS_SASL
35 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
36 char *sasl_realm = NULL;
37 char *sasl_authc_id = NULL;
38 char *sasl_authz_id = NULL;
39 char *sasl_mech = NULL;
40 char *sasl_secprops = NULL;
44 char *assertion = NULL;
51 struct berval passwd = { 0, NULL };
64 ldap_pvt_setlocale(LC_MESSAGES, "");
65 ldap_pvt_bindtextdomain(OPENLDAP_PACKAGE, LDAP_LOCALEDIR);
66 ldap_pvt_textdomain(OPENLDAP_PACKAGE);
70 tool_common_usage( void )
72 static const char *const descriptions[] = {
73 N_(" -c continuous operation mode (do not stop on errors)\n"),
74 N_(" -C chase referrals\n"),
75 N_(" -d level set LDAP debugging level to `level'\n"),
76 N_(" -D binddn bind DN\n"),
77 N_(" -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n")
78 N_(" [!]assert=<filter> (an RFC 2254 Filter)\n")
79 N_(" [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n")
80 N_(" [!]manageDSAit (alternate form, see -M)\n")
82 N_(" -f file read operations from `file'\n"),
83 N_(" -h host LDAP server\n"),
84 N_(" -H URI LDAP Uniform Resource Indentifier(s)\n"),
85 N_(" -I use SASL Interactive mode\n"),
86 N_(" -k use Kerberos authentication\n"),
87 N_(" -K like -k, but do only step 1 of the Kerberos bind\n"),
88 N_(" -M enable Manage DSA IT control (-MM to make critical)\n"),
89 N_(" -n show what would be done but don't actually do it\n"),
90 N_(" -O props SASL security properties\n"),
91 N_(" -p port port on LDAP server\n"),
92 N_(" -P version procotol version (default: 3)\n"),
93 N_(" -Q use SASL Quiet mode\n"),
94 N_(" -R realm SASL realm\n"),
95 N_(" -U authcid SASL authentication identity\n"),
96 N_(" -v run in verbose mode (diagnostics to standard output)\n"),
97 N_(" -V print version info (-VV only)\n"),
98 N_(" -w passwd bind password (for simple authentication)\n"),
99 N_(" -W prompt for bind password\n"),
100 N_(" -x Simple authentication\n"),
101 N_(" -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"),
102 N_(" -y file Read password from file\n"),
103 N_(" -Y mech SASL mechanism\n"),
104 N_(" -Z Start TLS request (-ZZ to require successful response)\n"),
107 const char *const *cpp;
109 fputs( _("Common options:\n"), stderr );
110 for( cpp = descriptions; *cpp != NULL; cpp++ ) {
111 if( strchr( options, (*cpp)[3] ) ) {
112 fputs( _(*cpp), stderr );
119 tool_args( int argc, char **argv )
123 while (( i = getopt( argc, argv, options )) != EOF ) {
125 char *control, *cvalue;
127 case 'c': /* continuous operation mode */
134 debug |= atoi( optarg );
136 case 'D': /* bind DN */
137 if( binddn != NULL ) {
138 fprintf( stderr, "%s: -D previously specified\n", prog );
139 exit( EXIT_FAILURE );
141 binddn = ber_strdup( optarg );
143 case 'e': /* general controls */
144 /* should be extended to support comma separated list of
145 * [!]key[=value] parameters, e.g. -e !foo,bar=567
150 if( optarg[0] == '!' ) {
155 control = ber_strdup( optarg );
156 if ( (cvalue = strchr( control, '=' )) != NULL ) {
160 if ( strcasecmp( control, "assert" ) == 0 ) {
161 if( assertion != NULL ) {
162 fprintf( stderr, "assert control previously specified\n");
163 exit( EXIT_FAILURE );
165 if( cvalue == NULL ) {
166 fprintf( stderr, "assert: control value expected\n" );
170 assert( assertion == NULL );
173 } else if ( strcasecmp( control, "authzid" ) == 0 ) {
174 if( authzid != NULL ) {
175 fprintf( stderr, "authzid control previously specified\n");
176 exit( EXIT_FAILURE );
178 if( cvalue == NULL ) {
179 fprintf( stderr, "authzid: control value expected\n" );
183 fprintf( stderr, "authzid: must be marked critical\n" );
187 assert( authzid == NULL );
190 } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
193 "manageDSAit control previously specified\n");
194 exit( EXIT_FAILURE );
196 if( cvalue != NULL ) {
198 "manageDSAit: no control value expected\n" );
202 manageDSAit = 1 + crit;
204 } else if ( strcasecmp( control, "noop" ) == 0 ) {
206 fprintf( stderr, "noop control previously specified\n");
207 exit( EXIT_FAILURE );
209 if( cvalue != NULL ) {
210 fprintf( stderr, "noop: no control value expected\n" );
217 fprintf( stderr, "Invalid general control name: %s\n",
222 case 'f': /* read from file */
223 if( infile != NULL ) {
224 fprintf( stderr, "%s: -f previously specified\n", prog );
225 exit( EXIT_FAILURE );
227 infile = ber_strdup( optarg );
229 case 'h': /* ldap host */
230 if( ldaphost != NULL ) {
231 fprintf( stderr, "%s: -h previously specified\n", prog );
232 exit( EXIT_FAILURE );
234 ldaphost = ber_strdup( optarg );
236 case 'H': /* ldap URI */
237 if( ldapuri != NULL ) {
238 fprintf( stderr, "%s: -H previously specified\n", prog );
239 exit( EXIT_FAILURE );
241 ldapuri = ber_strdup( optarg );
244 #ifdef HAVE_CYRUS_SASL
245 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
246 fprintf( stderr, "%s: incompatible previous "
247 "authentication choice\n",
249 exit( EXIT_FAILURE );
251 authmethod = LDAP_AUTH_SASL;
252 sasl_flags = LDAP_SASL_INTERACTIVE;
255 fprintf( stderr, "%s: was not compiled with SASL support\n",
257 exit( EXIT_FAILURE );
259 case 'k': /* kerberos bind */
260 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
261 if( authmethod != -1 ) {
262 fprintf( stderr, "%s: -k incompatible with previous "
263 "authentication choice\n", prog );
264 exit( EXIT_FAILURE );
266 authmethod = LDAP_AUTH_KRBV4;
268 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
269 exit( EXIT_FAILURE );
272 case 'K': /* kerberos bind, part one only */
273 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
274 if( authmethod != -1 ) {
275 fprintf( stderr, "%s: incompatible with previous "
276 "authentication choice\n", prog );
277 exit( EXIT_FAILURE );
279 authmethod = LDAP_AUTH_KRBV41;
281 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
282 exit( EXIT_FAILURE );
286 /* enable Manage DSA IT */
289 case 'n': /* print operations, don't actually do them */
293 #ifdef HAVE_CYRUS_SASL
294 if( sasl_secprops != NULL ) {
295 fprintf( stderr, "%s: -O previously specified\n", prog );
296 exit( EXIT_FAILURE );
298 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
299 fprintf( stderr, "%s: incompatible previous "
300 "authentication choice\n", prog );
301 exit( EXIT_FAILURE );
303 authmethod = LDAP_AUTH_SASL;
304 sasl_secprops = ber_strdup( optarg );
306 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
307 exit( EXIT_FAILURE );
312 fprintf( stderr, "%s: -p previously specified\n", prog );
313 exit( EXIT_FAILURE );
315 ldapport = atoi( optarg );
318 switch( atoi(optarg) ) {
320 if( protocol == LDAP_VERSION3 ) {
321 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
323 exit( EXIT_FAILURE );
325 protocol = LDAP_VERSION2;
328 if( protocol == LDAP_VERSION2 ) {
329 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
331 exit( EXIT_FAILURE );
333 protocol = LDAP_VERSION3;
336 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
342 #ifdef HAVE_CYRUS_SASL
343 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
344 fprintf( stderr, "%s: incompatible previous "
345 "authentication choice\n",
347 exit( EXIT_FAILURE );
349 authmethod = LDAP_AUTH_SASL;
350 sasl_flags = LDAP_SASL_QUIET;
353 fprintf( stderr, "%s: not compiled with SASL support\n",
355 exit( EXIT_FAILURE );
358 #ifdef HAVE_CYRUS_SASL
359 if( sasl_realm != NULL ) {
360 fprintf( stderr, "%s: -R previously specified\n", prog );
361 exit( EXIT_FAILURE );
363 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
364 fprintf( stderr, "%s: incompatible previous "
365 "authentication choice\n",
367 exit( EXIT_FAILURE );
369 authmethod = LDAP_AUTH_SASL;
370 sasl_realm = ber_strdup( optarg );
372 fprintf( stderr, "%s: not compiled with SASL support\n",
374 exit( EXIT_FAILURE );
378 #ifdef HAVE_CYRUS_SASL
379 if( sasl_authc_id != NULL ) {
380 fprintf( stderr, "%s: -U previously specified\n", prog );
381 exit( EXIT_FAILURE );
383 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
384 fprintf( stderr, "%s: incompatible previous "
385 "authentication choice\n",
387 exit( EXIT_FAILURE );
389 authmethod = LDAP_AUTH_SASL;
390 sasl_authc_id = ber_strdup( optarg );
392 fprintf( stderr, "%s: not compiled with SASL support\n",
394 exit( EXIT_FAILURE );
397 case 'v': /* verbose mode */
400 case 'V': /* version */
403 case 'w': /* password */
404 passwd.bv_val = ber_strdup( optarg );
408 for( p = optarg; *p != '\0'; p++ ) {
412 passwd.bv_len = strlen( passwd.bv_val );
421 #ifdef HAVE_CYRUS_SASL
422 if( sasl_mech != NULL ) {
423 fprintf( stderr, "%s: -Y previously specified\n", prog );
424 exit( EXIT_FAILURE );
426 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
428 "%s: incompatible with authentication choice\n", prog );
429 exit( EXIT_FAILURE );
431 authmethod = LDAP_AUTH_SASL;
432 sasl_mech = ber_strdup( optarg );
434 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
435 exit( EXIT_FAILURE );
439 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
440 fprintf( stderr, "%s: incompatible with previous "
441 "authentication choice\n", prog );
442 exit( EXIT_FAILURE );
444 authmethod = LDAP_AUTH_SIMPLE;
447 #ifdef HAVE_CYRUS_SASL
448 if( sasl_authz_id != NULL ) {
449 fprintf( stderr, "%s: -X previously specified\n", prog );
450 exit( EXIT_FAILURE );
452 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
453 fprintf( stderr, "%s: -X incompatible with "
454 "authentication choice\n", prog );
455 exit( EXIT_FAILURE );
457 authmethod = LDAP_AUTH_SASL;
458 sasl_authz_id = ber_strdup( optarg );
460 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
461 exit( EXIT_FAILURE );
468 fprintf( stderr, "%s: not compiled with TLS support\n", prog );
469 exit( EXIT_FAILURE );
473 if( handle_private_option( i ) ) break;
474 fprintf( stderr, "%s: unrecognized option -%c\n",
481 /* prevent bad linking */
483 api.ldapai_info_version = LDAP_API_INFO_VERSION;
485 if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api)
486 != LDAP_OPT_SUCCESS )
488 fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
489 exit( EXIT_FAILURE );
492 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
493 fprintf( stderr, "LDAP APIInfo version mismatch: "
494 "got %d, expected %d\n",
495 api.ldapai_info_version, LDAP_API_INFO_VERSION );
496 exit( EXIT_FAILURE );
499 if( api.ldapai_api_version != LDAP_API_VERSION ) {
500 fprintf( stderr, "LDAP API version mismatch: "
501 "got %d, expected %d\n",
502 api.ldapai_api_version, LDAP_API_VERSION );
503 exit( EXIT_FAILURE );
506 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
507 fprintf( stderr, "LDAP vendor name mismatch: "
508 "got %s, expected %s\n",
509 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
510 exit( EXIT_FAILURE );
513 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
514 fprintf( stderr, "LDAP vendor version mismatch: "
515 "got %d, expected %d\n",
516 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
517 exit( EXIT_FAILURE );
521 fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
523 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
524 if (version > 1) exit( EXIT_SUCCESS );
529 protocol = LDAP_VERSION3;
531 if (authmethod == -1 && protocol > LDAP_VERSION2) {
532 #ifdef HAVE_CYRUS_SASL
533 authmethod = LDAP_AUTH_SASL;
535 authmethod = LDAP_AUTH_SIMPLE;
539 if( ldapuri == NULL ) {
540 if( ldapport && ( ldaphost == NULL )) {
541 fprintf( stderr, "%s: -p without -h is invalid.\n", prog );
542 exit( EXIT_FAILURE );
545 if( ldaphost != NULL ) {
546 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
547 exit( EXIT_FAILURE );
550 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
551 exit( EXIT_FAILURE );
554 if( protocol == LDAP_VERSION2 ) {
555 if( authzid || manageDSAit || noop ) {
556 fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
557 exit( EXIT_FAILURE );
561 fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
562 exit( EXIT_FAILURE );
565 #ifdef HAVE_CYRUS_SASL
566 if( authmethod == LDAP_AUTH_SASL ) {
567 fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
569 exit( EXIT_FAILURE );
573 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
574 if ( authmethod == LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
575 fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
577 exit( EXIT_FAILURE );
585 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
590 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
591 != LBER_OPT_SUCCESS )
593 fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
595 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
596 != LDAP_OPT_SUCCESS )
598 fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
603 (void) SIGNAL( SIGPIPE, SIG_IGN );
607 /* connect to server */
608 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
610 fprintf( stderr, "ldap_init( %s, %d )\n",
611 ldaphost != NULL ? ldaphost : "<DEFAULT>",
615 ld = ldap_init( ldaphost, ldapport );
617 char buf[20 + sizeof(": ldap_init")];
618 sprintf( buf, "%.20s: ldap_init", prog );
620 exit( EXIT_FAILURE );
626 fprintf( stderr, "ldap_initialize( %s )\n",
627 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
629 rc = ldap_initialize( &ld, ldapuri );
630 if( rc != LDAP_SUCCESS ) {
632 "Could not create LDAP session handle (%d): %s\n",
633 rc, ldap_err2string(rc) );
634 exit( EXIT_FAILURE );
638 if( private_setup ) private_setup( ld );
641 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
642 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
644 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
645 referrals ? "on" : "off" );
646 exit( EXIT_FAILURE );
649 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
650 != LDAP_OPT_SUCCESS )
652 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
654 exit( EXIT_FAILURE );
658 ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ))
660 ldap_perror( ld, "ldap_start_tls" );
662 exit( EXIT_FAILURE );
672 tool_bind( LDAP *ld )
674 if ( authmethod == LDAP_AUTH_SASL ) {
675 #ifdef HAVE_CYRUS_SASL
679 if( sasl_secprops != NULL ) {
680 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
681 (void *) sasl_secprops );
683 if( rc != LDAP_OPT_SUCCESS ) {
685 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
687 exit( EXIT_FAILURE );
691 defaults = lutil_sasl_defaults( ld,
698 rc = ldap_sasl_interactive_bind_s( ld, binddn,
699 sasl_mech, NULL, NULL,
700 sasl_flags, lutil_sasl_interact, defaults );
702 lutil_sasl_freedefs( defaults );
703 if( rc != LDAP_SUCCESS ) {
704 ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
705 exit( EXIT_FAILURE );
708 fprintf( stderr, "%s: not compiled with SASL support\n",
710 exit( EXIT_FAILURE );
713 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
716 ldap_perror( ld, "ldap_bind" );
717 exit( EXIT_FAILURE );
723 /* Set server controls. Add controls extra_c[0..count-1], if set. */
725 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
727 int i = 0, j, crit = 0, err;
728 LDAPControl c[4], **ctrls;
730 ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
731 if ( ctrls == NULL ) {
732 fprintf( stderr, "No memory\n" );
733 exit( EXIT_FAILURE );
737 char berbuf[LBER_ELEMENT_SIZEOF];
738 BerElement *ber = (BerElement *)berbuf;
740 if( *assertion == '\0' ) {
741 fprintf( stderr, "Assertion=<empty>\n" );
742 exit( EXIT_FAILURE );
745 ber_init2( ber, NULL, LBER_USE_DER );
747 err = ldap_pvt_put_filter( ber, assertion );
749 fprintf( stderr, "assertion encode failed (%d)\n", err );
750 exit( EXIT_FAILURE );
753 err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
755 fprintf( stderr, "assertion flatten failed (%d)\n", err );
756 exit( EXIT_FAILURE );
759 c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
760 c[i].ldctl_iscritical = 1;
766 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
767 c[i].ldctl_value.bv_val = authzid;
768 c[i].ldctl_value.bv_len = strlen( authzid );
769 c[i].ldctl_iscritical = 1;
775 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
776 c[i].ldctl_value.bv_val = NULL;
777 c[i].ldctl_value.bv_len = 0;
778 c[i].ldctl_iscritical = manageDSAit > 1;
784 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
785 c[i].ldctl_value.bv_val = NULL;
786 c[i].ldctl_value.bv_len = 0;
787 c[i].ldctl_iscritical = noop > 1;
793 ctrls[i++] = extra_c++;
797 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
799 if ( err != LDAP_OPT_SUCCESS ) {
800 for ( j = 0; j < i; j++ ) {
801 if ( ctrls[j]->ldctl_iscritical ) crit = 1;
803 fprintf( stderr, "Could not set %scontrols\n",
804 crit ? "critical " : "" );
809 exit( EXIT_FAILURE );