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)
464 != LDAP_OPT_SUCCESS )
466 fprintf( stderr, "%s: ldap_get_option(API_INFO) failed\n", prog );
467 exit( EXIT_FAILURE );
470 if (api.ldapai_info_version != LDAP_API_INFO_VERSION) {
471 fprintf( stderr, "LDAP APIInfo version mismatch: "
472 "got %d, expected %d\n",
473 api.ldapai_info_version, LDAP_API_INFO_VERSION );
474 exit( EXIT_FAILURE );
477 if( api.ldapai_api_version != LDAP_API_VERSION ) {
478 fprintf( stderr, "LDAP API version mismatch: "
479 "got %d, expected %d\n",
480 api.ldapai_api_version, LDAP_API_VERSION );
481 exit( EXIT_FAILURE );
484 if( strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
485 fprintf( stderr, "LDAP vendor name mismatch: "
486 "got %s, expected %s\n",
487 api.ldapai_vendor_name, LDAP_VENDOR_NAME );
488 exit( EXIT_FAILURE );
491 if( api.ldapai_vendor_version != LDAP_VENDOR_VERSION ) {
492 fprintf( stderr, "LDAP vendor version mismatch: "
493 "got %d, expected %d\n",
494 api.ldapai_vendor_version, LDAP_VENDOR_VERSION );
495 exit( EXIT_FAILURE );
499 fprintf( stderr, "%s: %s\t(LDAP library: %s %d)\n",
501 LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION );
502 if (version > 1) exit( EXIT_SUCCESS );
507 protocol = LDAP_VERSION3;
509 if (authmethod == -1 && protocol > LDAP_VERSION2) {
510 #ifdef HAVE_CYRUS_SASL
511 authmethod = LDAP_AUTH_SASL;
513 authmethod = LDAP_AUTH_SIMPLE;
517 if( ldapuri != NULL ) {
518 if( ldaphost != NULL ) {
519 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
520 exit( EXIT_FAILURE );
523 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
524 exit( EXIT_FAILURE );
527 if( protocol == LDAP_VERSION2 ) {
528 if( authzid || manageDSAit || noop ) {
529 fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
530 exit( EXIT_FAILURE );
534 fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
535 exit( EXIT_FAILURE );
538 #ifdef HAVE_CYRUS_SASL
539 if( authmethod == LDAP_AUTH_SASL ) {
540 fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
542 exit( EXIT_FAILURE );
546 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
547 if ( authmethod == LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
548 fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
550 exit( EXIT_FAILURE );
558 tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
563 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
564 != LBER_OPT_SUCCESS ) {
565 fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
567 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
568 != LDAP_OPT_SUCCESS ) {
569 fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
574 (void) SIGNAL( SIGPIPE, SIG_IGN );
578 /* connect to server */
579 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
581 fprintf( stderr, "ldap_init( %s, %d )\n",
582 ldaphost != NULL ? ldaphost : "<DEFAULT>",
586 ld = ldap_init( ldaphost, ldapport );
588 char buf[20 + sizeof(": ldap_init")];
589 sprintf( buf, "%.20s: ldap_init", prog );
591 exit( EXIT_FAILURE );
597 fprintf( stderr, "ldap_initialize( %s )\n",
598 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
600 rc = ldap_initialize( &ld, ldapuri );
601 if( rc != LDAP_SUCCESS ) {
602 fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
603 rc, ldap_err2string(rc) );
604 exit( EXIT_FAILURE );
612 if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
613 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF )
614 != LDAP_OPT_SUCCESS )
616 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
617 referrals ? "on" : "off" );
618 exit( EXIT_FAILURE );
621 if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol )
622 != LDAP_OPT_SUCCESS )
624 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
626 exit( EXIT_FAILURE );
630 ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
631 ldap_perror( ld, "ldap_start_tls" );
633 exit( EXIT_FAILURE );
643 tool_bind( LDAP *ld )
645 if ( authmethod == LDAP_AUTH_SASL ) {
646 #ifdef HAVE_CYRUS_SASL
650 if( sasl_secprops != NULL ) {
651 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
652 (void *) sasl_secprops );
654 if( rc != LDAP_OPT_SUCCESS ) {
656 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
658 exit( EXIT_FAILURE );
662 defaults = lutil_sasl_defaults( ld,
669 rc = ldap_sasl_interactive_bind_s( ld, binddn,
670 sasl_mech, NULL, NULL,
671 sasl_flags, lutil_sasl_interact, defaults );
673 if( rc != LDAP_SUCCESS ) {
674 ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
675 exit( EXIT_FAILURE );
678 fprintf( stderr, "%s: not compiled with SASL support\n",
680 exit( EXIT_FAILURE );
683 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
685 ldap_perror( ld, "ldap_bind" );
686 exit( EXIT_FAILURE );
692 /* Set server controls. Add controls extra_c[0..count-1], if set. */
694 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
696 int i = 0, j, crit = 0, err;
697 LDAPControl c[3], **ctrls;
699 ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
700 if ( ctrls == NULL ) {
701 fprintf( stderr, "No memory\n" );
702 exit( EXIT_FAILURE );
706 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
707 c[i].ldctl_value.bv_val = authzid;
708 c[i].ldctl_value.bv_len = strlen( authzid );
709 c[i].ldctl_iscritical = 1;
715 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
716 c[i].ldctl_value.bv_val = NULL;
717 c[i].ldctl_value.bv_len = 0;
718 c[i].ldctl_iscritical = manageDSAit > 1;
724 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
725 c[i].ldctl_value.bv_val = NULL;
726 c[i].ldctl_value.bv_len = 0;
727 c[i].ldctl_iscritical = noop > 1;
733 ctrls[i++] = extra_c++;
736 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
738 if ( err != LDAP_OPT_SUCCESS ) {
739 for ( j = 0; j < i; j++ )
740 if ( ctrls[j]->ldctl_iscritical )
742 fprintf( stderr, "Could not set %scontrols\n",
743 crit ? "critical " : "" );
748 exit( EXIT_FAILURE );