From 95eea5acccaffb85ee2ac4ffcf4cd45dbb0fc4a0 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 17 Jul 2000 00:56:29 +0000 Subject: [PATCH] First cut SASL "interactive" and "quiet" modes (default is "automatic") --- clients/tools/ldapdelete.c | 112 ++++++++- clients/tools/ldapmodify.c | 110 ++++++++- clients/tools/ldapmodrdn.c | 119 ++++++++-- clients/tools/ldappasswd.c | 383 +++++++++++++++++++++++-------- clients/tools/ldapsearch.c | 110 ++++++++- include/ldap.h | 22 +- include/lutil_ldap.h | 21 +- libraries/libldap/cyrus.c | 24 +- libraries/libldap/init.c | 45 +++- libraries/libldap/ldap-int.h | 24 +- libraries/libldap/open.c | 12 +- libraries/libldap/sasl.c | 6 +- libraries/liblutil/sasl.c | 105 ++++++++- servers/slapd/tools/slappasswd.c | 2 +- 14 files changed, 918 insertions(+), 177 deletions(-) diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index 686f9ff764..ef9f94245f 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -27,9 +27,11 @@ static char *ldaphost = NULL; static int ldapport = 0; static int prune = 0; #ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LUTIL_SASL_AUTOMATIC; +static char *sasl_mech = NULL; +static char *sasl_realm = NULL; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; -static char *sasl_mech = NULL; static char *sasl_secprops = NULL; #endif static int use_tls = 0; @@ -61,6 +63,7 @@ usage( const char *s ) " -D binddn\tbind DN\n" " -f file\t\tread operations from `file'\n" " -h host\t\tLDAP server\n" +" -I\t\tuse SASL Interactive mode\n" " -k\t\tuse Kerberos authentication\n" " -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" " -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" @@ -68,6 +71,8 @@ usage( const char *s ) " -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" " -P version\tprocotol version (default: 3)\n" +" -Q\t\tuse SASL Quiet mode\n" +" -R realm\tSASL realm\n" " -U user\t\tSASL authentication identity (username)\n" " -v\t\trun in verbose mode (diagnostics to standard output)\n" " -w passwd\tbind passwd (for simple authentication)\n" @@ -96,13 +101,17 @@ main( int argc, char **argv ) prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog; - while (( i = getopt( argc, argv, "cf:r" "Cd:D:h:kKMnO:p:P:U:vw:WxX:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "cf:r" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) { switch( i ) { /* Delete Specific Options */ case 'c': /* continuous operation mode */ ++contoper; break; case 'f': /* read DNs from a file */ + if( fp != NULL ) { + fprintf( stderr, "%s: -f previously specified\n" ); + return EXIT_FAILURE; + } if (( fp = fopen( optarg, "r" )) == NULL ) { perror( optarg ); exit( EXIT_FAILURE ); @@ -120,9 +129,17 @@ main( int argc, char **argv ) debug |= atoi( optarg ); break; case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n" ); + return EXIT_FAILURE; + } binddn = strdup( optarg ); break; case 'h': /* ldap host */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n" ); + return EXIT_FAILURE; + } ldaphost = strdup( optarg ); break; case 'k': /* kerberos bind */ @@ -179,8 +196,12 @@ main( int argc, char **argv ) break; case 'O': #ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { - fprintf( stderr, "%s -O incompatible with LDAPv%d\n", + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", prog, version ); return EXIT_FAILURE; } @@ -189,9 +210,9 @@ main( int argc, char **argv ) "authentication choice\n", prog ); return EXIT_FAILURE; } - sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -199,6 +220,10 @@ main( int argc, char **argv ) #endif break; case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n" ); + return EXIT_FAILURE; + } ldapport = atoi( optarg ); break; case 'P': @@ -225,8 +250,59 @@ main( int argc, char **argv ) usage( prog ); return( EXIT_FAILURE ); } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LUTIL_SASL_QUIET; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'U': #ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -U incompatible with version %d\n", prog, version ); @@ -240,9 +316,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authc_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -258,7 +332,7 @@ main( int argc, char **argv ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } passwd.bv_len = strlen( passwd.bv_val ); @@ -268,6 +342,10 @@ main( int argc, char **argv ) break; case 'Y': #ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -Y incompatible with version %d\n", prog, version ); @@ -277,9 +355,9 @@ main( int argc, char **argv ) fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); return EXIT_FAILURE; } - authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -296,6 +374,10 @@ main( int argc, char **argv ) break; case 'X': #ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", prog, version ); @@ -308,9 +390,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authz_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -413,6 +493,8 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL + void *defaults; + if( sasl_secprops != NULL ) { rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *) sasl_secprops ); @@ -425,8 +507,16 @@ main( int argc, char **argv ) } } + defaults = lutil_sasl_defaults( ld, sasl_flags, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, - sasl_mech, NULL, NULL, lutil_sasl_interact ); + sasl_mech, NULL, NULL, + lutil_sasl_interact, defaults ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index 3134361851..e5a2af05f2 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -39,6 +39,8 @@ static struct berval passwd = { 0, NULL }; static char *ldaphost = NULL; static int ldapport = 0; #ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LUTIL_SASL_AUTOMATIC; +static char *sasl_realm = NULL; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; @@ -109,12 +111,15 @@ usage( const char *prog ) " -D dn\t\tbind DN\n" " -f file\t\tread operations from `file'\n" " -h host\t\tLDAP server\n" +" -I\t\tuse SASL Interactive mode\n" " -k\t\tuse Kerberos authentication\n" " -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" " -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" " -n\t\tprint changes, don't actually do them\n" " -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" +" -Q\t\tuse SASL Quiet mode\n" +" -R realm\tSASL realm\n" " -U user\t\tSASL authentication identity (username)\n" " -v\t\tverbose mode\n" " -w passwd\tbind password (for Simple authentication)\n" @@ -151,7 +156,7 @@ main( int argc, char **argv ) authmethod = -1; version = -1; - while (( i = getopt( argc, argv, "acrf:F" "Cd:D:h:kKMnO:p:P:U:vw:WxX:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "acrf:F" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) { switch( i ) { /* Modify Options */ case 'a': /* add */ @@ -161,6 +166,10 @@ main( int argc, char **argv ) contoper = 1; break; case 'f': /* read from file */ + if( infile != NULL ) { + fprintf( stderr, "%s: -f previously specified\n" ); + return EXIT_FAILURE; + } infile = strdup( optarg ); break; case 'F': /* force all changes records to be used */ @@ -178,9 +187,17 @@ main( int argc, char **argv ) debug |= atoi( optarg ); break; case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n" ); + return EXIT_FAILURE; + } binddn = strdup( optarg ); break; case 'h': /* ldap host */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n" ); + return EXIT_FAILURE; + } ldaphost = strdup( optarg ); break; case 'k': /* kerberos bind */ @@ -237,8 +254,12 @@ main( int argc, char **argv ) break; case 'O': #ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { - fprintf( stderr, "%s -O incompatible with LDAPv%d\n", + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", prog, version ); return EXIT_FAILURE; } @@ -247,9 +268,9 @@ main( int argc, char **argv ) "authentication choice\n", prog ); return EXIT_FAILURE; } - sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -257,6 +278,10 @@ main( int argc, char **argv ) #endif break; case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n" ); + return EXIT_FAILURE; + } ldapport = atoi( optarg ); break; case 'P': @@ -283,8 +308,59 @@ main( int argc, char **argv ) usage( prog ); return( EXIT_FAILURE ); } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LUTIL_SASL_QUIET; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'U': #ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -U incompatible with version %d\n", prog, version ); @@ -298,9 +374,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authc_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -316,7 +390,7 @@ main( int argc, char **argv ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } passwd.bv_len = strlen( passwd.bv_val ); @@ -326,6 +400,10 @@ main( int argc, char **argv ) break; case 'Y': #ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -Y incompatible with version %d\n", prog, version ); @@ -335,9 +413,9 @@ main( int argc, char **argv ) fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); return EXIT_FAILURE; } - authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -354,6 +432,10 @@ main( int argc, char **argv ) break; case 'X': #ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", prog, version ); @@ -366,9 +448,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authz_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -477,6 +557,8 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL + void *defaults; + if( sasl_secprops != NULL ) { rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *) sasl_secprops ); @@ -489,8 +571,16 @@ main( int argc, char **argv ) } } + defaults = lutil_sasl_defaults( ld, sasl_flags, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, - sasl_mech, NULL, NULL, lutil_sasl_interact ); + sasl_mech, NULL, NULL, + lutil_sasl_interact, defaults ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index cc8cc724fa..101a651c65 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -37,6 +37,8 @@ static struct berval passwd = { 0, NULL }; static char *ldaphost = NULL; static int ldapport = 0; #ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LUTIL_SASL_AUTOMATIC; +static char *sasl_realm = NULL; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; @@ -73,6 +75,7 @@ usage( const char *s ) " -d level\tset LDAP debugging level to `level'\n" " -D binddn\tbind DN\n" " -h host\t\tLDAP server\n" +" -I\t\tuse SASL Interactive mode\n" " -k\t\tuse Kerberos authentication\n" " -K\t\tlike -k, but do only step 1 of the Kerberos bind\n" " -M\t\tenable Manage DSA IT control (-MM to make it critical)\n" @@ -80,6 +83,8 @@ usage( const char *s ) " -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" " -P version\tprocotol version (default: 3)\n" +" -Q\t\tuse SASL Quiet mode\n" +" -R realm\tSASL realm\n" " -U user\t\tSASL authentication identity (username)\n" " -v\t\trun in verbose mode (diagnostics to standard output)\n" " -w passwd\tbind passwd (for simple authentication)\n" @@ -109,12 +114,22 @@ main(int argc, char **argv) prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog; - while (( i = getopt( argc, argv, "cf:rs:" "Cd:D:h:kKMnO:p:P:U:vw:WxX:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "cf:rs:" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z" )) != EOF ) { switch( i ) { /* Modrdn Options */ case 'c': contoper++; break; + case 'f': /* read from file */ + if( infile != NULL ) { + fprintf( stderr, "%s: -f previously specified\n" ); + return EXIT_FAILURE; + } + infile = strdup( optarg ); + break; + case 'r': /* remove old RDN */ + remove++; + break; case 's': /* newSuperior */ if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", @@ -124,9 +139,6 @@ main(int argc, char **argv) newSuperior = strdup( optarg ); version = LDAP_VERSION3; break; - case 'r': /* remove old RDN */ - remove++; - break; /* Common Options */ case 'C': @@ -136,9 +148,17 @@ main(int argc, char **argv) debug |= atoi( optarg ); break; case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n" ); + return EXIT_FAILURE; + } binddn = strdup( optarg ); break; case 'h': /* ldap host */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n" ); + return EXIT_FAILURE; + } ldaphost = strdup( optarg ); break; case 'k': /* kerberos bind */ @@ -195,8 +215,12 @@ main(int argc, char **argv) break; case 'O': #ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { - fprintf( stderr, "%s -O incompatible with LDAPv%d\n", + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", prog, version ); return EXIT_FAILURE; } @@ -205,9 +229,9 @@ main(int argc, char **argv) "authentication choice\n", prog ); return EXIT_FAILURE; } - sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -215,6 +239,10 @@ main(int argc, char **argv) #endif break; case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n" ); + return EXIT_FAILURE; + } ldapport = atoi( optarg ); break; case 'P': @@ -241,8 +269,59 @@ main(int argc, char **argv) usage( prog ); return( EXIT_FAILURE ); } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LUTIL_SASL_QUIET; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'U': #ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -U incompatible with version %d\n", prog, version ); @@ -256,9 +335,7 @@ main(int argc, char **argv) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authc_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -274,7 +351,7 @@ main(int argc, char **argv) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } passwd.bv_len = strlen( passwd.bv_val ); @@ -284,6 +361,10 @@ main(int argc, char **argv) break; case 'Y': #ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -Y incompatible with version %d\n", prog, version ); @@ -293,9 +374,9 @@ main(int argc, char **argv) fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); return EXIT_FAILURE; } - authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -312,6 +393,10 @@ main(int argc, char **argv) break; case 'X': #ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", prog, version ); @@ -324,9 +409,7 @@ main(int argc, char **argv) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authz_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -444,6 +527,8 @@ main(int argc, char **argv) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL + void *defaults; + if( sasl_secprops != NULL ) { rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *) sasl_secprops ); @@ -456,8 +541,16 @@ main(int argc, char **argv) } } + defaults = lutil_sasl_defaults( ld, sasl_flags, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, - sasl_mech, NULL, NULL, lutil_sasl_interact ); + sasl_mech, NULL, NULL, + lutil_sasl_interact, defaults ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 124ed1d425..be5f5d1b11 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -42,9 +42,12 @@ usage(const char *s) " -C\t\tchase referrals\n" " -D binddn\tbind DN\n" " -h host\t\tLDAP server (default: localhost)\n" +" -I\t\tuse SASL Interactive mode\n" " -n\t\tmake no modifications\n" " -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" +" -Q\t\tuse SASL Quiet mode\n" +" -R realm\tSASL realm\n" " -U user\t\tSASL authentication identity (username)\n" " -v\t\tverbose mode\n" " -w passwd\tbind password (for simple authentication)\n" @@ -76,13 +79,16 @@ main( int argc, char *argv[] ) int want_newpw = 0; int want_oldpw = 0; - int noupdates = 0; + int not = 0; int i; int ldapport = 0; int debug = 0; int version = -1; int authmethod = -1; + int manageDSAit = 0; #ifdef HAVE_CYRUS_SASL + unsigned sasl_flags = LUTIL_SASL_AUTOMATIC; + char *sasl_realm = NULL; char *sasl_authc_id = NULL; char *sasl_authz_id = NULL; char *sasl_mech = NULL; @@ -105,7 +111,7 @@ main( int argc, char *argv[] ) usage (argv[0]); while( (i = getopt( argc, argv, - "Aa:Ss:" "Cd:D:h:nO:p:U:vw:WxX:Y:Z" )) != EOF ) + "Aa:Ss:" "Cd:D:h:InO:p:QRU:vw:WxX:Y:Z" )) != EOF ) { switch (i) { /* Password Options */ @@ -120,7 +126,7 @@ main( int argc, char *argv[] ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } break; @@ -135,116 +141,303 @@ main( int argc, char *argv[] ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } break; - /* Common Options */ - case 'C': - referrals++; - break; - - case 'D': /* bind distinguished name */ - binddn = strdup (optarg); - break; - - case 'd': /* debugging option */ - debug |= atoi (optarg); - break; - - case 'h': /* ldap host */ - ldaphost = strdup (optarg); - break; - - case 'n': /* don't update entry(s) */ - noupdates++; - break; - - case 'p': /* ldap port */ - ldapport = strtol( optarg, NULL, 10 ); - break; + /* Common Options (including options we don't use) */ + case 'C': + referrals++; + break; + case 'd': + debug |= atoi( optarg ); + break; + case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n" ); + return EXIT_FAILURE; + } + binddn = strdup( optarg ); + break; + case 'h': /* ldap host */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n" ); + return EXIT_FAILURE; + } + ldaphost = strdup( optarg ); + break; + case 'k': /* kerberos bind */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } - case 'v': /* verbose */ - verbose++; - break; + if( authmethod != -1 ) { + fprintf( stderr, "%s: -k incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + + authmethod = LDAP_AUTH_KRBV4; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return EXIT_FAILURE; +#endif + break; + case 'K': /* kerberos bind, part one only */ +#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND + if( version > LDAP_VERSION2 ) { + fprintf( stderr, "%s: -k incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } - case 'W': /* prompt for bind password */ - want_bindpw++; + authmethod = LDAP_AUTH_KRBV41; +#else + fprintf( stderr, "%s: not compiled with Kerberos support\n", prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'M': + /* enable Manage DSA IT */ + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -M incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + manageDSAit++; + version = LDAP_VERSION3; + break; + case 'n': /* print deletes, don't actually do them */ + ++not; + break; + case 'O': +#ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); +#else + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n" ); + return EXIT_FAILURE; + } + ldapport = atoi( optarg ); + break; + case 'P': + switch( atoi(optarg) ) { + case 2: + if( version == LDAP_VERSION3 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION2; break; - - case 'w': /* bind password */ - passwd.bv_val = strdup (optarg); - { - char* p; - - for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; - } + case 3: + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -P 2 incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; } - passwd.bv_len = strlen( passwd.bv_val ); + version = LDAP_VERSION3; break; - - case 'O': + default: + fprintf( stderr, "%s: protocol version should be 2 or 3\n", + prog ); + usage( prog ); + return( EXIT_FAILURE ); + } break; + case 'Q': #ifdef HAVE_CYRUS_SASL - sasl_secprops = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LUTIL_SASL_QUIET; #else - fprintf( stderr, "%s was not compiled with SASL support\n", - argv[0] ); - return( EXIT_FAILURE ); + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); #endif - break; - case 'Y': + case 'R': #ifdef HAVE_CYRUS_SASL - if ( strcasecmp( optarg, "any" ) && - strcmp( optarg, "*" ) ) { - sasl_mech = strdup( optarg ); - } - authmethod = LDAP_AUTH_SASL; + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); #else - fprintf( stderr, "%s was not compiled with SASL " - "support\n", argv[0] ); - return( EXIT_FAILURE ); + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); #endif - break; - case 'U': + break; + case 'U': #ifdef HAVE_CYRUS_SASL - sasl_authc_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -U incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authc_id = strdup( optarg ); #else - fprintf( stderr, "%s was not compiled with SASL " - "support\n", argv[0] ); - return( EXIT_FAILURE ); + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); #endif - break; - case 'x': - if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) { - fprintf( stderr, "%s: incompatible with previous " - "authentication choice\n", prog ); - return EXIT_FAILURE; + break; + case 'v': /* verbose mode */ + verbose++; + break; + case 'w': /* password */ + passwd.bv_val = strdup( optarg ); + { + char* p; + + for( p = optarg; *p == '\0'; p++ ) { + *p = '\0'; } - authmethod = LDAP_AUTH_SIMPLE; - break; - case 'X': + } + passwd.bv_len = strlen( passwd.bv_val ); + break; + case 'W': + want_bindpw++; + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Y incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; + case 'x': + if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) { + fprintf( stderr, "%s: incompatible with previous " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SIMPLE; + break; + case 'X': #ifdef HAVE_CYRUS_SASL - sasl_authz_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: -X incompatible with " + "authentication choice\n", prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_authz_id = strdup( optarg ); #else - fprintf( stderr, "%s was not compiled with SASL " - "support\n", argv[0] ); - return( EXIT_FAILURE ); + fprintf( stderr, "%s: not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); #endif - break; - case 'Z': + break; + case 'Z': #ifdef HAVE_TLS - use_tls++; + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s -Z incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + version = LDAP_VERSION3; + use_tls++; #else - fprintf( stderr, "%s was not compiled with TLS " - "support\n", argv[0] ); - return( EXIT_FAILURE ); + fprintf( stderr, "%s: not compiled with TLS support\n", + prog ); + return( EXIT_FAILURE ); #endif - break; + break; + default: fprintf( stderr, "%s: unrecongized option -%c\n", @@ -359,6 +552,8 @@ main( int argc, char *argv[] ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL + void *defaults; + if( sasl_secprops != NULL ) { rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *) sasl_secprops ); @@ -371,8 +566,16 @@ main( int argc, char *argv[] ) } } + defaults = lutil_sasl_defaults( ld, sasl_flags, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, - sasl_mech, NULL, NULL, lutil_sasl_interact ); + sasl_mech, NULL, NULL, + lutil_sasl_interact, defaults ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); @@ -435,7 +638,7 @@ main( int argc, char *argv[] ) ber_free( ber, 1 ); } - if ( noupdates ) { + if ( not ) { rc = LDAP_SUCCESS; goto skip; } diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index 4b51feb1f3..01f0510584 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -68,6 +68,7 @@ usage( const char *s ) "\t-D binddn\tbind DN\n" "\t-f file\t\tread operations from `file'\n" "\t-h host\t\tLDAP server\n" +"\t-I\t\tuse SASL Interactive mode\n" "\t-k\t\tuse Kerberos authentication\n" "\t-K\t\tlike -k, but do only step 1 of the Kerberos bind\n" "\t-M\t\tenable Manage DSA IT control (-MM to make critical)\n" @@ -75,6 +76,8 @@ usage( const char *s ) "\t-O secprops\tSASL security properties\n" "\t-p port\t\tport on LDAP server\n" "\t-P version\tprocotol version (default: 3)\n" +"\t-Q\t\tuse SASL Quiet mode\n" +"\t-R realm\tSASL realm\n" "\t-U user\t\tSASL authentication identity (username)\n" "\t-v\t\trun in verbose mode (diagnostics to standard output)\n" "\t-V prefix\tURL prefix for files (default: \"" LDAP_FILE_URI_PREFIX ")\n" @@ -143,6 +146,8 @@ static char *base = NULL; static char *ldaphost = NULL; static int ldapport = 0; #ifdef HAVE_CYRUS_SASL +static unsigned sasl_flags = LUTIL_SASL_AUTOMATIC; +static char *sasl_realm = NULL; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; @@ -174,7 +179,7 @@ main( int argc, char **argv ) prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog; while (( i = getopt( argc, argv, - "Aa:b:f:Ll:S:s:T:tuV:z:" "Cd:D:h:kKMnO:p:P:U:vw:WxX:Y:Z")) != EOF ) + "Aa:b:f:Ll:S:s:T:tuV:z:" "Cd:D:h:IkKMnO:p:P:QRU:vw:WxX:Y:Z")) != EOF ) { switch( i ) { /* Search Options */ @@ -199,6 +204,10 @@ main( int argc, char **argv ) base = strdup( optarg ); break; case 'f': /* input file */ + if( infile != NULL ) { + fprintf( stderr, "%s: -f previously specified\n" ); + return EXIT_FAILURE; + } infile = strdup( optarg ); break; case 'l': /* time limit */ @@ -248,9 +257,17 @@ main( int argc, char **argv ) debug |= atoi( optarg ); break; case 'D': /* bind DN */ + if( binddn != NULL ) { + fprintf( stderr, "%s: -D previously specified\n" ); + return EXIT_FAILURE; + } binddn = strdup( optarg ); break; case 'h': /* ldap host */ + if( ldaphost != NULL ) { + fprintf( stderr, "%s: -h previously specified\n" ); + return EXIT_FAILURE; + } ldaphost = strdup( optarg ); break; case 'k': /* kerberos bind */ @@ -307,8 +324,12 @@ main( int argc, char **argv ) break; case 'O': #ifdef HAVE_CYRUS_SASL + if( sasl_secprops != NULL ) { + fprintf( stderr, "%s: -O previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { - fprintf( stderr, "%s -O incompatible with LDAPv%d\n", + fprintf( stderr, "%s: -O incompatible with LDAPv%d\n", prog, version ); return EXIT_FAILURE; } @@ -317,9 +338,9 @@ main( int argc, char **argv ) "authentication choice\n", prog ); return EXIT_FAILURE; } - sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_secprops = strdup( optarg ); #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -327,6 +348,10 @@ main( int argc, char **argv ) #endif break; case 'p': + if( ldapport ) { + fprintf( stderr, "%s: -p previously specified\n" ); + return EXIT_FAILURE; + } ldapport = atoi( optarg ); break; case 'P': @@ -353,8 +378,59 @@ main( int argc, char **argv ) usage( prog ); return( EXIT_FAILURE ); } break; + case 'Q': +#ifdef HAVE_CYRUS_SASL + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -Q incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_flags = LUTIL_SASL_QUIET; +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + case 'R': +#ifdef HAVE_CYRUS_SASL + if( sasl_realm != NULL ) { + fprintf( stderr, "%s: -R previously specified\n" ); + return EXIT_FAILURE; + } + if( version == LDAP_VERSION2 ) { + fprintf( stderr, "%s: -R incompatible with version %d\n", + prog, version ); + return EXIT_FAILURE; + } + if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) { + fprintf( stderr, "%s: incompatible previous " + "authentication choice\n", + prog ); + return EXIT_FAILURE; + } + authmethod = LDAP_AUTH_SASL; + version = LDAP_VERSION3; + sasl_realm = strdup( optarg ); +#else + fprintf( stderr, "%s: was not compiled with SASL support\n", + prog ); + return( EXIT_FAILURE ); +#endif + break; case 'U': #ifdef HAVE_CYRUS_SASL + if( sasl_authc_id != NULL ) { + fprintf( stderr, "%s: -U previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -U incompatible with version %d\n", prog, version ); @@ -368,9 +444,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authc_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -386,7 +460,7 @@ main( int argc, char **argv ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } passwd.bv_len = strlen( passwd.bv_val ); @@ -396,6 +470,10 @@ main( int argc, char **argv ) break; case 'Y': #ifdef HAVE_CYRUS_SASL + if( sasl_mech != NULL ) { + fprintf( stderr, "%s: -Y previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -Y incompatible with version %d\n", prog, version ); @@ -405,9 +483,9 @@ main( int argc, char **argv ) fprintf( stderr, "%s: incompatible with authentication choice\n", prog ); return EXIT_FAILURE; } - authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; + sasl_mech = strdup( optarg ); #else fprintf( stderr, "%s: was not compiled with SASL support\n", prog ); @@ -424,6 +502,10 @@ main( int argc, char **argv ) break; case 'X': #ifdef HAVE_CYRUS_SASL + if( sasl_authz_id != NULL ) { + fprintf( stderr, "%s: -X previously specified\n" ); + return EXIT_FAILURE; + } if( version == LDAP_VERSION2 ) { fprintf( stderr, "%s: -X incompatible with LDAPv%d\n", prog, version ); @@ -436,9 +518,7 @@ main( int argc, char **argv ) } authmethod = LDAP_AUTH_SASL; version = LDAP_VERSION3; - sasl_authz_id = strdup( optarg ); - authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s: not compiled with SASL support\n", prog ); @@ -604,6 +684,8 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL + void *defaults; + if( sasl_secprops != NULL ) { rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *) sasl_secprops ); @@ -616,8 +698,16 @@ main( int argc, char **argv ) } } + defaults = lutil_sasl_defaults( ld, sasl_flags, + sasl_mech, + sasl_realm, + sasl_authc_id, + passwd.bv_val, + sasl_authz_id ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, - sasl_mech, NULL, NULL, lutil_sasl_interact ); + sasl_mech, NULL, NULL, + lutil_sasl_interact, defaults ); if( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); diff --git a/include/ldap.h b/include/ldap.h index 75322dd8a6..33479405cd 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -131,13 +131,16 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_TRY 4 /* OpenLDAP SASL options */ -#define LDAP_OPT_X_SASL_SSF 0x6100 /* read-only */ -#define LDAP_OPT_X_SASL_SSF_EXTERNAL 0x6101 /* write-only */ -#define LDAP_OPT_X_SASL_SECPROPS 0x6102 /* write-only */ - -#define LDAP_OPT_X_SASL_SSF_MIN 0x6103 -#define LDAP_OPT_X_SASL_SSF_MAX 0x6104 -#define LDAP_OPT_X_SASL_MAXBUFSIZE 0x6105 +#define LDAP_OPT_X_SASL_MECH 0x6100 +#define LDAP_OPT_X_SASL_REALM 0x6101 +#define LDAP_OPT_X_SASL_AUTHCID 0x6102 +#define LDAP_OPT_X_SASL_AUTHZID 0x6103 +#define LDAP_OPT_X_SASL_SSF 0x6104 /* read-only */ +#define LDAP_OPT_X_SASL_SSF_EXTERNAL 0x6105 /* write-only */ +#define LDAP_OPT_X_SASL_SECPROPS 0x6106 /* write-only */ +#define LDAP_OPT_X_SASL_SSF_MIN 0x6107 +#define LDAP_OPT_X_SASL_SSF_MAX 0x6108 +#define LDAP_OPT_X_SASL_MAXBUFSIZE 0x6109 /* on/off values */ @@ -695,7 +698,7 @@ ldap_sasl_bind LDAP_P(( /* V3 SASL Interaction Function Callback Prototype */ /* when using Cyrus SASL, interact is pointer to sasl_interact_t */ typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P(( - LDAP *ld, void *interact )); + LDAP *ld, void* defaults, void *interact )); LDAP_F( int ) ldap_sasl_interactive_bind_s LDAP_P(( @@ -704,7 +707,8 @@ ldap_sasl_interactive_bind_s LDAP_P(( LDAP_CONST char *saslMechanism, LDAPControl **serverControls, LDAPControl **clientControls, - LDAP_SASL_INTERACT_PROC *proc )); + LDAP_SASL_INTERACT_PROC *proc, + LDAP_CONST void *defaults )); LDAP_F( int ) ldap_sasl_bind_s LDAP_P(( diff --git a/include/lutil_ldap.h b/include/lutil_ldap.h index 86da3ae3c3..0c5467c0e5 100644 --- a/include/lutil_ldap.h +++ b/include/lutil_ldap.h @@ -21,9 +21,28 @@ LDAP_BEGIN_DECL +/* + * Automatic (default): use defaults, prompt otherwise + * Interactive: prompt always + * Quiet: never prompt + */ +#define LUTIL_SASL_AUTOMATIC 0U +#define LUTIL_SASL_INTERACTIVE 1U +#define LUTIL_SASL_QUIET 2U + +LDAP_LUTIL_F( void * ) +lutil_sasl_defaults LDAP_P(( + LDAP *ld, + unsigned flags, + char *mech, + char *realm, + char *authcid, + char *passwd, + char *authzid )); + LDAP_LUTIL_F( int ) lutil_sasl_interact LDAP_P(( - LDAP *ld, void *p )); + LDAP *ld, void *defaults, void *p )); LDAP_END_DECL diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c index 7a34bbe407..c6058fca2a 100644 --- a/libraries/libldap/cyrus.c +++ b/libraries/libldap/cyrus.c @@ -455,7 +455,8 @@ ldap_int_sasl_bind( const char *mechs, LDAPControl **sctrls, LDAPControl **cctrls, - LDAP_SASL_INTERACT_PROC *interact ) + LDAP_SASL_INTERACT_PROC *interact, + void * defaults ) { char *data; const char *mech = NULL; @@ -525,7 +526,7 @@ ldap_int_sasl_bind( if( saslrc == SASL_INTERACT ) { if( !interact ) break; - rc = (interact)( ld, prompts ); + rc = (interact)( ld, defaults, prompts ); if( rc != LDAP_SUCCESS ) { break; } @@ -574,7 +575,7 @@ ldap_int_sasl_bind( if( saslrc == SASL_INTERACT ) { int res; if( !interact ) break; - res = (interact)( ld, prompts ); + res = (interact)( ld, defaults, prompts ); if( res != LDAP_SUCCESS ) { break; } @@ -740,6 +741,23 @@ ldap_int_sasl_get_option( LDAP *ld, int option, void *arg ) return -1; switch ( option ) { + case LDAP_OPT_X_SASL_MECH: { + *(char **)arg = ld->ld_options.ldo_def_sasl_mech + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_mech ) : NULL; + } break; + case LDAP_OPT_X_SASL_REALM: { + *(char **)arg = ld->ld_options.ldo_def_sasl_realm + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_realm ) : NULL; + } break; + case LDAP_OPT_X_SASL_AUTHCID: { + *(char **)arg = ld->ld_options.ldo_def_sasl_authcid + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authcid ) : NULL; + } break; + case LDAP_OPT_X_SASL_AUTHZID: { + *(char **)arg = ld->ld_options.ldo_def_sasl_authzid + ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL; + } break; + case LDAP_OPT_X_SASL_SSF: { int sc; sasl_ssf_t *ssf; diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index b7558f75ec..164761b6ed 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -69,17 +69,25 @@ static const struct ol_attribute { {0, ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, #ifdef HAVE_CYRUS_SASL - {0, ATTR_SASL, "SASL_SECPROPS",NULL, LDAP_OPT_X_SASL_SECPROPS}, + {1, ATTR_STRING, "SASL_MECH", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_mech)}, + {1, ATTR_STRING, "SASL_REALM", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_realm)}, + {1, ATTR_STRING, "SASL_AUTHCID", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_authcid)}, + {1, ATTR_STRING, "SASL_AUTHZID", NULL, + offsetof(struct ldapoptions, ldo_def_sasl_authzid)}, + {0, ATTR_SASL, "SASL_SECPROPS", NULL, LDAP_OPT_X_SASL_SECPROPS}, #endif #ifdef HAVE_TLS {0, ATTR_TLS, "TLS", NULL, LDAP_OPT_X_TLS}, - {0, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, - {0, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, + {1, ATTR_TLS, "TLS_CERT", NULL, LDAP_OPT_X_TLS_CERTFILE}, + {1, ATTR_TLS, "TLS_KEY", NULL, LDAP_OPT_X_TLS_KEYFILE}, {0, ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, {0, ATTR_TLS, "TLS_CACERTDIR",NULL, LDAP_OPT_X_TLS_CACERTDIR}, - {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, - {0, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, + {1, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, + {1, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, #endif {0, ATTR_NONE, NULL, NULL, 0} @@ -395,10 +403,12 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS); -#ifdef HAVE_TLS - gopts->ldo_tls_ctx = NULL; -#endif #ifdef HAVE_CYRUS_SASL + gopts->ldo_def_sasl_mech = NULL; + gopts->ldo_def_sasl_realm = NULL; + gopts->ldo_def_sasl_authcid = NULL; + gopts->ldo_def_sasl_authzid = NULL; + memset( &gopts->ldo_sasl_secprops, '\0', sizeof(gopts->ldo_sasl_secprops) ); gopts->ldo_sasl_secprops.max_ssf = INT_MAX; @@ -406,6 +416,10 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl gopts->ldo_sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT|SASL_SEC_NOANONYMOUS; #endif +#ifdef HAVE_TLS + gopts->ldo_tls_ctx = NULL; +#endif + gopts->ldo_valid = LDAP_INITIALIZED; return; @@ -450,6 +464,21 @@ void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) return; } +#ifdef HAVE_CYRUS_SASL + { + /* set authentication identity to current user name */ + char *user = getenv("USER"); + + if( user == NULL ) user = getenv("USERNAME"); + if( user == NULL ) user = getenv("LOGNAME"); + + if( user != NULL ) { + /* this value is leaked, need at_exit() handler */ + gopts->ldo_def_sasl_authcid = LDAP_STRDUP( user ); + } + } +#endif + openldap_ldap_init_w_sysconf(LDAP_CONF_FILE); openldap_ldap_init_w_userconf(LDAP_USERRC_FILE); diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 7b196497ab..51939c3701 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -125,7 +125,17 @@ struct ldapoptions { LDAPURLDesc *ldo_defludp; int ldo_defport; char* ldo_defbase; - char* ldo_defbinddn; /* simple bind dn */ + char* ldo_defbinddn; /* bind dn */ + +#ifdef HAVE_CYRUS_SASL + char* ldo_def_sasl_mech; /* SASL Mechanism(s) */ + char* ldo_def_sasl_realm; /* SASL realm */ + char* ldo_def_sasl_authcid; /* SASL authentication identity */ + char* ldo_def_sasl_authzid; /* SASL authorization identity */ + + /* SASL Security Properties */ + struct sasl_security_properties ldo_sasl_secprops; +#endif #ifdef LDAP_CONNECTIONLESS int ldo_cldaptries; /* connectionless search retry count */ @@ -145,9 +155,6 @@ struct ldapoptions { /* tls context */ void *ldo_tls_ctx; int ldo_tls_mode; -#endif -#ifdef HAVE_CYRUS_SASL - struct sasl_security_properties ldo_sasl_secprops; #endif LDAP_BOOLEANS ldo_booleans; /* boolean options */ }; @@ -545,9 +552,12 @@ LDAP_F (int) ldap_int_sasl_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); LDAP_F (int) ldap_int_sasl_bind LDAP_P(( - struct ldap *, LDAP_CONST char *, - const char *, LDAPControl **, LDAPControl **, - LDAP_SASL_INTERACT_PROC *interact )); + struct ldap *ld, + const char *, + const char *, + LDAPControl **, LDAPControl **, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults)); /* * in tls.c diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index 1e34a73cfe..4ee3c1b269 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -140,10 +140,20 @@ ldap_create( LDAP **ldp ) ld->ld_valid = LDAP_VALID_SESSION; /* but not pointers to malloc'ed items */ - ld->ld_options.ldo_defludp = NULL; ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; +#ifdef HAVE_CYRUS_SASL + ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech + ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; + ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm + ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; + ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid + ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; + ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid + ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; +#endif + ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); if ( ld->ld_options.ldo_defludp == NULL ) { diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index 2660a271aa..c63efd5d0d 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -410,7 +410,8 @@ ldap_sasl_interactive_bind_s( LDAP_CONST char *mechs, LDAPControl **serverControls, LDAPControl **clientControls, - LDAP_SASL_INTERACT_PROC *interact ) + LDAP_SASL_INTERACT_PROC *interact, + void *defaults ) { int rc; @@ -436,7 +437,8 @@ ldap_sasl_interactive_bind_s( } rc = ldap_int_sasl_bind( ld, dn, mechs, - serverControls, clientControls, interact ); + serverControls, clientControls, + interact, defaults ); return rc; } diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c index a005cdf6bc..c1636e639e 100644 --- a/libraries/liblutil/sasl.c +++ b/libraries/liblutil/sasl.c @@ -18,15 +18,80 @@ #include #include "lutil_ldap.h" + +typedef struct lutil_sasl_defaults_s { + unsigned flags; + char *mech; + char *realm; + char *authcid; + char *passwd; + char *authzid; +} lutilSASLdefaults; + + +void * +lutil_sasl_defaults( + LDAP *ld, + unsigned flags, + char *mech, + char *realm, + char *authcid, + char *passwd, + char *authzid ) +{ + lutilSASLdefaults *defaults; + + defaults = ber_memalloc( sizeof( lutilSASLdefaults ) ); + + if( defaults == NULL ) return NULL; + + defaults->flags = flags; + defaults->mech = mech; + defaults->realm = realm; + defaults->authcid = authcid; + defaults->passwd = passwd; + defaults->authzid = authzid; + + if( defaults->mech == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech ); + } + if( defaults->realm == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm ); + } + if( defaults->authcid == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid ); + } + if( defaults->authzid == NULL ) { + ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid ); + } + + return defaults; +} + static int interaction( - sasl_interact_t *interact ) + sasl_interact_t *interact, lutilSASLdefaults *defaults ) { + unsigned flags = defaults ? defaults->flags : 0; + const char *dflt = interact->defresult; char input[1024]; int noecho=0; int challenge=0; switch( interact->id ) { + case SASL_CB_GETREALM: + if( defaults ) dflt = defaults->realm; + break; + case SASL_CB_AUTHNAME: + if( defaults ) dflt = defaults->authcid; + break; + case SASL_CB_PASS: + if( defaults ) dflt = defaults->passwd; + noecho = 1; + break; + case SASL_CB_USER: + if( defaults ) dflt = defaults->authzid; + break; case SASL_CB_NOECHOPROMPT: noecho = 1; challenge = 1; @@ -34,22 +99,31 @@ static int interaction( case SASL_CB_ECHOPROMPT: challenge = 1; break; - case SASL_CB_PASS: - noecho = 1; - break; + } + + if( dflt && !*dflt ) dflt = NULL; + + if( flags != LUTIL_SASL_INTERACTIVE && dflt ) { + goto use_default; + } + + if( flags == LUTIL_SASL_QUIET ) { + /* don't prompt */ + return LDAP_OTHER; } if( challenge ) { if( interact->challenge ) { fprintf( stderr, "Challenge: %s\n", interact->challenge ); } - if( interact->defresult ) { - fprintf( stderr, "Default Result: %s\n", interact->defresult ); - } + } + + if( dflt ) { + fprintf( stderr, "Default: %s\n", dflt ); } sprintf( input, "%s: ", - interact->prompt ? interact->prompt : "Interaction required" ); + interact->prompt ? interact->prompt : "Interact" ); if( noecho ) { interact->result = (char *) getpassphrase( input ); @@ -88,8 +162,17 @@ static int interaction( memset( p, '\0', interact->len ); } else { +use_default: /* must be empty */ - interact->result = strdup(""); + interact->result = strdup( (dflt && *dflt) ? dflt : "" ); + interact->len = interact->result + ? strlen( interact->result ) : 0; + } + + if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) { + /* zap password after first use */ + memset( defaults->passwd, '\0', strlen(defaults->passwd) ); + defaults->passwd = NULL; } return LDAP_SUCCESS; @@ -97,6 +180,7 @@ static int interaction( int lutil_sasl_interact( LDAP *ld, + void *defaults, void *in ) { sasl_interact_t *interact = in; @@ -104,7 +188,7 @@ int lutil_sasl_interact( fputs( "SASL Interaction\n", stderr ); while( interact->id != SASL_CB_LIST_END ) { - int rc = interaction( interact ); + int rc = interaction( interact, defaults ); if( rc ) return rc; interact++; @@ -112,5 +196,4 @@ int lutil_sasl_interact( return LDAP_SUCCESS; } - #endif diff --git a/servers/slapd/tools/slappasswd.c b/servers/slapd/tools/slappasswd.c index 37c32c4e94..c433ab6357 100644 --- a/servers/slapd/tools/slappasswd.c +++ b/servers/slapd/tools/slappasswd.c @@ -63,7 +63,7 @@ main( int argc, char *argv[] ) char* p; for( p = optarg; *p == '\0'; p++ ) { - *p = '*'; + *p = '\0'; } } break; -- 2.39.5