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"
31 char *ldaphost = NULL;
33 #ifdef HAVE_CYRUS_SASL
34 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
35 char *sasl_realm = NULL;
36 char *sasl_authc_id = NULL;
37 char *sasl_authz_id = NULL;
38 char *sasl_mech = NULL;
39 char *sasl_secprops = NULL;
49 struct berval passwd = { 0, NULL };
60 tool_common_usage( void )
62 static const char *const descriptions[] = {
63 " -c continuous operation mode (do not stop on errors)\n",
64 " -C chase referrals\n",
65 " -d level set LDAP debugging level to `level'\n",
66 " -D binddn bind DN\n",
67 " -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
68 " [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
69 " [!]manageDSAit (alternate form, see -M)\n"
71 " -f file read operations from `file'\n",
72 " -h host LDAP server\n",
73 " -H URI LDAP Uniform Resource Indentifier(s)\n",
74 " -I use SASL Interactive mode\n",
75 " -k use Kerberos authentication\n",
76 " -K like -k, but do only step 1 of the Kerberos bind\n",
77 " -M enable Manage DSA IT control (-MM to make critical)\n",
78 " -n show what would be done but don't actually do it\n",
79 " -O props SASL security properties\n",
80 " -p port port on LDAP server\n",
81 " -P version procotol version (default: 3)\n",
82 " -Q use SASL Quiet mode\n",
83 " -R realm SASL realm\n",
84 " -U authcid SASL authentication identity\n",
85 " -v run in verbose mode (diagnostics to standard output)\n",
86 " -V print version info (-VV only)\n",
87 " -w passwd bind passwd (for simple authentication)\n",
88 " -W prompt for bind passwd\n",
89 " -x Simple authentication\n",
90 " -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n",
91 " -y file Read passwd from file\n",
92 " -Y mech SASL mechanism\n",
93 " -Z Start TLS request (-ZZ to require successful response)\n",
96 const char *const *cpp;
98 fputs( "Common options:\n", stderr );
99 for( cpp = descriptions; *cpp != NULL; cpp++ ) {
100 if( strchr( options, (*cpp)[3] ) ) {
101 fputs( *cpp, stderr );
108 tool_args( int argc, char **argv )
111 while (( i = getopt( argc, argv, options )) != EOF )
114 char *control, *cvalue;
116 case 'c': /* continuous operation mode */
123 debug |= atoi( optarg );
125 case 'D': /* bind DN */
126 if( binddn != NULL ) {
127 fprintf( stderr, "%s: -D previously specified\n", prog );
128 exit( EXIT_FAILURE );
130 binddn = ber_strdup( optarg );
132 case 'e': /* general controls */
133 /* should be extended to support comma separated list of
134 * [!]key[=value] parameters, e.g. -e !foo,bar=567
139 if( optarg[0] == '!' ) {
144 control = ber_strdup( optarg );
145 if ( (cvalue = strchr( control, '=' )) != NULL ) {
149 if ( strcasecmp( control, "authzid" ) == 0 ) {
150 if( authzid != NULL ) {
151 fprintf( stderr, "authzid control previously specified\n");
152 exit( EXIT_FAILURE );
154 if( cvalue == NULL ) {
155 fprintf( stderr, "authzid: control value expected\n" );
159 fprintf( stderr, "authzid: must be marked critical\n" );
163 assert( authzid == NULL );
166 } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
169 "manageDSAit control previously specified\n");
170 exit( EXIT_FAILURE );
172 if( cvalue != NULL ) {
174 "manageDSAit: no control value expected\n" );
178 manageDSAit = 1 + crit;
180 } else if ( strcasecmp( control, "noop" ) == 0 ) {
182 fprintf( stderr, "noop control previously specified\n");
183 exit( EXIT_FAILURE );
185 if( cvalue != NULL ) {
186 fprintf( stderr, "noop: no control value expected\n" );
193 fprintf( stderr, "Invalid general control name: %s\n",
198 case 'f': /* read from file */
199 if( infile != NULL ) {
200 fprintf( stderr, "%s: -f previously specified\n", prog );
201 exit( EXIT_FAILURE );
203 infile = ber_strdup( optarg );
205 case 'h': /* ldap host */
206 if( ldaphost != NULL ) {
207 fprintf( stderr, "%s: -h previously specified\n", prog );
208 exit( EXIT_FAILURE );
210 ldaphost = ber_strdup( optarg );
212 case 'H': /* ldap URI */
213 if( ldapuri != NULL ) {
214 fprintf( stderr, "%s: -H previously specified\n", prog );
215 exit( EXIT_FAILURE );
217 ldapuri = ber_strdup( optarg );
220 #ifdef HAVE_CYRUS_SASL
221 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
222 fprintf( stderr, "%s: incompatible previous "
223 "authentication choice\n",
225 exit( EXIT_FAILURE );
227 authmethod = LDAP_AUTH_SASL;
228 sasl_flags = LDAP_SASL_INTERACTIVE;
231 fprintf( stderr, "%s: was not compiled with SASL support\n",
233 exit( EXIT_FAILURE );
235 case 'k': /* kerberos bind */
236 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
237 if( authmethod != -1 ) {
238 fprintf( stderr, "%s: -k incompatible with previous "
239 "authentication choice\n", prog );
240 exit( EXIT_FAILURE );
242 authmethod = LDAP_AUTH_KRBV4;
244 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
245 exit( EXIT_FAILURE );
248 case 'K': /* kerberos bind, part one only */
249 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
250 if( authmethod != -1 ) {
251 fprintf( stderr, "%s: incompatible with previous "
252 "authentication choice\n", prog );
253 exit( EXIT_FAILURE );
255 authmethod = LDAP_AUTH_KRBV41;
257 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
258 exit( EXIT_FAILURE );
262 /* enable Manage DSA IT */
265 case 'n': /* print operations, don't actually do them */
269 #ifdef HAVE_CYRUS_SASL
270 if( sasl_secprops != NULL ) {
271 fprintf( stderr, "%s: -O previously specified\n", prog );
272 exit( EXIT_FAILURE );
274 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
275 fprintf( stderr, "%s: incompatible previous "
276 "authentication choice\n", prog );
277 exit( EXIT_FAILURE );
279 authmethod = LDAP_AUTH_SASL;
280 sasl_secprops = ber_strdup( optarg );
282 fprintf( stderr, "%s: not compiled with SASL support\n",
284 exit( EXIT_FAILURE );
289 fprintf( stderr, "%s: -p previously specified\n", prog );
290 exit( EXIT_FAILURE );
292 ldapport = atoi( optarg );
295 switch( atoi(optarg) ) {
297 if( protocol == LDAP_VERSION3 ) {
298 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
300 exit( EXIT_FAILURE );
302 protocol = LDAP_VERSION2;
305 if( protocol == LDAP_VERSION2 ) {
306 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
308 exit( EXIT_FAILURE );
310 protocol = LDAP_VERSION3;
313 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
319 #ifdef HAVE_CYRUS_SASL
320 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
321 fprintf( stderr, "%s: incompatible previous "
322 "authentication choice\n",
324 exit( EXIT_FAILURE );
326 authmethod = LDAP_AUTH_SASL;
327 sasl_flags = LDAP_SASL_QUIET;
330 fprintf( stderr, "%s: not compiled with SASL support\n",
332 exit( EXIT_FAILURE );
335 #ifdef HAVE_CYRUS_SASL
336 if( sasl_realm != NULL ) {
337 fprintf( stderr, "%s: -R previously specified\n", prog );
338 exit( EXIT_FAILURE );
340 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
341 fprintf( stderr, "%s: incompatible previous "
342 "authentication choice\n",
344 exit( EXIT_FAILURE );
346 authmethod = LDAP_AUTH_SASL;
347 sasl_realm = ber_strdup( optarg );
349 fprintf( stderr, "%s: not compiled with SASL support\n",
351 exit( EXIT_FAILURE );
355 #ifdef HAVE_CYRUS_SASL
356 if( sasl_authc_id != NULL ) {
357 fprintf( stderr, "%s: -U previously specified\n", prog );
358 exit( EXIT_FAILURE );
360 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
361 fprintf( stderr, "%s: incompatible previous "
362 "authentication choice\n",
364 exit( EXIT_FAILURE );
366 authmethod = LDAP_AUTH_SASL;
367 sasl_authc_id = ber_strdup( optarg );
369 fprintf( stderr, "%s: not compiled with SASL support\n",
371 exit( EXIT_FAILURE );
374 case 'v': /* verbose mode */
377 case 'V': /* version */
380 case 'w': /* password */
381 passwd.bv_val = ber_strdup( optarg );
385 for( p = optarg; *p != '\0'; p++ ) {
389 passwd.bv_len = strlen( passwd.bv_val );
398 #ifdef HAVE_CYRUS_SASL
399 if( sasl_mech != NULL ) {
400 fprintf( stderr, "%s: -Y previously specified\n", prog );
401 exit( EXIT_FAILURE );
403 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
404 fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
405 exit( EXIT_FAILURE );
407 authmethod = LDAP_AUTH_SASL;
408 sasl_mech = ber_strdup( optarg );
410 fprintf( stderr, "%s: not compiled with SASL support\n",
412 exit( EXIT_FAILURE );
416 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
417 fprintf( stderr, "%s: incompatible with previous "
418 "authentication choice\n", prog );
419 exit( EXIT_FAILURE );
421 authmethod = LDAP_AUTH_SIMPLE;
424 #ifdef HAVE_CYRUS_SASL
425 if( sasl_authz_id != NULL ) {
426 fprintf( stderr, "%s: -X previously specified\n", prog );
427 exit( EXIT_FAILURE );
429 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
430 fprintf( stderr, "%s: -X incompatible with "
431 "authentication choice\n", prog );
432 exit( EXIT_FAILURE );
434 authmethod = LDAP_AUTH_SASL;
435 sasl_authz_id = ber_strdup( optarg );
437 fprintf( stderr, "%s: not compiled with SASL support\n", prog );
438 exit( EXIT_FAILURE );
445 fprintf( stderr, "%s: not compiled with TLS support\n", prog );
446 exit( EXIT_FAILURE );
450 if( handle_private_option( i ) )
452 fprintf( stderr, "%s: unrecognized option -%c\n",
459 /* prevent bad linking */
461 api.ldapai_info_version = LDAP_API_INFO_VERSION;
463 if ( ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS ) {
464 fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
465 exit( EXIT_FAILURE );
468 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
469 fprintf( stderr, "LDAP APIInfo version mismatch: "
470 "got %d, expected %d\n",
471 api.ldapai_info_version, LDAP_API_INFO_VERSION );
472 exit( EXIT_FAILURE );
475 if( api.ldapai_api_version != LDAP_API_VERSION ) {
476 fprintf( stderr, "LDAP API version mismatch: "
477 "got %d, expected %d\n",
478 api.ldapai_api_version, LDAP_API_VERSION );
479 exit( EXIT_FAILURE );
482 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
483 fprintf( stderr, "LDAP vendor name mismatch: "
484 "got %s, expected %s\n",
485 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
486 exit( EXIT_FAILURE );
489 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
490 fprintf( stderr, "LDAP vendor version mismatch: "
491 "got %d, expected %d\n",
492 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
493 exit( EXIT_FAILURE );
497 fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
499 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
500 if (version > 1) exit( EXIT_SUCCESS );
505 protocol = LDAP_VERSION3;
507 if (authmethod == -1 && protocol > LDAP_VERSION2) {
508 #ifdef HAVE_CYRUS_SASL
509 authmethod = LDAP_AUTH_SASL;
511 authmethod = LDAP_AUTH_SIMPLE;
515 if( ldapuri != NULL ) {
516 if( ldaphost != NULL ) {
517 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
518 exit( EXIT_FAILURE );
521 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
522 exit( EXIT_FAILURE );
525 if( protocol == LDAP_VERSION2 ) {
526 if( authzid || manageDSAit || noop ) {
527 fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
528 exit( EXIT_FAILURE );
532 fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
533 exit( EXIT_FAILURE );
536 #ifdef HAVE_CYRUS_SASL
537 if( authmethod == LDAP_AUTH_SASL ) {
538 fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
540 exit( EXIT_FAILURE );
544 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
545 if ( authmethod = LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
546 fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
548 exit( EXIT_FAILURE );
556 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
561 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
562 != LBER_OPT_SUCCESS ) {
563 fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
565 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
566 != LDAP_OPT_SUCCESS ) {
567 fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
572 (void) SIGNAL( SIGPIPE, SIG_IGN );
576 /* connect to server */
577 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
579 fprintf( stderr, "ldap_init( %s, %d )\n",
580 ldaphost != NULL ? ldaphost : "<DEFAULT>",
584 ld = ldap_init( ldaphost, ldapport );
586 char buf[20 + sizeof(": ldap_init")];
587 sprintf( buf, "%.20s: ldap_init", prog );
589 exit( EXIT_FAILURE );
595 fprintf( stderr, "ldap_initialize( %s )\n",
596 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
598 rc = ldap_initialize( &ld, ldapuri );
599 if( rc != LDAP_SUCCESS ) {
600 fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
601 rc, ldap_err2string(rc) );
602 exit( EXIT_FAILURE );
610 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
611 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF )
612 != LDAP_OPT_SUCCESS )
614 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
615 referrals ? "on" : "off" );
616 exit( EXIT_FAILURE );
619 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
620 != LDAP_OPT_SUCCESS )
622 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
624 exit( EXIT_FAILURE );
628 ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
629 ldap_perror( ld, "ldap_start_tls" );
631 exit( EXIT_FAILURE );
641 tool_bind( LDAP *ld )
643 if ( authmethod == LDAP_AUTH_SASL ) {
644 #ifdef HAVE_CYRUS_SASL
648 if( sasl_secprops != NULL ) {
649 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
650 (void *) sasl_secprops );
652 if( rc != LDAP_OPT_SUCCESS ) {
654 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
656 exit( EXIT_FAILURE );
660 defaults = lutil_sasl_defaults( ld,
667 rc = ldap_sasl_interactive_bind_s( ld, binddn,
668 sasl_mech, NULL, NULL,
669 sasl_flags, lutil_sasl_interact, defaults );
671 if( rc != LDAP_SUCCESS ) {
672 ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
673 exit( EXIT_FAILURE );
676 fprintf( stderr, "%s: not compiled with SASL support\n",
678 exit( EXIT_FAILURE );
681 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
683 ldap_perror( ld, "ldap_bind" );
684 exit( EXIT_FAILURE );
690 /* Set server controls. Add controls extra_c[0..count-1], if set. */
692 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
694 int i = 0, j, crit = 0, err;
695 LDAPControl c[3], **ctrls;
697 ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
698 if ( ctrls == NULL ) {
699 fprintf( stderr, "No memory\n" );
700 exit( EXIT_FAILURE );
704 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
705 c[i].ldctl_value.bv_val = authzid;
706 c[i].ldctl_value.bv_len = strlen( authzid );
707 c[i].ldctl_iscritical = 1;
713 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
714 c[i].ldctl_value.bv_val = NULL;
715 c[i].ldctl_value.bv_len = 0;
716 c[i].ldctl_iscritical = manageDSAit > 1;
722 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
723 c[i].ldctl_value.bv_val = NULL;
724 c[i].ldctl_value.bv_len = 0;
725 c[i].ldctl_iscritical = noop > 1;
731 ctrls[i++] = extra_c++;
734 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
736 if ( err != LDAP_OPT_SUCCESS ) {
737 for ( j = 0; j < i; j++ )
738 if ( ctrls[j]->ldctl_iscritical )
740 fprintf( stderr, "Could not set %scontrols\n",
741 crit ? "critical " : "" );
746 exit( EXIT_FAILURE );