From 5fc22599e2e875c9620b63fbf465273fba3c378f Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Thu, 13 Jul 2000 22:54:38 +0000 Subject: [PATCH] Update SASL code to reuse context through life of session. Replace 'negotiated' with 'interactive' bind Add hooks for SASL/EXTERNAL Disable SASL security layers Rework SASL command line and config file parameters --- clients/gopher/go500.c | 3 +- clients/gopher/go500gw.c | 3 +- clients/tools/ldapdelete.c | 68 +- clients/tools/ldapmodify.c | 68 +- clients/tools/ldapmodrdn.c | 68 +- clients/tools/ldappasswd.c | 69 +- clients/tools/ldapsearch.c | 63 +- configure | 98 +-- configure.in | 98 +-- doc/devel/args | 16 +- doc/man/man5/ldap.conf.5 | 3 + include/ldap.h | 26 +- include/ldap_pvt.h | 40 +- libraries/libldap/Makefile.in | 4 +- libraries/libldap/charray.c | 45 ++ libraries/libldap/cyrus.c | 874 ++++++++++++++++++++++ libraries/libldap/init.c | 75 +- libraries/libldap/ldap-int.h | 59 +- libraries/libldap/ldap.conf | 3 - libraries/libldap/open.c | 85 ++- libraries/libldap/options.c | 15 +- libraries/libldap/os-ip.c | 117 +-- libraries/libldap/request.c | 6 +- libraries/libldap/sasl.c | 712 +----------------- libraries/libldap/tls.c | 9 +- libraries/libldap/unbind.c | 6 - libraries/libldap_r/Makefile.in | 4 +- libraries/liblutil/Makefile.in | 4 +- libraries/liblutil/authpasswd.c | 6 +- libraries/liblutil/passwd.c | 4 +- libraries/liblutil/sasl.c | 114 +++ servers/slapd/back-dnssrv/init.c | 6 - servers/slapd/back-ldap/init.c | 6 - servers/slapd/back-ldbm/init.c | 6 - servers/slapd/back-ldbm/proto-back-ldbm.h | 24 - servers/slapd/back-ldbm/sasl.c | 3 +- servers/slapd/back-passwd/init.c | 6 - servers/slapd/back-perl/init.c | 6 - servers/slapd/back-shell/init.c | 6 - servers/slapd/bind.c | 58 +- servers/slapd/config.c | 31 +- servers/slapd/connection.c | 29 +- servers/slapd/daemon.c | 17 +- servers/slapd/init.c | 12 +- servers/slapd/proto-slap.h | 28 +- servers/slapd/root_dse.c | 8 +- servers/slapd/sasl.c | 420 ++++++----- servers/slapd/search.c | 2 +- servers/slapd/slap.h | 47 +- servers/slapd/tools/mimic.c | 25 +- tests/data/slapd-dnssrv.conf | 4 + 51 files changed, 1931 insertions(+), 1578 deletions(-) create mode 100644 libraries/libldap/cyrus.c create mode 100644 libraries/liblutil/sasl.c diff --git a/clients/gopher/go500.c b/clients/gopher/go500.c index 34b3e1a5ef..51a3dbb903 100644 --- a/clients/gopher/go500.c +++ b/clients/gopher/go500.c @@ -139,11 +139,12 @@ main( int argc, char **argv ) #ifdef GO500_HOSTNAME strcpy( myhost, GO500_HOSTNAME ); #else - if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) ) + if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 ) == -1 ) { perror( "gethostname" ); exit( EXIT_FAILURE ); } + myhost[sizeof(myhost)-1] = '\0'; #endif #ifdef HAVE_SYSCONF diff --git a/clients/gopher/go500gw.c b/clients/gopher/go500gw.c index fc9fa853ee..4943f97a8d 100644 --- a/clients/gopher/go500gw.c +++ b/clients/gopher/go500gw.c @@ -176,11 +176,12 @@ main (int argc, char **argv ) #ifdef GO500GW_HOSTNAME strcpy( myhost, GO500GW_HOSTNAME ); #else - if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) ) + if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 ) == -1 ) { perror( "gethostname" ); exit( EXIT_FAILURE ); } + myhost[sizeof(myhost)-1] = '\0'; #endif /* detach if stderr is redirected or no debugging */ diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index 200d9f2a21..092ddcfdd8 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -17,9 +17,10 @@ #include #include +#include "lutil_ldap.h" static char *binddn = NULL; -static struct berval passwd = { 0, NULL}; +static struct berval passwd = { 0, NULL }; static char *ldaphost = NULL; static int ldapport = 0; static int prune = 0; @@ -27,8 +28,7 @@ static int prune = 0; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; -static int sasl_integrity = 0; -static int sasl_privacy = 0; +static char *sasl_secprops = NULL; #endif static int use_tls = 0; static int not, verbose, contoper; @@ -55,15 +55,13 @@ usage( const char *s ) " -C\t\tchase referrals\n" " -d level\tset LDAP debugging level to `level'\n" " -D binddn\tbind DN\n" -" -E\t\trequest SASL privacy (-EE to make it critical)\n" " -f file\t\tdelete DNs listed in `file'\n" " -h host\t\tLDAP server\n" -" -I\t\trequest SASL integrity checking (-II to make it\n" -" \tcritical)\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\tshow what would be done but don't actually delete\n" +" -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" " -P version\tprocotol version (default: 3)\n" " -r\t\tdelete recursively\n" @@ -92,7 +90,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "cCD:d:Ef:h:IKMnP:p:rU:vWw:X:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "cCD:d:f:h:KMnO:P:p:rU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND @@ -176,19 +174,9 @@ main( int argc, char **argv ) return( EXIT_FAILURE ); } break; - case 'I': + case 'O': #ifdef HAVE_CYRUS_SASL - sasl_integrity++; - authmethod = LDAP_AUTH_SASL; -#else - fprintf( stderr, "%s was not compiled with SASL support\n", - argv[0] ); - return( EXIT_FAILURE ); -#endif - break; - case 'E': -#ifdef HAVE_CYRUS_SASL - sasl_privacy++; + sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s was not compiled with SASL support\n", @@ -341,37 +329,25 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - int minssf = 0, maxssf = 0; - - if ( sasl_integrity > 0 ) - maxssf = 1; - if ( sasl_integrity > 1 ) - minssf = 1; - if ( sasl_privacy > 0 ) - maxssf = 100000; /* Something big value */ - if ( sasl_privacy > 1 ) - minssf = 56; - - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, - (void *)&minssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); - } - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, - (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" - "%d\n", maxssf); - return( EXIT_FAILURE ); + ldap_set_sasl_interact_proc( ld, lutil_sasl_interact ); + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } } - rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, - sasl_authz_id, sasl_mech, - passwd.bv_len ? &passwd : NULL, - NULL, NULL ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL ); if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); return( EXIT_FAILURE ); } #else diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index 18385bffb7..27262e80b1 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -29,20 +29,20 @@ #include +#include "lutil_ldap.h" #include "ldif.h" #include "ldap_defaults.h" static char *prog; static char *binddn = NULL; -static struct berval passwd = { 0, NULL}; +static struct berval passwd = { 0, NULL }; static char *ldaphost = NULL; static int ldapport = 0; #ifdef HAVE_CYRUS_SASL static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; -static int sasl_integrity = 0; -static int sasl_privacy = 0; +static char *sasl_secprops = NULL; #endif static int use_tls = 0; static int ldapadd, replace, not, verbose, contoper, force; @@ -104,16 +104,14 @@ usage( const char *prog ) " -C\t\tchase referrals\n" " -d level\tset LDAP debugging level to `level'\n" " -D dn\t\tbind DN\n" -" -E\t\trequest SASL privacy (-EE to make it critical)\n" " -f file\t\tperform sequence of operations listed in file\n" " -F\t\tforce all changes records to be used\n" " -h host\t\tLDAP server\n" -" -I\t\trequest SASL integrity checking (-II to make it\n" -" \tcritical)\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" " -r\t\treplace values\n" " -U user\t\tSASL authentication identity (username)\n" @@ -151,7 +149,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "acCD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "acCD:d:Ff:h:KkMnO:P:p:rtU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'a': /* add */ ldapadd = 1; @@ -237,19 +235,9 @@ main( int argc, char **argv ) usage( argv[0] ); } break; - case 'I': + case 'O': #ifdef HAVE_CYRUS_SASL - sasl_integrity++; - authmethod = LDAP_AUTH_SASL; -#else - fprintf( stderr, "%s was not compiled with SASL support\n", - argv[0] ); - return( EXIT_FAILURE ); -#endif - break; - case 'E': -#ifdef HAVE_CYRUS_SASL - sasl_privacy++; + sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s was not compiled with SASL support\n", @@ -404,37 +392,25 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - int minssf = 0, maxssf = 0; - - if ( sasl_integrity > 0 ) - maxssf = 1; - if ( sasl_integrity > 1 ) - minssf = 1; - if ( sasl_privacy > 0 ) - maxssf = 100000; /* Something big value */ - if ( sasl_privacy > 1 ) - minssf = 56; - - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, - (void *)&minssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); - } - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, - (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); + ldap_set_sasl_interact_proc( ld, lutil_sasl_interact ); + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } } - rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, - sasl_authz_id, sasl_mech, - passwd.bv_len ? &passwd : NULL, - NULL, NULL ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL ); if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); return( EXIT_FAILURE ); } #else diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index 142efb62dc..96604926c2 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -29,17 +29,17 @@ #include #include +#include "lutil_ldap.h" static char *binddn = NULL; -static struct berval passwd = { 0, NULL}; +static struct berval passwd = { 0, NULL }; static char *ldaphost = NULL; static int ldapport = 0; #ifdef HAVE_CYRUS_SASL static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; -static int sasl_integrity = 0; -static int sasl_privacy = 0; +static char *sasl_secprops = NULL; #endif static int use_tls = 0; static int not, verbose, contoper; @@ -66,15 +66,13 @@ usage( const char *s ) " -C\t\tchase referrals\n" " -d level\tset LDAP debugging level to `level'\n" " -D binddn\tbind DN\n" -" -E\t\trequest SASL privacy (-EE to make it critical)\n" " -f file\t\tdo renames listed in `file'\n" " -h host\t\tLDAP server\n" -" -I\t\trequest SASL integrity checking (-II to make it\n" -" \tcritical)\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\tshow what would be done but don't actually do it\n" +" -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" " -P version\tprocotol version (default: 3)\n" " -r\t\tremove old RDN\n" @@ -108,7 +106,7 @@ main(int argc, char **argv) myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname; - while (( i = getopt( argc, argv, "cCD:d:Ef:h:IKkMnP:p:rs:U:vWw:X:Y:Z" )) != EOF ) { + while (( i = getopt( argc, argv, "cCD:d:f:h:KkMnO:P:p:rs:U:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND @@ -193,19 +191,9 @@ main(int argc, char **argv) return( EXIT_FAILURE ); } break; - case 'I': + case 'O': #ifdef HAVE_CYRUS_SASL - sasl_integrity++; - authmethod = LDAP_AUTH_SASL; -#else - fprintf( stderr, "%s was not compiled with SASL support\n", - argv[0] ); - return( EXIT_FAILURE ); -#endif - break; - case 'E': -#ifdef HAVE_CYRUS_SASL - sasl_privacy++; + sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s was not compiled with SASL support\n", @@ -383,37 +371,25 @@ main(int argc, char **argv) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - int minssf = 0, maxssf = 0; - - if ( sasl_integrity > 0 ) - maxssf = 1; - if ( sasl_integrity > 1 ) - minssf = 1; - if ( sasl_privacy > 0 ) - maxssf = 100000; /* Something big value */ - if ( sasl_privacy > 1 ) - minssf = 56; - - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, - (void *)&minssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); - } - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, - (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" - "%d\n", maxssf); - return( EXIT_FAILURE ); + ldap_set_sasl_interact_proc( ld, lutil_sasl_interact ); + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } } - rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, - sasl_authz_id, sasl_mech, - passwd.bv_len ? &passwd : NULL, - NULL, NULL ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL ); if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); return( EXIT_FAILURE ); } #else diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 5385aa1d58..dc70fcd593 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -19,6 +19,7 @@ #include +#include "lutil_ldap.h" #include "ldap_defaults.h" static int verbose = 0; @@ -41,6 +42,7 @@ usage(const char *s) " -I\t\trequest SASL integrity checking (-II to make it\n" " \tcritical)\n" " -n\t\tmake no modifications\n" +" -O secprops\tSASL security properties\n" " -p port\t\tport on LDAP server\n" " -S\t\tprompt for new password\n" " -s secret\tnew password\n" @@ -65,7 +67,7 @@ main( int argc, char *argv[] ) char *dn = NULL; char *binddn = NULL; - struct berval passwd = { 0, NULL}; + struct berval passwd = { 0, NULL }; char *newpw = NULL; char *oldpw = NULL; @@ -83,8 +85,7 @@ main( int argc, char *argv[] ) char *sasl_authc_id = NULL; char *sasl_authz_id = NULL; char *sasl_mech = NULL; - int sasl_integrity = 0; - int sasl_privacy = 0; + char *sasl_secprops = NULL; #endif int use_tls = 0; int referrals = 0; @@ -101,7 +102,7 @@ main( int argc, char *argv[] ) usage (argv[0]); while( (i = getopt( argc, argv, - "Aa:CD:d:EIh:np:Ss:U:vWw:X:Y:Z" )) != EOF ) + "Aa:CD:d:h:nO:p:Ss:U:vWw:X:Y:Z" )) != EOF ) { switch (i) { case 'A': /* prompt for oldr password */ @@ -176,23 +177,13 @@ main( int argc, char *argv[] ) passwd.bv_len = strlen( passwd.bv_val ); break; - case 'I': + case 'O': #ifdef HAVE_CYRUS_SASL - sasl_integrity++; + sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; #else - fprintf( stderr, "%s was not compiled with SASL " - "support\n", argv[0] ); - return( EXIT_FAILURE ); -#endif - break; - case 'E': -#ifdef HAVE_CYRUS_SASL - sasl_privacy++; - authmethod = LDAP_AUTH_SASL; -#else - fprintf( stderr, "%s was not compiled with SASL " - "support\n", argv[0] ); + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -342,37 +333,25 @@ main( int argc, char *argv[] ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - int minssf = 0, maxssf = 0; - - if ( sasl_integrity > 0 ) - maxssf = 1; - if ( sasl_integrity > 1 ) - minssf = 1; - if ( sasl_privacy > 0 ) - maxssf = 100000; /* Something big value */ - if ( sasl_privacy > 1 ) - minssf = 56; - - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, - (void *)&minssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); - } - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, - (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" - "%d\n", maxssf); - return( EXIT_FAILURE ); + ldap_set_sasl_interact_proc( ld, lutil_sasl_interact ); + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } } - rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, - sasl_authz_id, sasl_mech, - passwd.bv_len ? &passwd : NULL, - NULL, NULL ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL ); if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); return( EXIT_FAILURE ); } #else diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index a07370ecb6..d5e59a3f69 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -31,6 +31,7 @@ #include "ldif.h" #include "lutil.h" +#include "lutil_ldap.h" #include "ldap_defaults.h" static void @@ -64,6 +65,7 @@ usage( const char *s ) "\t\t\tand version\n" "\t-M\t\tenable Manage DSA IT control (-MM to make critical)\n" "\t-n\t\tshow what would be done but don't actually search\n" +"\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-s scope\tone of base, one, or sub (search scope)\n" @@ -143,8 +145,7 @@ static int ldapport = 0; static char *sasl_authc_id = NULL; static char *sasl_authz_id = NULL; static char *sasl_mech = NULL; -static int sasl_integrity = 0; -static int sasl_privacy = 0; +static char *sasl_secprops = NULL; #endif static int use_tls = 0; static char *sortattr = NULL; @@ -170,7 +171,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; while (( i = getopt( argc, argv, - "Aa:b:CD:d:Ef:h:IKkLl:MnP:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF ) + "Aa:b:CD:d:f:h:KkLl:MnO:P:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF ) { switch( i ) { case 'n': /* do nothing */ @@ -309,19 +310,9 @@ main( int argc, char **argv ) usage( argv[0] ); } break; - case 'I': + case 'O': #ifdef HAVE_CYRUS_SASL - sasl_integrity++; - authmethod = LDAP_AUTH_SASL; -#else - fprintf( stderr, "%s was not compiled with SASL support\n", - argv[0] ); - return( EXIT_FAILURE ); -#endif - break; - case 'E': -#ifdef HAVE_CYRUS_SASL - sasl_privacy++; + sasl_secprops = strdup( optarg ); authmethod = LDAP_AUTH_SASL; #else fprintf( stderr, "%s was not compiled with SASL support\n", @@ -531,37 +522,25 @@ main( int argc, char **argv ) if ( authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL - int minssf = 0, maxssf = 0; - - if ( sasl_integrity > 0 ) - maxssf = 1; - if ( sasl_integrity > 1 ) - minssf = 1; - if ( sasl_privacy > 0 ) - maxssf = 100000; /* Something big value */ - if ( sasl_privacy > 1 ) - minssf = 56; - - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF, - (void *)&minssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF" - "%d\n", minssf); - return( EXIT_FAILURE ); - } - if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF, - (void *)&maxssf ) != LDAP_OPT_SUCCESS ) { - fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF" - "%d\n", maxssf); - return( EXIT_FAILURE ); + ldap_set_sasl_interact_proc( ld, lutil_sasl_interact ); + + if( sasl_secprops != NULL ) { + rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, + (void *) sasl_secprops ); + + if( rc != LDAP_OPT_SUCCESS ) { + fprintf( stderr, + "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n", + sasl_secprops ); + return( EXIT_FAILURE ); + } } - rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, - sasl_authz_id, sasl_mech, - passwd.bv_len ? &passwd : NULL, - NULL, NULL ); + rc = ldap_sasl_interactive_bind_s( ld, binddn, + sasl_mech, NULL, NULL ); if( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_negotiated_sasl_bind_s" ); + ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); return( EXIT_FAILURE ); } #else diff --git a/configure b/configure index bfcffb940e..902fc01389 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # $OpenLDAP$ -# from OpenLDAP: pkg/ldap/configure.in,v 1.316 2000/06/25 19:40:13 kurt Exp +# from OpenLDAP: pkg/ldap/configure.in,v 1.317 2000/07/09 19:49:43 kurt Exp # Copyright 1998-2000 The OpenLDAP Foundation. All Rights Reserved. # @@ -27,105 +27,105 @@ ac_default_prefix=/usr/local ac_help="$ac_help --with-subdir=DIR change default subdirectory used for installs" ac_help="$ac_help - --enable-debug enable debugging (yes)" + --enable-debug enable debugging (yes)" ac_help="$ac_help - --enable-syslog enable syslog support (auto)" + --enable-syslog enable syslog support (auto)" ac_help="$ac_help - --enable-proctitle enable proctitle support (yes)" + --enable-proctitle enable proctitle support (yes)" ac_help="$ac_help - --enable-cache enable caching (yes)" + --enable-cache enable caching (yes)" ac_help="$ac_help - --enable-referrals enable V2 Referrals extension (yes)" + --enable-referrals enable V2 Referrals extension (yes)" ac_help="$ac_help - --enable-kbind enable V2 Kerberos IV bind (auto)" + --enable-kbind enable V2 Kerberos IV bind (auto)" ac_help="$ac_help - --enable-cldap enable connectionless ldap (no)" + --enable-cldap enable connectionless ldap (no)" ac_help="$ac_help - --enable-ipv6 enable IPv6 support (auto)" + --enable-ipv6 enable IPv6 support (auto)" ac_help="$ac_help - --enable-local enable AF_LOCAL socket support (auto)" + --enable-local enable AF_LOCAL (AF_UNIX) socket support (auto)" ac_help="$ac_help - --enable-x-compile enable cross compiling (no)" + --enable-x-compile enable cross compiling (no)" ac_help="$ac_help - --with-cyrus-sasl with Cyrus SASL support (auto)" + --with-cyrus-sasl with Cyrus SASL support (auto)" ac_help="$ac_help - --with-fetch with fetch URL support (auto)" + --with-fetch with fetch URL support (auto)" ac_help="$ac_help - --with-kerberos with support (auto)" + --with-kerberos with support (auto)" ac_help="$ac_help - --with-readline with readline support (auto)" + --with-readline with readline support (auto)" ac_help="$ac_help - --with-threads use threads (auto)" + --with-threads with threads (auto)" ac_help="$ac_help - --with-tls with TLS/SSL support (auto)" + --with-tls with TLS/SSL support (auto)" ac_help="$ac_help - --with-yielding-select with implicitly yielding select (auto)" + --with-yielding-select with implicitly yielding select (auto)" ac_help="$ac_help SLAPD (Standalone LDAP Daemon) Options:" ac_help="$ac_help - --enable-slapd enable building slapd (yes)" + --enable-slapd enable building slapd (yes)" ac_help="$ac_help - --enable-cleartext enable cleartext passwords (yes)" + --enable-cleartext enable cleartext passwords (yes)" ac_help="$ac_help - --enable-crypt enable crypt(3) passwords (auto)" + --enable-crypt enable crypt(3) passwords (auto)" ac_help="$ac_help - --enable-kpasswd enable kerberos password verification (no)" + --enable-kpasswd enable kerberos password verification (no)" ac_help="$ac_help - --enable-spasswd enable (Cyrus) SASL password verification (no)" + --enable-spasswd enable (Cyrus) SASL password verification (no)" ac_help="$ac_help - --enable-modules enable dynamic module support (no)" + --enable-modules enable dynamic module support (no)" ac_help="$ac_help - --enable-multimaster enable multimaster replication (no)" + --enable-multimaster enable multimaster replication (no)" ac_help="$ac_help - --enable-phonetic enable phonetic/soundex (no)" + --enable-phonetic enable phonetic/soundex (no)" ac_help="$ac_help - --enable-rlookups enable reverse lookups (auto)" + --enable-rlookups enable reverse lookups (auto)" ac_help="$ac_help - --enable-aci enable per-object ACIs (no)" + --enable-aci enable per-object ACIs (no)" ac_help="$ac_help - --enable-wrappers enable tcp wrapper support (no)" + --enable-wrappers enable tcp wrapper support (no)" ac_help="$ac_help - --enable-dynamic enable linking built binaries with dynamic libs (no)" + --enable-dynamic enable linking built binaries with dynamic libs (no)" ac_help="$ac_help - --enable-dnssrv enable dnssrv backend (no)" + --enable-dnssrv enable dnssrv backend (no)" ac_help="$ac_help - --with-dnssrv-module module type (static)" + --with-dnssrv-module module type (static)" ac_help="$ac_help - --enable-ldap enable ldap backend (no)" + --enable-ldap enable ldap backend (no)" ac_help="$ac_help - --with-ldap-module module type (static)" + --with-ldap-module module type (static)" ac_help="$ac_help - --enable-ldbm enable ldbm backend (yes)" + --enable-ldbm enable ldbm backend (yes)" ac_help="$ac_help - --with-ldbm-api use LDBM API (auto)" + --with-ldbm-api with LDBM API (auto)" ac_help="$ac_help - --with-ldbm-module module type (static)" + --with-ldbm-module module type (static)" ac_help="$ac_help - --with-ldbm-type use LDBM type (auto)" + --with-ldbm-type use LDBM type (auto)" ac_help="$ac_help - --enable-passwd enable passwd backend (no)" + --enable-passwd enable passwd backend (no)" ac_help="$ac_help - --with-passwd-module module type (static)" + --with-passwd-module module type (static)" ac_help="$ac_help - --enable-perl enable perl backend (no)" + --enable-perl enable perl backend (no)" ac_help="$ac_help - --with-perl-module module type (static)" + --with-perl-module module type (static)" ac_help="$ac_help - --enable-shell enable shell backend (no)" + --enable-shell enable shell backend (no)" ac_help="$ac_help - --with-shell-module module type (static)" + --with-shell-module module type (static)" ac_help="$ac_help - --enable-sql enable sql backend (no)" + --enable-sql enable sql backend (no)" ac_help="$ac_help - --with-sql-module module type (static)" + --with-sql-module module type (static)" ac_help="$ac_help - --enable-tcl enable tcl backend (no)" + --enable-tcl enable tcl backend (no)" ac_help="$ac_help - --with-tcl-module module type (static)" + --with-tcl-module module type (static)" ac_help="$ac_help SLURPD (Replication Daemon) Options:" ac_help="$ac_help - --enable-slurpd enable building slurpd (auto)" + --enable-slurpd enable building slurpd (auto)" ac_help="$ac_help Library Generation & Linking Options" ac_help="$ac_help diff --git a/configure.in b/configure.in index 7023dbc4a4..fed1111ce4 100644 --- a/configure.in +++ b/configure.in @@ -100,35 +100,35 @@ AC_SUBST(ldap_subdir)dnl dnl ---------------------------------------------------------------- dnl General "enable" options -OL_ARG_ENABLE(debug,[ --enable-debug enable debugging], yes)dnl -OL_ARG_ENABLE(syslog,[ --enable-syslog enable syslog support], auto)dnl -OL_ARG_ENABLE(proctitle,[ --enable-proctitle enable proctitle support], yes)dnl -OL_ARG_ENABLE(cache,[ --enable-cache enable caching], yes)dnl -OL_ARG_ENABLE(referrals,[ --enable-referrals enable V2 Referrals extension], yes)dnl -OL_ARG_ENABLE(kbind,[ --enable-kbind enable V2 Kerberos IV bind], auto)dnl -OL_ARG_ENABLE(cldap,[ --enable-cldap enable connectionless ldap], no)dnl -OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl -OL_ARG_ENABLE(local,[ --enable-local enable AF_LOCAL socket support], auto)dnl -OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling], +OL_ARG_ENABLE(debug,[ --enable-debug enable debugging], yes)dnl +OL_ARG_ENABLE(syslog,[ --enable-syslog enable syslog support], auto)dnl +OL_ARG_ENABLE(proctitle,[ --enable-proctitle enable proctitle support], yes)dnl +OL_ARG_ENABLE(cache,[ --enable-cache enable caching], yes)dnl +OL_ARG_ENABLE(referrals,[ --enable-referrals enable V2 Referrals extension], yes)dnl +OL_ARG_ENABLE(kbind,[ --enable-kbind enable V2 Kerberos IV bind], auto)dnl +OL_ARG_ENABLE(cldap,[ --enable-cldap enable connectionless ldap], no)dnl +OL_ARG_ENABLE(ipv6,[ --enable-ipv6 enable IPv6 support], auto)dnl +OL_ARG_ENABLE(local,[ --enable-local enable AF_LOCAL (AF_UNIX) socket support], auto)dnl +OL_ARG_ENABLE(x_compile,[ --enable-x-compile enable cross compiling], no, [yes no])dnl dnl ---------------------------------------------------------------- dnl General "with" options -dnl OL_ARG_ENABLE(dmalloc,[ --enable-dmalloc enable debug malloc support], no)dnl +dnl OL_ARG_ENABLE(dmalloc,[ --enable-dmalloc enable debug malloc support], no)dnl -OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support], +OL_ARG_WITH(cyrus_sasl,[ --with-cyrus-sasl with Cyrus SASL support], auto, [auto yes no] ) -OL_ARG_WITH(fetch,[ --with-fetch with fetch URL support], +OL_ARG_WITH(fetch,[ --with-fetch with fetch URL support], auto, [auto yes no] ) -OL_ARG_WITH(kerberos,[ --with-kerberos with support], +OL_ARG_WITH(kerberos,[ --with-kerberos with support], auto, [auto k5 k5only k425 kth k4 afs yes no]) -OL_ARG_WITH(readline,[ --with-readline with readline support], +OL_ARG_WITH(readline,[ --with-readline with readline support], auto, [auto yes no] ) -OL_ARG_WITH(threads,[ --with-threads use threads], +OL_ARG_WITH(threads,[ --with-threads with threads], auto, [auto nt posix mach pth lwp yes no manual] ) -OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support], +OL_ARG_WITH(tls,[ --with-tls with TLS/SSL support], auto, [auto ssleay openssl yes no] ) -OL_ARG_WITH(yielding_select,[ --with-yielding-select with implicitly yielding select], +OL_ARG_WITH(yielding_select,[ --with-yielding-select with implicitly yielding select], auto, [auto yes no manual] ) dnl ---------------------------------------------------------------- @@ -138,53 +138,53 @@ dnl ---------------------------------------------------------------- dnl ---------------------------------------------------------------- dnl SLAPD OPTIONS AC_ARG_WITH(xxslapdoptions,[SLAPD (Standalone LDAP Daemon) Options:]) -OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl -OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl -OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], auto)dnl -OL_ARG_ENABLE(kpasswd,[ --enable-kpasswd enable kerberos password verification], no)dnl -OL_ARG_ENABLE(spasswd,[ --enable-spasswd enable (Cyrus) SASL password verification], no)dnl -OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl -OL_ARG_ENABLE(multimaster,[ --enable-multimaster enable multimaster replication], no)dnl -OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl -OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl -OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs], no)dnl -OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl -OL_ARG_ENABLE(dynamic,[ --enable-dynamic enable linking built binaries with dynamic libs], no)dnl +OL_ARG_ENABLE(slapd,[ --enable-slapd enable building slapd], yes)dnl +OL_ARG_ENABLE(cleartext,[ --enable-cleartext enable cleartext passwords], yes)dnl +OL_ARG_ENABLE(crypt,[ --enable-crypt enable crypt(3) passwords], auto)dnl +OL_ARG_ENABLE(kpasswd,[ --enable-kpasswd enable kerberos password verification], no)dnl +OL_ARG_ENABLE(spasswd,[ --enable-spasswd enable (Cyrus) SASL password verification], no)dnl +OL_ARG_ENABLE(modules,[ --enable-modules enable dynamic module support], no)dnl +OL_ARG_ENABLE(multimaster,[ --enable-multimaster enable multimaster replication], no)dnl +OL_ARG_ENABLE(phonetic,[ --enable-phonetic enable phonetic/soundex], no)dnl +OL_ARG_ENABLE(rlookups,[ --enable-rlookups enable reverse lookups], auto)dnl +OL_ARG_ENABLE(aci,[ --enable-aci enable per-object ACIs], no)dnl +OL_ARG_ENABLE(wrappers,[ --enable-wrappers enable tcp wrapper support], no)dnl +OL_ARG_ENABLE(dynamic,[ --enable-dynamic enable linking built binaries with dynamic libs], no)dnl dnl SLAPD Backend options -OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend], no)dnl -OL_ARG_WITH(dnssrv_module,[ --with-dnssrv-module module type], static, +OL_ARG_ENABLE(dnssrv,[ --enable-dnssrv enable dnssrv backend], no)dnl +OL_ARG_WITH(dnssrv_module,[ --with-dnssrv-module module type], static, [static dynamic]) -OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend], no)dnl -OL_ARG_WITH(ldap_module,[ --with-ldap-module module type], static, +OL_ARG_ENABLE(ldap,[ --enable-ldap enable ldap backend], no)dnl +OL_ARG_WITH(ldap_module,[ --with-ldap-module module type], static, [static dynamic]) -OL_ARG_ENABLE(ldbm,[ --enable-ldbm enable ldbm backend], yes)dnl -OL_ARG_WITH(ldbm_api,[ --with-ldbm-api use LDBM API], auto, +OL_ARG_ENABLE(ldbm,[ --enable-ldbm enable ldbm backend], yes)dnl +OL_ARG_WITH(ldbm_api,[ --with-ldbm-api with LDBM API], auto, [auto berkeley bcompat mdbm gdbm]) -OL_ARG_WITH(ldbm_module,[ --with-ldbm-module module type], static, +OL_ARG_WITH(ldbm_module,[ --with-ldbm-module module type], static, [static dynamic]) -OL_ARG_WITH(ldbm_type,[ --with-ldbm-type use LDBM type], auto, +OL_ARG_WITH(ldbm_type,[ --with-ldbm-type use LDBM type], auto, [auto btree hash]) -OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend], no)dnl -OL_ARG_WITH(passwd_module,[ --with-passwd-module module type], static, +OL_ARG_ENABLE(passwd,[ --enable-passwd enable passwd backend], no)dnl +OL_ARG_WITH(passwd_module,[ --with-passwd-module module type], static, [static dynamic]) -OL_ARG_ENABLE(perl,[ --enable-perl enable perl backend], no)dnl -OL_ARG_WITH(perl_module,[ --with-perl-module module type], static, +OL_ARG_ENABLE(perl,[ --enable-perl enable perl backend], no)dnl +OL_ARG_WITH(perl_module,[ --with-perl-module module type], static, [static dynamic]) -OL_ARG_ENABLE(shell,[ --enable-shell enable shell backend], no)dnl -OL_ARG_WITH(shell_module,[ --with-shell-module module type], static, +OL_ARG_ENABLE(shell,[ --enable-shell enable shell backend], no)dnl +OL_ARG_WITH(shell_module,[ --with-shell-module module type], static, [static dynamic]) -OL_ARG_ENABLE(sql,[ --enable-sql enable sql backend], no)dnl -OL_ARG_WITH(sql_module,[ --with-sql-module module type], static, +OL_ARG_ENABLE(sql,[ --enable-sql enable sql backend], no)dnl +OL_ARG_WITH(sql_module,[ --with-sql-module module type], static, [static dynamic]) -OL_ARG_ENABLE(tcl,[ --enable-tcl enable tcl backend], no)dnl -OL_ARG_WITH(tcl_module,[ --with-tcl-module module type], static, +OL_ARG_ENABLE(tcl,[ --enable-tcl enable tcl backend], no)dnl +OL_ARG_WITH(tcl_module,[ --with-tcl-module module type], static, [static dynamic]) dnl ---------------------------------------------------------------- dnl SLURPD OPTIONS AC_ARG_WITH(xxslurpdoptions,[SLURPD (Replication Daemon) Options:]) -OL_ARG_ENABLE(slurpd,[ --enable-slurpd enable building slurpd], auto)dnl +OL_ARG_ENABLE(slurpd,[ --enable-slurpd enable building slurpd], auto)dnl dnl ---------------------------------------------------------------- AC_ARG_WITH(xxliboptions,[Library Generation & Linking Options]) diff --git a/doc/devel/args b/doc/devel/args index 513e2fdea0..5c2cad4945 100644 --- a/doc/devel/args +++ b/doc/devel/args @@ -1,9 +1,9 @@ Tools ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -ldapdelete CDE I K M P * U WXYZ cd f h k n p vw -ldapmodify CDEF I K M P * U WXYZabcd f h k n p r t vw -ldapmodrdn CDE I K M P * U WXYZ cd f h k n p rs vw -ldappasswd A CDE I *S U WXYZa d h s vw -ldapsearch A CDE I KLM P *STUVWXYZab*d f h kl n p stuvw z +ldapdelete CD K M OP * U WXYZ cd f h k n p vw +ldapmodify CD F K M OP * U WXYZabcd f h k n p r t vw +ldapmodrdn CD K M OP * U WXYZ cd f h k n p rs vw +ldappasswd A CD O *S U WXYZa d h s vw +ldapsearch A CD KLM OP *STUVWXYZab*d f h kl n p stuvw z Other Clients ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz fax500 f h m @@ -17,7 +17,7 @@ ud D V cd f l p s uv * reserved - GHJNOegijmoqxy + EGHIJNOegijmoqxy * General flags: -C Chase Referrals @@ -31,15 +31,13 @@ ud D V cd f l p s uv -p port -v verbose -w bind password - -W prompt for bind password * LDAPv3 Only -M ManageDSAIT -Z StartTLS - -I SASL Intergity - -E SASL Privacy (encryption) + -O SASL Security Options -U SASL Authentication Identity (username) -X SASL Authorization Identity -Y SASL Mechanism diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5 index 1e9e5266e9..0ba36c568c 100644 --- a/doc/man/man5/ldap.conf.5 +++ b/doc/man/man5/ldap.conf.5 @@ -63,6 +63,9 @@ listed of host may be provided. Used to specify the port used with connecting to LDAP servers(s). The port may be specified as a number. .TP 1i +\fBSASL_SECPROPS \fP +Used to specify Cyrus SASL security properties. +.TP 1i \fBSIZELIMIT \fP Used to specify a size limit to use when performing searches. The number should be an non-negative integer. \fISIZELIMIT\fP of zero (0) diff --git a/include/ldap.h b/include/ldap.h index 527344594a..56c817b3d7 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -131,9 +131,14 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_TRY 4 /* OpenLDAP SASL options */ -#define LDAP_OPT_X_SASL_MINSSF 0x6100 -#define LDAP_OPT_X_SASL_MAXSSF 0x6101 -#define LDAP_OPT_X_SASL_ACTSSF 0x6102 +#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 + /* on/off values */ #define LDAP_OPT_ON ((void *) 1) @@ -557,6 +562,16 @@ ldap_set_rebind_proc LDAP_P(( LDAP *ld, LDAP_REBIND_PROC *ldap_proc)); +/* 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_F( int ) +ldap_set_sasl_interact_proc LDAP_P(( + LDAP *ld, + LDAP_SASL_INTERACT_PROC *ldap_proc)); + /* * in controls.c: */ @@ -688,13 +703,10 @@ ldap_sasl_bind LDAP_P(( int *msgidp )); LDAP_F( int ) -ldap_negotiated_sasl_bind_s LDAP_P(( +ldap_sasl_interactive_bind_s LDAP_P(( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ - LDAP_CONST char *authenticationId, - LDAP_CONST char *authorizationId, /* usually NULL */ LDAP_CONST char *saslMechanism, - struct berval *passPhrase, LDAPControl **serverControls, LDAPControl **clientControls )); diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index f6eeb6f379..92e287cdfd 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -92,6 +92,10 @@ ldap_str2charray LDAP_P(( const char *str, const char *brkstr )); +LDAP_F( char * ) +ldap_charray2str LDAP_P(( + char **array, const char* sep )); + /* url.c */ LDAP_F (void) ldap_pvt_hex_unescape LDAP_P(( char *s )); LDAP_F (int) ldap_pvt_unhex( int c ); @@ -118,23 +122,23 @@ LDAP_F (int) ldap_pvt_unhex( int c ); #define LDAP_NEEDSESCAPE(c) ((c) == '\\' || (c) == '"') #ifdef HAVE_CYRUS_SASL -/* sasl.c */ -LDAP_END_DECL -#include -#include -LDAP_BEGIN_DECL - -LDAP_F (int) ldap_pvt_sasl_init LDAP_P(( void )); /* clientside init */ -LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( Sockbuf *, void * )); -LDAP_F (int) ldap_pvt_sasl_bind LDAP_P(( LDAP *, LDAP_CONST char *, - LDAP_CONST char *, LDAP_CONST sasl_callback_t *, LDAPControl **, - LDAPControl ** )); -LDAP_F (int) ldap_pvt_sasl_get_option LDAP_P(( LDAP *ld, int option, - void *arg )); -LDAP_F (int) ldap_pvt_sasl_set_option LDAP_P(( LDAP *ld, int option, - void *arg )); +/* cyrus.c */ +struct sasl_security_properties; /* avoid pulling in */ +LDAP_F (int) ldap_pvt_sasl_secprops LDAP_P(( + const char *in, + struct sasl_security_properties *secprops )); + +LDAP_F (void *) ldap_pvt_sasl_mutex_new LDAP_P((void)); +LDAP_F (int) ldap_pvt_sasl_mutex_lock LDAP_P((void *mutex)); +LDAP_F (int) ldap_pvt_sasl_mutex_unlock LDAP_P((void *mutex)); +LDAP_F (void) ldap_pvt_sasl_mutex_dispose LDAP_P((void *mutex)); + +struct sockbuf; /* avoid pulling in */ +LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * )); #endif /* HAVE_CYRUS_SASL */ +#define LDAP_PVT_SASL_LOCAL_SSF 52 /* SSF for Unix Domain Sockets */ + /* search.c */ LDAP_F( char * ) ldap_pvt_find_wildcard LDAP_P(( const char *s )); @@ -154,16 +158,16 @@ struct ldapoptions; struct ldap; LDAP_F (int) ldap_pvt_tls_init LDAP_P(( void )); -LDAP_F (int) ldap_pvt_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); LDAP_F (int) ldap_pvt_tls_connect LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg )); LDAP_F (int) ldap_pvt_tls_accept LDAP_P(( Sockbuf *sb, void *ctx_arg )); -LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); -LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); LDAP_F (void *) ldap_pvt_tls_sb_handle LDAP_P(( Sockbuf *sb )); LDAP_F (void *) ldap_pvt_tls_get_handle LDAP_P(( struct ldap *ld )); LDAP_F (int) ldap_pvt_tls_inplace LDAP_P(( Sockbuf *sb )); LDAP_F (int) ldap_pvt_tls_start LDAP_P(( struct ldap *ld, Sockbuf *sb, void *ctx_arg )); +LDAP_F (int) ldap_pvt_tls_get_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); +LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldapoptions *lo, int option, void *arg )); + /* * UTF-8 (in utf-8.c) */ diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index fc02e1d780..b89e4dee2c 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -10,7 +10,7 @@ XLIBRARY = ../libldap.a PROGRAMS = apitest ltest ttest SRCS = bind.c open.c result.c error.c compare.c search.c \ - controls.c messages.c references.c extended.c \ + controls.c messages.c references.c extended.c cyrus.c \ modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \ @@ -20,7 +20,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ charray.c tls.c dn.c os-local.c dnssrv.c \ utf-8.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ - controls.lo messages.lo references.lo extended.lo \ + controls.lo messages.lo references.lo extended.lo cyrus.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \ diff --git a/libraries/libldap/charray.c b/libraries/libldap/charray.c index 744ab07b73..82d2feeb1b 100644 --- a/libraries/libldap/charray.c +++ b/libraries/libldap/charray.c @@ -217,3 +217,48 @@ ldap_str2charray( const char *str_in, const char *brkstr ) LDAP_FREE( str ); return( res ); } + +char * ldap_charray2str( char **a, const char *sep ) +{ + char *s, **v, *p; + int len = 0; + int slen; + + if( sep == NULL ) sep = " "; + + slen = strlen( sep ); + + for ( v = a; *v != NULL; v++ ) { + len += strlen( *v ) + slen; /* for a space */ + } + + if ( len == 0 ) { + return NULL; + } + + len -= slen; + len += 1; /* EOS */ + + s = LDAP_MALLOC ( len ); + + if ( s == NULL ) { + return NULL; + } + + p = s; + for ( v = a; *v != NULL; v++ ) { + int len; + + if ( v != a ) { + strncpy( p, sep, slen ); + p += slen; + } + + len = strlen( *v ); + strncpy( p, *v, len ); + p += len; + } + + *p = '\0'; + return s; +} diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c new file mode 100644 index 0000000000..4257c6ee5f --- /dev/null +++ b/libraries/libldap/cyrus.c @@ -0,0 +1,874 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1999-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include +#include + +#include +#include +#include +#include + +#include "ldap-int.h" + +#ifdef HAVE_CYRUS_SASL +#include + +/* +* Various Cyrus SASL related stuff. +*/ + +#define SASL_MAX_BUFF_SIZE 65536 +#define SASL_MIN_BUFF_SIZE 4096 + +int ldap_int_sasl_init( void ) +{ + /* XXX not threadsafe */ + static int sasl_initialized = 0; + + static sasl_callback_t client_callbacks[] = { +#ifdef SASL_CB_GETREALM + { SASL_CB_GETREALM, NULL, NULL }, +#endif + { SASL_CB_USER, NULL, NULL }, + { SASL_CB_AUTHNAME, NULL, NULL }, + { SASL_CB_PASS, NULL, NULL }, + { SASL_CB_ECHOPROMPT, NULL, NULL }, + { SASL_CB_NOECHOPROMPT, NULL, NULL }, + { SASL_CB_LIST_END, NULL, NULL } + }; + + if ( sasl_initialized ) { + return 0; + } + +#ifndef CSRIMALLOC + sasl_set_alloc( + ber_memalloc, + ber_memcalloc, + ber_memrealloc, + ber_memfree ); +#endif /* CSRIMALLOC */ + +#ifdef LDAP_R_COMPILE + sasl_set_mutex( + ldap_pvt_sasl_mutex_new, + ldap_pvt_sasl_mutex_lock, + ldap_pvt_sasl_mutex_unlock, + ldap_pvt_sasl_mutex_dispose ); +#endif + + if ( sasl_client_init( client_callbacks ) == SASL_OK ) { + sasl_initialized = 1; + return 0; + } + + return -1; +} + +/* + * SASL encryption support for LBER Sockbufs + */ + +struct sb_sasl_data { + sasl_conn_t *sasl_context; + Sockbuf_Buf sec_buf_in; + Sockbuf_Buf buf_in; + Sockbuf_Buf buf_out; +}; + +static int +sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg ) +{ + struct sb_sasl_data *p; + + assert( sbiod != NULL ); + + p = LBER_MALLOC( sizeof( *p ) ); + if ( p == NULL ) + return -1; + p->sasl_context = (sasl_conn_t *)arg; + ber_pvt_sb_buf_init( &p->sec_buf_in ); + ber_pvt_sb_buf_init( &p->buf_in ); + ber_pvt_sb_buf_init( &p->buf_out ); + if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, SASL_MIN_BUFF_SIZE ) < 0 ) { + errno = ENOMEM; + return -1; + } + + sbiod->sbiod_pvt = p; + + return 0; +} + +static int +sb_sasl_remove( Sockbuf_IO_Desc *sbiod ) +{ + struct sb_sasl_data *p; + + assert( sbiod != NULL ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + ber_pvt_sb_buf_destroy( &p->sec_buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_in ); + ber_pvt_sb_buf_destroy( &p->buf_out ); + LBER_FREE( p ); + sbiod->sbiod_pvt = NULL; + return 0; +} + +static ber_len_t +sb_sasl_pkt_length( const char *buf, int debuglevel ) +{ + ber_len_t size; + long tmp; + + assert( buf != NULL ); + + tmp = *((long *)buf); + size = ntohl( tmp ); + + if ( size > SASL_MAX_BUFF_SIZE ) { + /* somebody is trying to mess me up. */ + ber_log_printf( LDAP_DEBUG_ANY, debuglevel, + "sb_sasl_pkt_length: received illegal packet length " + "of %lu bytes\n", (unsigned long)size ); + size = 16; /* this should lead to an error. */ +} + + return size + 4; /* include the size !!! */ +} + +/* Drop a processed packet from the input buffer */ +static void +sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel ) +{ + ber_slen_t len; + + len = sec_buf_in->buf_ptr - sec_buf_in->buf_end; + if ( len > 0 ) + memmove( sec_buf_in->buf_base, sec_buf_in->buf_base + + sec_buf_in->buf_end, len ); + + if ( len >= 4 ) { + sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base, + debuglevel); + } + else { + sec_buf_in->buf_end = 0; + } + sec_buf_in->buf_ptr = len; +} + +static ber_slen_t +sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_data *p; + ber_slen_t ret, bufptr; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + /* Are there anything left in the buffer? */ + ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); + bufptr = ret; + len -= ret; + + if ( len == 0 ) + return bufptr; + + ber_pvt_sb_buf_destroy( &p->buf_in ); + + /* Read the length of the packet */ + while ( p->sec_buf_in.buf_ptr < 4 ) { + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base, + 4 - p->sec_buf_in.buf_ptr ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* The new packet always starts at p->sec_buf_in.buf_base */ + ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base, + sbiod->sbiod_sb->sb_debug ); + + /* Grow the packet buffer if neccessary */ + if ( ( p->sec_buf_in.buf_size < ret ) && + ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) { + errno = ENOMEM; + return -1; + } + p->sec_buf_in.buf_end = ret; + + /* Did we read the whole encrypted packet? */ + while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { + /* No, we have got only a part of it */ + ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; + + ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + + p->sec_buf_in.buf_ptr, ret ); +#ifdef EINTR + if ( ( ret < 0 ) && ( errno == EINTR ) ) + continue; +#endif + if ( ret <= 0 ) + return ret; + + p->sec_buf_in.buf_ptr += ret; + } + + /* Decode the packet */ + ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base, + p->sec_buf_in.buf_end, &p->buf_in.buf_base, + (unsigned *)&p->buf_in.buf_end ); + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_read: failed to decode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + sb_sasl_drop_packet( &p->sec_buf_in, + sbiod->sbiod_sb->sb_debug ); + errno = EIO; + return -1; + } + + /* Drop the packet from the input buffer */ + sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug ); + + p->buf_in.buf_size = p->buf_in.buf_end; + + bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); + + return bufptr; +} + +static ber_slen_t +sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + struct sb_sasl_data *p; + int ret; + + assert( sbiod != NULL ); + assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + /* Are there anything left in the buffer? */ + if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + if ( ret <= 0 ) + return ret; + } + + /* now encode the next packet. */ + ber_pvt_sb_buf_destroy( &p->buf_out ); + ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base, + (unsigned *)&p->buf_out.buf_size ); + if ( ret != SASL_OK ) { + ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, + "sb_sasl_write: failed to encode packet: %s\n", + sasl_errstring( ret, NULL, NULL ) ); + return -1; + } + p->buf_out.buf_end = p->buf_out.buf_size; + + ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + if ( ret <= 0 ) + return ret; + return len; +} + +static int +sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) +{ + struct sb_sasl_data *p; + + p = (struct sb_sasl_data *)sbiod->sbiod_pvt; + + if ( opt == LBER_SB_OPT_DATA_READY ) { + if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) + return 1; + } + + return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); +} + +Sockbuf_IO ldap_pvt_sockbuf_io_sasl = { + sb_sasl_setup, /* sbi_setup */ + sb_sasl_remove, /* sbi_remove */ + sb_sasl_ctrl, /* sbi_ctrl */ + sb_sasl_read, /* sbi_read */ + sb_sasl_write, /* sbi_write */ + NULL /* sbi_close */ +}; + +int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg ) +{ + Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n", + 0, 0, 0 ); + + /* don't install the stuff unless security has been negotiated */ + + if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, + &ldap_pvt_sockbuf_io_sasl ) ) + ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl, + LBER_SBIOD_LEVEL_APPLICATION, ctx_arg ); + + return LDAP_SUCCESS; +} + +static int +sasl_err2ldap( int saslerr ) +{ + int rc; + + switch (saslerr) { + case SASL_CONTINUE: + rc = LDAP_MORE_RESULTS_TO_RETURN; + break; + case SASL_OK: + rc = LDAP_SUCCESS; + break; + case SASL_FAIL: + rc = LDAP_LOCAL_ERROR; + break; + case SASL_NOMEM: + rc = LDAP_NO_MEMORY; + break; + case SASL_NOMECH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_BADAUTH: + rc = LDAP_AUTH_UNKNOWN; + break; + case SASL_NOAUTHZ: + rc = LDAP_PARAM_ERROR; + break; + case SASL_TOOWEAK: + case SASL_ENCRYPT: + rc = LDAP_AUTH_UNKNOWN; + break; + default: + rc = LDAP_LOCAL_ERROR; + break; + } + + assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); + return rc; +} + +int +ldap_int_sasl_open( + LDAP *ld, + LDAPConn *lc, + const char * host, + ber_len_t ssf ) +{ + int rc; + sasl_conn_t *ctx; + assert( lc->lconn_sasl_ctx == NULL ); + + if ( host == NULL ) { + ld->ld_errno = LDAP_UNAVAILABLE; + return ld->ld_errno; + } + + rc = sasl_client_new( "ldap", host, + NULL, +#ifdef LDAP_SASL_SECURITY_LAYER + SASL_SECURITY_LAYER, +#else + 0, +#endif + &ctx ); + + if ( rc != SASL_OK ) { + ld->ld_errno = sasl_err2ldap( rc ); + return ld->ld_errno; + } + + Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: %s\n", + host, 0, 0 ); + + lc->lconn_sasl_ctx = ctx; + + if( ssf ) { + sasl_external_properties_t extprops; + memset(&extprops, 0L, sizeof(extprops)); + extprops.ssf = ssf; + + (void) sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); + + Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: ssf=%ld\n", + (long) ssf, 0, 0 ); + } + + return LDAP_SUCCESS; +} + +int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) +{ + sasl_conn_t *ctx = lc->lconn_sasl_ctx; + assert( ctx != NULL ); + + if( ctx ) { + sasl_dispose( &ctx ); + lc->lconn_sasl_ctx = NULL; + } + + return LDAP_SUCCESS; +} + +int +ldap_int_sasl_bind( + LDAP *ld, + const char *dn, + const char *mechs, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ + const char *mech = NULL; + const char *pmech = NULL; + int saslrc, rc; + sasl_ssf_t *ssf = NULL; + sasl_conn_t *ctx; + sasl_interact_t *prompts = NULL; + unsigned credlen; + struct berval ccred, *scred; + ber_socket_t sd; + + Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n", + mechs ? mechs : "", 0, 0 ); + + /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ + if (ld->ld_version < LDAP_VERSION3) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + + if ( sd == AC_SOCKET_INVALID ) { + /* not connected yet */ + int rc = ldap_open_defconn( ld ); + + if( rc < 0 ) return ld->ld_errno; + ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); + + if( sd == AC_SOCKET_INVALID ) { + ld->ld_errno = LDAP_UNAVAILABLE; + return ld->ld_errno; + } + } + + ctx = ld->ld_defconn->lconn_sasl_ctx; + + if( ctx == NULL ) { + ld->ld_errno = LDAP_UNAVAILABLE; + return ld->ld_errno; + } + + /* (re)set security properties */ + sasl_setprop( ctx, SASL_SEC_PROPS, + &ld->ld_options.ldo_sasl_secprops ); + + ccred.bv_val = NULL; + ccred.bv_len = 0; + + do { + saslrc = sasl_client_start( ctx, + mechs, + NULL, + &prompts, + &ccred.bv_val, + &credlen, + &mech ); + + if( pmech == NULL && mech != NULL ) { + pmech = mech; + + fprintf(stderr, + "SASL/%s authentication started\n", + pmech ); + } + + if( saslrc == SASL_INTERACT ) { + if( !ld->ld_options.ldo_sasl_interact ) break; + + rc = (ld->ld_options.ldo_sasl_interact)( ld, prompts ); + if( rc != LDAP_SUCCESS ) { + break; + } + } + } while ( saslrc == SASL_INTERACT ); + + ccred.bv_len = credlen; + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + ld->ld_errno = sasl_err2ldap( saslrc ); + return ld->ld_errno; + } + + scred = NULL; + + do { + unsigned credlen; + + rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred ); + + if ( rc == LDAP_SUCCESS ) { + break; + } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) { + if ( ccred.bv_val != NULL ) { + LDAP_FREE( ccred.bv_val ); + } + return ld->ld_errno; + } + + if ( ccred.bv_val != NULL ) { + LDAP_FREE( ccred.bv_val ); + ccred.bv_val = NULL; + } + + do { + saslrc = sasl_client_step( ctx, + (scred == NULL) ? NULL : scred->bv_val, + (scred == NULL) ? 0 : scred->bv_len, + &prompts, + &ccred.bv_val, + &credlen ); + + Debug( LDAP_DEBUG_TRACE, "sasl_client_start: %d\n", + saslrc, 0, 0 ); + + if( saslrc == SASL_INTERACT ) { + fprintf(stderr, "Interacting\n"); + if( !ld->ld_options.ldo_sasl_interact ) break; + + rc = (ld->ld_options.ldo_sasl_interact)( ld, prompts ); + if( rc != LDAP_SUCCESS ) { + break; + } + } + } while ( saslrc == SASL_INTERACT ); + + ccred.bv_len = credlen; + ber_bvfree( scred ); + + if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { + ld->ld_errno = sasl_err2ldap( saslrc ); + return ld->ld_errno; + } + } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); + + assert ( rc == LDAP_SUCCESS ); + + if ( sasl_getprop( ctx, SASL_SSF, (void **) &ssf ) + == SASL_OK && ssf && *ssf > 1 ) + { +#ifdef LDAP_SASL_SECURITY_LAYER + fprintf(stderr, "Installing Security Layer: ssf=%lu\n", + (unsigned long) *ssf ); + + ldap_pvt_sasl_install( ld->ld_sb, ctx ); +#else + fprintf(stderr, "SASL Security Factor is %lu\n", + (unsigned long) *ssf ); +#endif + } + + return rc; +} + +int ldap_pvt_sasl_secprops( + const char *in, + sasl_security_properties_t *secprops ) +{ + int i; + char **props = ldap_str2charray( in, "," ); + unsigned sflags = 0; + int got_sflags = 0; + sasl_ssf_t max_ssf; + int got_max_ssf = 0; + sasl_ssf_t min_ssf; + int got_min_ssf = 0; + unsigned maxbufsize; + int got_maxbufsize = 0; + + if( props == NULL || secprops == NULL ) { + return LDAP_PARAM_ERROR; + } + + for( i=0; props[i]; i++ ) { + if( !strcasecmp(props[i], "none") ) { + got_sflags++; + + } else if( !strcasecmp(props[i], "noplain") ) { + got_sflags++; + sflags |= SASL_SEC_NOPLAINTEXT; + + } else if( !strcasecmp(props[i], "noactive") ) { + got_sflags++; + sflags |= SASL_SEC_NOACTIVE; + + } else if( !strcasecmp(props[i], "nodict") ) { + got_sflags++; + sflags |= SASL_SEC_NODICTIONARY; + + } else if( !strcasecmp(props[i], "forwardsec") ) { + got_sflags++; + sflags |= SASL_SEC_FORWARD_SECRECY; + + } else if( !strcasecmp(props[i], "noanonymous")) { + got_sflags++; + sflags |= SASL_SEC_NOANONYMOUS; + + } else if( !strcasecmp(props[i], "passcred") ) { + got_sflags++; + sflags |= SASL_SEC_PASS_CREDENTIALS; + + } else if( !strncasecmp(props[i], + "minssf=", sizeof("minssf")) ) + { + if( isdigit( props[i][sizeof("minssf")] ) ) { + got_max_ssf++; + min_ssf = atoi( &props[i][sizeof("minssf")] ); + } else { + return LDAP_NOT_SUPPORTED; + } + + } else if( !strncasecmp(props[i], + "maxssf=", sizeof("maxssf")) ) + { + if( isdigit( props[i][sizeof("maxssf")] ) ) { + got_max_ssf++; + max_ssf = atoi( &props[i][sizeof("maxssf")] ); + } else { + return LDAP_NOT_SUPPORTED; + } + + } else if( !strncasecmp(props[i], + "maxbufsize=", sizeof("maxbufsize")) ) + { + if( isdigit( props[i][sizeof("maxbufsize")] ) ) { + got_maxbufsize++; + maxbufsize = atoi( &props[i][sizeof("maxbufsize")] ); + } else { + return LDAP_NOT_SUPPORTED; + } + + } else { + return LDAP_NOT_SUPPORTED; + } + } + + if(got_sflags) { + secprops->security_flags = sflags; + } + if(got_min_ssf) { + secprops->min_ssf = min_ssf; + } + if(got_max_ssf) { + secprops->max_ssf = max_ssf; + } + if(got_maxbufsize) { + secprops->maxbufsize = maxbufsize; + } + + ldap_charray_free( props ); + return LDAP_SUCCESS; +} + +int +ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg ) +{ + int rc; + + switch( option ) { + case LDAP_OPT_X_SASL_SECPROPS: + rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops ); + if( rc == LDAP_SUCCESS ) return 0; + } + + return -1; +} + +int +ldap_int_sasl_get_option( LDAP *ld, int option, void *arg ) +{ + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_SSF: { + int sc; + sasl_ssf_t *ssf; + sasl_conn_t *ctx; + + if( ld->ld_defconn == NULL ) { + return -1; + } + + ctx = ld->ld_defconn->lconn_sasl_ctx; + + if ( ctx == NULL ) { + return -1; + } + + sc = sasl_getprop( ctx, SASL_SSF, + (void **) &ssf ); + + if ( sc != SASL_OK ) { + return -1; + } + + *(ber_len_t *)arg = *ssf; + } break; + + case LDAP_OPT_X_SASL_SSF_EXTERNAL: + /* this option is write only */ + return -1; + + case LDAP_OPT_X_SASL_SSF_MIN: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.min_ssf; + break; + case LDAP_OPT_X_SASL_SSF_MAX: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.max_ssf; + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.maxbufsize; + break; + + case LDAP_OPT_X_SASL_SECPROPS: + /* this option is write only */ + return -1; + + default: + return -1; + } + return 0; +} + +int +ldap_int_sasl_set_option( LDAP *ld, int option, void *arg ) +{ + if ( ld == NULL ) + return -1; + + switch ( option ) { + case LDAP_OPT_X_SASL_SSF: + /* This option is read-only */ + return -1; + + case LDAP_OPT_X_SASL_SSF_EXTERNAL: { + int sc; + sasl_external_properties_t extprops; + sasl_conn_t *ctx; + + if( ld->ld_defconn == NULL ) { + return -1; + } + + ctx = ld->ld_defconn->lconn_sasl_ctx; + + if ( ctx == NULL ) { + return -1; + } + + memset(&extprops, 0L, sizeof(extprops)); + + extprops.ssf = * (ber_len_t *) arg; + + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); + + if ( sc != SASL_OK ) { + return -1; + } + } break; + + case LDAP_OPT_X_SASL_SSF_MIN: + ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg; + break; + case LDAP_OPT_X_SASL_SSF_MAX: + ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg; + break; + case LDAP_OPT_X_SASL_MAXBUFSIZE: + ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg; + break; + + case LDAP_OPT_X_SASL_SECPROPS: { + int sc; + sc = ldap_pvt_sasl_secprops( (char *) arg, + &ld->ld_options.ldo_sasl_secprops ); + + return sc == LDAP_SUCCESS ? 0 : -1; + } + + default: + return -1; + } + return 0; +} + +#ifdef LDAP_R_COMPILE +void *ldap_pvt_sasl_mutex_new(void) +{ + ldap_pvt_thread_mutex_t *mutex; + + mutex = (ldap_pvt_thread_mutex_t *) LDAP_MALLOC( + sizeof(ldap_pvt_thread_mutex_t) ); + + if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) { + return mutex; + } + return NULL; +} + +int ldap_pvt_sasl_mutex_lock(void *mutex) +{ + return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex ) + ? SASL_FAIL : SASL_OK; +} + +int ldap_pvt_sasl_mutex_unlock(void *mutex) +{ + return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex ) + ? SASL_FAIL : SASL_OK; +} + +void ldap_pvt_sasl_mutex_dispose(void *mutex) +{ + (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex ); + LDAP_FREE( mutex ); +} +#endif + +#else +int ldap_int_sasl_init( void ) +{ return LDAP_SUCCESS; } + +int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc ) +{ return LDAP_SUCCESS; } + +int +ldap_int_sasl_bind( + LDAP *ld, + const char *dn, + const char *mechs, + LDAPControl **sctrls, + LDAPControl **cctrls ) +{ return LDAP_NOT_SUPPORTED; } +#endif /* HAVE_CYRUS_SASL */ diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index d507e8cb4d..b7558f75ec 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -26,8 +26,10 @@ struct ldapoptions ldap_int_global_options = #define ATTR_INT 2 #define ATTR_KV 3 #define ATTR_STRING 4 -#define ATTR_TLS 5 -#define ATTR_URIS 6 +#define ATTR_URIS 5 + +#define ATTR_SASL 6 +#define ATTR_TLS 7 struct ol_keyvalue { const char * key; @@ -66,6 +68,10 @@ static const struct ol_attribute { {0, ATTR_BOOL, "REFERRALS", NULL, LDAP_BOOL_REFERRALS}, {0, ATTR_BOOL, "RESTART", NULL, LDAP_BOOL_RESTART}, +#ifdef HAVE_CYRUS_SASL + {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}, @@ -76,13 +82,6 @@ static const struct ol_attribute { {0, ATTR_TLS, "TLS_RANDFILE", NULL, LDAP_OPT_X_TLS_RANDOM_FILE}, #endif -#ifdef HAVE_CYRUS_SASL - {0, ATTR_INT, "SASL_MINSSF", NULL, - offsetof(struct ldapoptions, ldo_sasl_minssf)}, - {0, ATTR_INT, "SASL_MAXSSF", NULL, - offsetof(struct ldapoptions, ldo_sasl_maxssf)}, -#endif - {0, ATTR_NONE, NULL, NULL, 0} }; @@ -204,11 +203,6 @@ static void openldap_ldap_init_w_conf( if (* (char**) p != NULL) LDAP_FREE(* (char**) p); * (char**) p = LDAP_STRDUP(opt); break; - case ATTR_TLS: -#ifdef HAVE_TLS - ldap_pvt_tls_config( gopts, attrs[i].offset, opt ); -#endif - break; case ATTR_URIS: if (attrs[i].offset == 0) { ldap_set_option( NULL, LDAP_OPT_URI, opt ); @@ -216,7 +210,18 @@ static void openldap_ldap_init_w_conf( ldap_set_option( NULL, LDAP_OPT_HOST_NAME, opt ); } break; + case ATTR_SASL: +#ifdef HAVE_CYRUS_SASL + ldap_int_sasl_config( gopts, attrs[i].offset, opt ); +#endif + break; + case ATTR_TLS: +#ifdef HAVE_TLS + ldap_int_tls_config( gopts, attrs[i].offset, opt ); +#endif + break; } + break; } } @@ -338,11 +343,6 @@ static void openldap_ldap_init_w_env( * (char**) p = LDAP_STRDUP(value); } break; - case ATTR_TLS: -#ifdef HAVE_TLS - ldap_pvt_tls_config( gopts, attrs[i].offset, value ); -#endif - break; case ATTR_URIS: if (attrs[i].offset == 0) { ldap_set_option( NULL, LDAP_OPT_URI, value ); @@ -350,6 +350,16 @@ static void openldap_ldap_init_w_env( ldap_set_option( NULL, LDAP_OPT_HOST_NAME, value ); } break; + case ATTR_SASL: +#ifdef HAVE_CYRUS_SASL + ldap_int_sasl_config( gopts, attrs[i].offset, value ); +#endif + break; + case ATTR_TLS: +#ifdef HAVE_TLS + ldap_int_tls_config( gopts, attrs[i].offset, value ); +#endif + break; } } } @@ -389,8 +399,11 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl gopts->ldo_tls_ctx = NULL; #endif #ifdef HAVE_CYRUS_SASL - gopts->ldo_sasl_minssf = 0; - gopts->ldo_sasl_maxssf = INT_MAX; + memset( &gopts->ldo_sasl_secprops, '\0', sizeof(gopts->ldo_sasl_secprops) ); + + gopts->ldo_sasl_secprops.max_ssf = INT_MAX; + gopts->ldo_sasl_secprops.maxbufsize = 65536; + gopts->ldo_sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT|SASL_SEC_NOANONYMOUS; #endif gopts->ldo_valid = LDAP_INITIALIZED; @@ -398,21 +411,35 @@ void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl return; } +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) \ + || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) +char * ldap_int_hostname = "localhost"; +#endif + void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl ) { if ( gopts->ldo_valid == LDAP_INITIALIZED ) { return; } +#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) \ + || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) + { + char hostbuf[MAXHOSTNAMELEN+1]; + if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { + hostbuf[MAXHOSTNAMELEN] = '\0'; + ldap_int_hostname = hostbuf; + } + } +#endif + ldap_int_utils_init(); #ifdef HAVE_TLS ldap_pvt_tls_init(); #endif -#ifdef HAVE_CYRUS_SASL - ldap_pvt_sasl_init(); -#endif + ldap_int_sasl_init(); if ( ldap_int_tblsize == 0 ) ldap_int_ip_init(); diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index fd6352d93a..004d68468b 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -18,6 +18,11 @@ #include "../liblber/lber-int.h" +#ifdef HAVE_CYRUS_SASL + /* the need for this should be removed */ +#include +#endif + /* * Support needed if the library is running in the kernel */ @@ -142,8 +147,8 @@ struct ldapoptions { int ldo_tls_mode; #endif #ifdef HAVE_CYRUS_SASL - sasl_ssf_t ldo_sasl_minssf; - sasl_ssf_t ldo_sasl_maxssf; + struct sasl_security_properties ldo_sasl_secprops; + LDAP_SASL_INTERACT_PROC *ldo_sasl_interact; #endif LDAP_BOOLEANS ldo_booleans; /* boolean options */ }; @@ -164,7 +169,8 @@ typedef struct ldap_server { * structure for representing an LDAP server connection */ typedef struct ldap_conn { - Sockbuf *lconn_sb; + Sockbuf *lconn_sb; + void *lconn_sasl_ctx; int lconn_refcnt; time_t lconn_lastused; /* time */ int lconn_rebind_inprogress; /* set if rebind in progress */ @@ -266,7 +272,8 @@ struct ldap { #define ld_cctrls ld_options.ldo_cctrls #define ld_rebindproc ld_options.ldo_rebindproc -#define ld_version ld_options.ldo_version +#define ld_version ld_options.ldo_version + char *ld_host; int ld_port; @@ -298,22 +305,20 @@ struct ldap { LDAPConn *ld_defconn; /* default connection */ LDAPConn *ld_conns; /* list of server connections */ void *ld_selectinfo; /* platform specifics for select */ -#ifdef HAVE_CYRUS_SASL - sasl_conn_t *ld_sasl_context; -#endif /* HAVE_CYRUS_SASL */ }; #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) #if defined(HAVE_RES_QUERY) && defined(LDAP_R_COMPILE) #include -extern ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; +LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex; #endif /* HAVE_RES_QUERY && LDAP_R_COMPILE */ /* * in init.c */ -LDAP_F ( struct ldapoptions ) ldap_int_global_options; +LDAP_V ( struct ldapoptions ) ldap_int_global_options; + LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *)); LDAP_F ( void ) ldap_int_initialize_global_options LDAP_P(( struct ldapoptions *, int *)); @@ -400,16 +405,20 @@ LDAP_F (char *) ldap_get_kerberosv4_credentials LDAP_P(( * in open.c */ LDAP_F (int) ldap_open_defconn( LDAP *ld ); -LDAP_F (int) open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srvlist, char **krbinstancep, int async ); +LDAP_F (int) ldap_int_open_connection( LDAP *ld, + LDAPConn *conn, LDAPURLDesc *srvlist, int async ); /* * in os-ip.c */ LDAP_F (int) ldap_int_tblsize; LDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm ); -LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, unsigned long address, int port, int async ); +LDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, + int proto, const char *host, unsigned long address, int port, + int async ); #if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL) +LDAP_V (char *) ldap_int_hostname; LDAP_F (char *) ldap_host_connected_to( Sockbuf *sb ); #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ @@ -427,7 +436,8 @@ LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); * in os-local.c */ #ifdef LDAP_PF_UNIX -LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, const char *path, int async ); +LDAP_F (int) ldap_connect_to_path( LDAP *ld, Sockbuf *sb, int proto, + const char *path, int async ); #endif /* LDAP_PF_UNIX */ /* @@ -518,6 +528,31 @@ LDAP_F (char *) ldap_url_list2urls LDAP_P(( LDAP_F (void) ldap_free_urllist LDAP_P(( LDAPURLDesc *ludlist )); +/* + * in cyrus.c + */ +LDAP_F (int) ldap_int_sasl_init LDAP_P(( void )); + +LDAP_F (int) ldap_int_sasl_open LDAP_P(( + LDAP *ld, LDAPConn *conn, + const char* host, ber_len_t ssf )); +LDAP_F (int) ldap_int_sasl_close LDAP_P(( LDAP *ld, LDAPConn *conn )); + +LDAP_F (int) ldap_int_sasl_get_option LDAP_P(( LDAP *ld, + int option, void *arg )); +LDAP_F (int) ldap_int_sasl_set_option LDAP_P(( LDAP *ld, + int option, void *arg )); +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 ** )); + +/* + * in tls.c + */ +LDAP_F (int) ldap_int_tls_config LDAP_P(( struct ldapoptions *lo, int option, const char *arg )); LDAP_END_DECL diff --git a/libraries/libldap/ldap.conf b/libraries/libldap/ldap.conf index 32fd51d2ed..03d508c94f 100644 --- a/libraries/libldap/ldap.conf +++ b/libraries/libldap/ldap.conf @@ -7,9 +7,6 @@ # This file should be world readable. #BASE dc=OpenLDAP, dc=Org -#HOST ldap.openldap.org -#PORT 389 - #URI ldap://ldap.openldap.org ldap://ldap-master.openldap.org:666 #SIZELIMIT 12 diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index 2c9fafb669..1e34a73cfe 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -26,14 +26,15 @@ int ldap_open_defconn( LDAP *ld ) { - if (( ld->ld_defconn = ldap_new_connection( ld, ld->ld_options.ldo_defludp, 1,1,NULL )) == NULL ) - { + ld->ld_defconn = ldap_new_connection( ld, + ld->ld_options.ldo_defludp, 1, 1, NULL ); + + if( ld->ld_defconn == NULL ) { ld->ld_errno = LDAP_SERVER_DOWN; return -1; } ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ - return 0; } @@ -91,7 +92,7 @@ ldap_create( LDAP **ldp ) ldap_int_initialize(gopts, NULL); } - Debug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 ); #ifdef HAVE_WINSOCK2 { WORD wVersionRequested; @@ -179,7 +180,7 @@ ldap_create( LDAP **ldp ) * * Example: * LDAP *ld; - * ld = ldap_open( host, port ); + * ld = ldap_init( host, port ); */ LDAP * ldap_init( LDAP_CONST char *defhost, int defport ) @@ -250,8 +251,9 @@ ldap_start_tls_s ( LDAP *ld, if (ldap_pvt_tls_inplace(lc->lconn_sb) != 0) return LDAP_OPERATIONS_ERROR; + /* XXYYZ: this initiates operaton only on default connection! */ rc = ldap_extended_operation_s(ld, LDAP_EXOP_START_TLS, - NULL, serverctrls, clientctrls, &rspoid, &rspdata); + NULL, serverctrls, clientctrls, &rspoid, &rspdata); if (rc != LDAP_SUCCESS) return rc; @@ -270,14 +272,21 @@ ldap_start_tls_s ( LDAP *ld, } int -open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, - char **krbinstancep, int async ) +ldap_int_open_connection( + LDAP *ld, + LDAPConn *conn, + LDAPURLDesc *srv, + int async ) { int rc = -1; +#ifdef HAVE_CYRUS_SASL + char *sasl_host = NULL; + int sasl_ssf = 0; +#endif int port; long addr; - Debug( LDAP_DEBUG_TRACE, "open_ldap_connection\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n", 0, 0, 0 ); port = srv->lud_port; if (port == 0) @@ -290,30 +299,36 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, switch ( ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) { case LDAP_PROTO_TCP: - rc = ldap_connect_to_host( ld, sb, srv->lud_host, - addr, port, async ); - if ( rc == -1 ) - return rc; - ber_sockbuf_add_io( sb, &ber_sockbuf_io_tcp, + rc = ldap_connect_to_host( ld, conn->lconn_sb, 0, + srv->lud_host, addr, port, async ); + if ( rc == -1 ) return rc; + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); + +#ifdef HAVE_CYRUS_SASL + sasl_host = ldap_host_connected_to( conn->lconn_sb ); +#endif break; case LDAP_PROTO_UDP: - rc = ldap_connect_to_host( ld, sb, srv->lud_host, - addr, port, async ); - if ( rc == -1 ) - return rc; - ber_sockbuf_add_io( sb, &ber_sockbuf_io_udp, + rc = ldap_connect_to_host( ld, conn->lconn_sb, 1, + srv->lud_host, addr, port, async ); + if ( rc == -1 ) return rc; + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp, LBER_SBIOD_LEVEL_PROVIDER, NULL ); break; case LDAP_PROTO_IPC: #ifdef LDAP_PF_LOCAL /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */ - rc = ldap_connect_to_path( ld, sb, + rc = ldap_connect_to_path( ld, conn->lconn_sb, 0, srv->lud_host, async ); - if ( rc == -1 ) - return rc; - ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, + if ( rc == -1 ) return rc; + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER, NULL ); + +#ifdef HAVE_CYRUS_SASL + sasl_host = ldap_host_connected_to( conn->lconn_sb ); + sasl_ssf = LDAP_PVT_SASL_LOCAL_SSF; +#endif break; #endif /* LDAP_PF_LOCAL */ default: @@ -321,31 +336,41 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, break; } - ber_sockbuf_add_io( sb, &ber_sockbuf_io_readahead, +#ifdef HAVE_CYRUS_SASL + if( sasl_host != NULL ) { + ldap_int_sasl_open( ld, conn, sasl_host, sasl_ssf ); + } +#endif + + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead, LBER_SBIOD_LEVEL_PROVIDER, NULL ); #ifdef LDAP_DEBUG - ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, INT_MAX, NULL ); + ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug, + INT_MAX, NULL ); #endif #ifdef HAVE_TLS if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD || strcmp( srv->lud_scheme, "ldaps" ) == 0 ) { - rc = ldap_pvt_tls_start( ld, sb, ld->ld_options.ldo_tls_ctx ); + rc = ldap_pvt_tls_start( ld, conn->lconn_sb, + ld->ld_options.ldo_tls_ctx ); if (rc != LDAP_SUCCESS) return rc; } #endif - if ( krbinstancep != NULL ) { + if ( conn->lconn_krbinstance != NULL ) { #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char *c; - if (( *krbinstancep = ldap_host_connected_to( sb )) != NULL && - ( c = strchr( *krbinstancep, '.' )) != NULL ) { + conn->lconn_krbinstance = ldap_host_connected_to( conn->sb ); + + if( conn->lconn_krbinstance != NULL && + ( c = strchr( conn->lconn_krbinstance, '.' )) != NULL ) { *c = '\0'; } #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ - *krbinstancep = NULL; + conn->lconn_krbinstance = NULL; #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */ } diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index a45cccecf7..91a10ed54f 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -285,7 +285,7 @@ ldap_get_option( return LDAP_OPT_SUCCESS; #endif #ifdef HAVE_CYRUS_SASL - if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 ) + if ( ldap_int_sasl_get_option(ld, option, outvalue ) == 0 ) return LDAP_OPT_SUCCESS; #endif /* bad param */ @@ -582,7 +582,7 @@ ldap_set_option( return LDAP_OPT_SUCCESS; #endif #ifdef HAVE_CYRUS_SASL - if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 ) + if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) return LDAP_OPT_SUCCESS; #endif /* bad param */ @@ -596,3 +596,14 @@ ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc) { return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc)); } + +int +ldap_set_sasl_interact_proc( LDAP *ld, LDAP_SASL_INTERACT_PROC *proc) +{ +#ifdef HAVE_CYRUS_SASL + ld->ld_options.ldo_sasl_interact = proc; + return LDAP_OPT_SUCCESS; +#else + return LDAP_OPT_ERROR; +#endif +} diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 7ffc16bd8c..805e0223f5 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -95,9 +95,9 @@ ldap_pvt_ndelay_off(LDAP *ld, int fd) } static ber_socket_t -ldap_pvt_socket(LDAP *ld, int family) +ldap_int_socket(LDAP *ld, int family, int type ) { - ber_socket_t s = socket(family, SOCK_STREAM, 0); + ber_socket_t s = socket(family, type, 0); osip_debug(ld, "ldap_new_socket: %d\n",s,0,0); return ( s ); } @@ -110,22 +110,23 @@ ldap_pvt_close_socket(LDAP *ld, int s) } static int -ldap_pvt_prepare_socket(LDAP *ld, int fd) +ldap_int_prepare_socket(LDAP *ld, int s, int proto ) { - osip_debug(ld, "ldap_prepare_socket: %d\n",fd,0,0); + osip_debug(ld, "ldap_prepare_socket: %d\n", s,0,0); #ifdef TCP_NODELAY -{ - int dummy = 1; - if ( setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, - (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) - { - osip_debug(ld, "ldap_prepare_socket: " - "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", - fd, 0, 0); + if( proto = LDAP_PROTO_TCP ) { + int dummy = 1; + if ( setsockopt( s, IPPROTO_TCP, TCP_NODELAY, + (char*) &dummy, sizeof(dummy) ) == AC_SOCKET_ERROR ) + { + osip_debug(ld, "ldap_prepare_socket: " + "setsockopt(%d, TCP_NODELAY) failed (ignored).\n", + s, 0, 0); + } } -} #endif + return 0; } @@ -183,7 +184,9 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s) #undef TRACE static int -ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr *sin, socklen_t addrlen, int async) +ldap_pvt_connect(LDAP *ld, ber_socket_t s, + struct sockaddr *sin, socklen_t addrlen, + int async) { struct timeval tv, *opt_tv=NULL; fd_set wfds, *z=NULL; @@ -275,8 +278,10 @@ ldap_pvt_inet_aton( const char *host, struct in_addr *in) int -ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, - unsigned long address, int port, int async) +ldap_connect_to_host(LDAP *ld, Sockbuf *sb, + int proto, + const char *host, + unsigned long address, int port, int async) { struct sockaddr_in sin; struct in_addr in; @@ -290,12 +295,13 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, if (host != NULL) { #ifdef HAVE_GETADDRINFO - char serv[7]; + char serv[7]; struct addrinfo hints, *res, *sai; memset( &hints, '\0', sizeof(hints) ); hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + hints.ai_socktype = proto == LDAP_PROTO_UDP + ? SOCK_DGRAM : SOCK_STREAM; snprintf(serv, sizeof serv, "%d", ntohs(port)); if ( getaddrinfo(host, serv, &hints, &res) ) { @@ -305,11 +311,18 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, sai = res; rc = -1; do { - s = ldap_pvt_socket( ld, sai->ai_family ); + /* we assume AF_x and PF_x are equal for all x */ + s = ldap_int_socket( ld, sai->ai_family, + proto == LDAP_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM ); if ( s == -1 ) { continue; } + if ( ldap_int_prepare_socket(ld, s, proto ) == -1 ) { + ldap_pvt_close_socket(ld, s); + break; + } + switch (sai->ai_family) { #ifdef LDAP_PF_INET6 case AF_INET6: { @@ -330,6 +343,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, addr, serv, 0); } break; } + rc = ldap_pvt_connect(ld, s, sai->ai_addr, sai->ai_addrlen, async); if ( (rc == 0) || (rc == -2) ) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s ); @@ -363,15 +377,15 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, rc = s = -1; for ( i = 0; !use_hp || (hp->h_addr_list[i] != 0); ++i, rc = -1 ) { - s = ldap_pvt_socket( ld, AF_INET ); + s = ldap_int_socket( ld, PF_INET, + proto == LDAP_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM ); if ( s == -1 ) { /* use_hp ? continue : break; */ break; } - if ( ldap_pvt_prepare_socket(ld, s) == -1 ) { + if ( ldap_int_prepare_socket( ld, s, proto ) == -1 ) { ldap_pvt_close_socket(ld, s); - /* use_hp ? continue : break; */ break; } @@ -385,7 +399,9 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, osip_debug(ld, "ldap_connect_to_host: Trying %s:%d\n", inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),0); - rc = ldap_pvt_connect(ld, s, (struct sockaddr *)&sin, sizeof(struct sockaddr_in), async); + rc = ldap_pvt_connect(ld, s, + (struct sockaddr *)&sin, sizeof(struct sockaddr_in), + async); if ( (rc == 0) || (rc == -2) ) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s ); @@ -401,27 +417,28 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host, return rc; } -#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL ) +#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) \ + || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL ) char * ldap_host_connected_to( Sockbuf *sb ) { - struct hostent *hp; - socklen_t len; - struct sockaddr sa; - char *addr; + struct hostent *hp; + socklen_t len; + struct sockaddr sa; + char *addr; + char *host; /* buffers for gethostbyaddr_r */ - struct hostent he_buf; - int local_h_errno; + struct hostent he_buf; + int local_h_errno; char *ha_buf=NULL; - ber_socket_t sd; -#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x); - + ber_socket_t sd; + (void)memset( (char *)&sa, '\0', sizeof( struct sockaddr )); len = sizeof( sa ); ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); - if ( getpeername( sd, (struct sockaddr *)&sa, &len ) == -1 ) { + if ( getpeername( sd, &sa, &len ) == -1 ) { return( NULL ); } @@ -432,6 +449,10 @@ ldap_host_connected_to( Sockbuf *sb ) */ switch (sa.sa_family) { +#ifdef LDAP_PF_LOCAL + case AF_LOCAL: + return LDAP_STRDUP( ldap_int_hostname ); +#endif #ifdef LDAP_PF_INET6 case AF_INET6: addr = (char *) &((struct sockaddr_in6 *)&sa)->sin6_addr; @@ -441,25 +462,37 @@ ldap_host_connected_to( Sockbuf *sb ) case AF_INET: addr = (char *) &((struct sockaddr_in *)&sa)->sin_addr; len = sizeof( struct in_addr ); + + { + struct sockaddr_in localhost; + localhost.sin_addr.s_addr = htonl( INADDR_ANY ); + + if( memcmp ( &localhost.sin_addr, + &((struct sockaddr_in *)&sa)->sin_addr, + sizeof(localhost.sin_addr) ) == 0 ) + { + return LDAP_STRDUP( ldap_int_hostname ); + } + } break; + default: return( NULL ); break; } + + host = NULL; if ((ldap_pvt_gethostbyaddr_a( addr, len, sa.sa_family, &he_buf, &ha_buf, - &hp,&local_h_errno ) ==0 ) && (hp != NULL) ) + &hp,&local_h_errno ) == 0 ) && + (hp != NULL) && ( hp->h_name != NULL ) ) { - if ( hp->h_name != NULL ) { - char *host = LDAP_STRDUP( hp->h_name ); - DO_RETURN( host ); - } + host = LDAP_STRDUP( hp->h_name ); } - DO_RETURN( NULL ); + LDAP_FREE( ha_buf ); + return host; } -#undef DO_RETURN - #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND || HAVE_TLS */ diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index 8c348a1552..7ca2c675c9 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -256,9 +256,7 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb, if ( connect ) { for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) { - if ( open_ldap_connection( ld, lc->lconn_sb, - srv, &lc->lconn_krbinstance, 0 ) != -1 ) - { + if ( ldap_int_open_connection( ld, lc, srv, 0 ) != -1 ) { break; } } @@ -396,6 +394,8 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) ber_free( lc->lconn_ber, 1 ); } + ldap_int_sasl_close( ld, lc ); + prevlc = NULL; for ( tmplc = ld->ld_conns; tmplc != NULL; tmplc = tmplc->lconn_next ) { diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index a7dab4373a..3168692582 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -27,6 +27,7 @@ #include "portable.h" +#include #include #include @@ -345,367 +346,6 @@ ldap_parse_sasl_bind_result( return( ld->ld_errno ); } -#ifdef HAVE_CYRUS_SASL -/* -* Various Cyrus SASL related stuff. -*/ - -#define MAX_BUFF_SIZE 65536 -#define MIN_BUFF_SIZE 4096 - -static char * -array2str( char **a ) -{ - char *s, **v, *p; - int len = 0; - - for ( v = a; *v != NULL; v++ ) { - len += strlen( *v ) + 1; /* for a space */ - } - - if ( len == 0 ) { - return NULL; - } - - s = LDAP_MALLOC ( len ); /* last space holds \0 */ - - if ( s == NULL ) { - return NULL; - } - - p = s; - for ( v = a; *v != NULL; v++ ) { - int len; - - if ( v != a ) { - strncpy( p, " ", 1 ); - ++p; - } - len = strlen( *v ); - strncpy( p, *v, len ); - p += len; - } - - *p = '\0'; - - return s; -} - -int ldap_pvt_sasl_init( void ) -{ - /* XXX not threadsafe */ - static int sasl_initialized = 0; - - if ( sasl_initialized ) { - return 0; - } -#ifndef CSRIMALLOC - sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree ); -#endif /* CSRIMALLOC */ - - if ( sasl_client_init( NULL ) == SASL_OK ) { - sasl_initialized = 1; - return 0; - } - - return -1; -} - -/* - * SASL encryption support for LBER Sockbufs - */ - -struct sb_sasl_data { - sasl_conn_t *sasl_context; - Sockbuf_Buf sec_buf_in; - Sockbuf_Buf buf_in; - Sockbuf_Buf buf_out; -}; - -static int -sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg ) -{ - struct sb_sasl_data *p; - - assert( sbiod != NULL ); - - p = LBER_MALLOC( sizeof( *p ) ); - if ( p == NULL ) - return -1; - p->sasl_context = (sasl_conn_t *)arg; - ber_pvt_sb_buf_init( &p->sec_buf_in ); - ber_pvt_sb_buf_init( &p->buf_in ); - ber_pvt_sb_buf_init( &p->buf_out ); - if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, MIN_BUFF_SIZE ) < 0 ) { - errno = ENOMEM; - return -1; - } - - sbiod->sbiod_pvt = p; - - return 0; -} - -static int -sb_sasl_remove( Sockbuf_IO_Desc *sbiod ) -{ - struct sb_sasl_data *p; - - assert( sbiod != NULL ); - - p = (struct sb_sasl_data *)sbiod->sbiod_pvt; - ber_pvt_sb_buf_destroy( &p->sec_buf_in ); - ber_pvt_sb_buf_destroy( &p->buf_in ); - ber_pvt_sb_buf_destroy( &p->buf_out ); - LBER_FREE( p ); - sbiod->sbiod_pvt = NULL; - return 0; -} - -static ber_len_t -sb_sasl_pkt_length( const char *buf, int debuglevel ) -{ - ber_len_t size; - long tmp; - - assert( buf != NULL ); - - tmp = *((long *)buf); - size = ntohl( tmp ); - - if ( size > MAX_BUFF_SIZE ) { - /* somebody is trying to mess me up. */ - ber_log_printf( LDAP_DEBUG_ANY, debuglevel, - "sb_sasl_pkt_length: received illegal packet length " - "of %lu bytes\n", (unsigned long)size ); - size = 16; /* this should lead to an error. */ -} - - return size + 4; /* include the size !!! */ -} - -/* Drop a processed packet from the input buffer */ -static void -sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel ) -{ - ber_slen_t len; - - len = sec_buf_in->buf_ptr - sec_buf_in->buf_end; - if ( len > 0 ) - memmove( sec_buf_in->buf_base, sec_buf_in->buf_base + - sec_buf_in->buf_end, len ); - - if ( len >= 4 ) { - sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base, - debuglevel); - } - else { - sec_buf_in->buf_end = 0; - } - sec_buf_in->buf_ptr = len; -} - -static ber_slen_t -sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) -{ - struct sb_sasl_data *p; - ber_slen_t ret, bufptr; - - assert( sbiod != NULL ); - assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - - p = (struct sb_sasl_data *)sbiod->sbiod_pvt; - - /* Are there anything left in the buffer? */ - ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); - bufptr = ret; - len -= ret; - - if ( len == 0 ) - return bufptr; - - ber_pvt_sb_buf_destroy( &p->buf_in ); - - /* Read the length of the packet */ - while ( p->sec_buf_in.buf_ptr < 4 ) { - ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base, - 4 - p->sec_buf_in.buf_ptr ); -#ifdef EINTR - if ( ( ret < 0 ) && ( errno == EINTR ) ) - continue; -#endif - if ( ret <= 0 ) - return ret; - - p->sec_buf_in.buf_ptr += ret; - } - - /* The new packet always starts at p->sec_buf_in.buf_base */ - ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base, - sbiod->sbiod_sb->sb_debug ); - - /* Grow the packet buffer if neccessary */ - if ( ( p->sec_buf_in.buf_size < ret ) && - ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) { - errno = ENOMEM; - return -1; - } - p->sec_buf_in.buf_end = ret; - - /* Did we read the whole encrypted packet? */ - while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { - /* No, we have got only a part of it */ - ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; - - ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + - p->sec_buf_in.buf_ptr, ret ); -#ifdef EINTR - if ( ( ret < 0 ) && ( errno == EINTR ) ) - continue; -#endif - if ( ret <= 0 ) - return ret; - - p->sec_buf_in.buf_ptr += ret; - } - - /* Decode the packet */ - ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base, - p->sec_buf_in.buf_end, &p->buf_in.buf_base, - (unsigned *)&p->buf_in.buf_end ); - if ( ret != SASL_OK ) { - ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, - "sb_sasl_read: failed to decode packet: %s\n", - sasl_errstring( ret, NULL, NULL ) ); - sb_sasl_drop_packet( &p->sec_buf_in, - sbiod->sbiod_sb->sb_debug ); - errno = EIO; - return -1; - } - - /* Drop the packet from the input buffer */ - sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug ); - - p->buf_in.buf_size = p->buf_in.buf_end; - - bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); - - return bufptr; -} - -static ber_slen_t -sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) -{ - struct sb_sasl_data *p; - int ret; - - assert( sbiod != NULL ); - assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); - - p = (struct sb_sasl_data *)sbiod->sbiod_pvt; - - /* Are there anything left in the buffer? */ - if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { - ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); - if ( ret <= 0 ) - return ret; - } - - /* now encode the next packet. */ - ber_pvt_sb_buf_destroy( &p->buf_out ); - ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base, - (unsigned *)&p->buf_out.buf_size ); - if ( ret != SASL_OK ) { - ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, - "sb_sasl_write: failed to encode packet: %s\n", - sasl_errstring( ret, NULL, NULL ) ); - return -1; - } - p->buf_out.buf_end = p->buf_out.buf_size; - - ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); - if ( ret <= 0 ) - return ret; - return len; -} - -static int -sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) -{ - struct sb_sasl_data *p; - - p = (struct sb_sasl_data *)sbiod->sbiod_pvt; - - if ( opt == LBER_SB_OPT_DATA_READY ) { - if ( p->buf_in.buf_ptr != p->buf_in.buf_end ) - return 1; - } - - return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); -} - -Sockbuf_IO ldap_pvt_sockbuf_io_sasl = -{ - sb_sasl_setup, /* sbi_setup */ - sb_sasl_remove, /* sbi_remove */ - sb_sasl_ctrl, /* sbi_ctrl */ - sb_sasl_read, /* sbi_read */ - sb_sasl_write, /* sbi_write */ - NULL /* sbi_close */ -}; - -int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg ) -{ - /* don't install the stuff unless security has been negotiated */ - - if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, - &ldap_pvt_sockbuf_io_sasl ) ) - ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl, - LBER_SBIOD_LEVEL_APPLICATION, ctx_arg ); - - return LDAP_SUCCESS; -} - -static int -sasl_err2ldap( int saslerr ) -{ - int rc; - - switch (saslerr) { - case SASL_CONTINUE: - rc = LDAP_MORE_RESULTS_TO_RETURN; - break; - case SASL_OK: - rc = LDAP_SUCCESS; - break; - case SASL_FAIL: - rc = LDAP_LOCAL_ERROR; - break; - case SASL_NOMEM: - rc = LDAP_NO_MEMORY; - break; - case SASL_NOMECH: - rc = LDAP_AUTH_UNKNOWN; - break; - case SASL_BADAUTH: - rc = LDAP_AUTH_UNKNOWN; - break; - case SASL_NOAUTHZ: - rc = LDAP_PARAM_ERROR; - break; - case SASL_TOOWEAK: - case SASL_ENCRYPT: - rc = LDAP_AUTH_UNKNOWN; - break; - default: - rc = LDAP_LOCAL_ERROR; - break; - } - - assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) ); - return rc; -} - int ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) { @@ -739,7 +379,7 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) return ld->ld_errno; } - mechlist = array2str( values ); + mechlist = ldap_charray2str( values, " " ); if ( mechlist == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; LDAP_VFREE( values ); @@ -755,361 +395,47 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist ) return LDAP_SUCCESS; } -int -ldap_pvt_sasl_bind( - LDAP *ld, - LDAP_CONST char *dn, - LDAP_CONST char *mechs, - LDAP_CONST sasl_callback_t *callbacks, - LDAPControl **sctrls, - LDAPControl **cctrls ) -{ - const char *mech; - int saslrc, rc; - sasl_ssf_t *ssf = NULL; - unsigned credlen; - struct berval ccred, *scred; - char *host; - sasl_interact_t *client_interact = NULL; - struct sockaddr_in sin; - socklen_t len; - sasl_security_properties_t secprops; - ber_socket_t sd; - - Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 ); - - /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ - if (ld->ld_version < LDAP_VERSION3) { - ld->ld_errno = LDAP_NOT_SUPPORTED; - return ld->ld_errno; - } - - ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); - - if ( sd == AC_SOCKET_INVALID ) { - /* not connected yet */ - int rc = ldap_open_defconn( ld ); - - if( rc < 0 ) return ld->ld_errno; - ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ); - } - - /* XXX this doesn't work with PF_LOCAL hosts */ - host = ldap_host_connected_to( ld->ld_sb ); - - if ( host == NULL ) { - ld->ld_errno = LDAP_UNAVAILABLE; - return ld->ld_errno; - } - - if ( ld->ld_sasl_context != NULL ) { - sasl_dispose( &ld->ld_sasl_context ); - } - - saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER, - &ld->ld_sasl_context ); - - LDAP_FREE( host ); - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - ld->ld_errno = sasl_err2ldap( saslrc ); - sasl_dispose( &ld->ld_sasl_context ); - return ld->ld_errno; - } - - len = sizeof( sin ); - if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) { - Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n", - 0, 0, 0 ); - ld->ld_errno = LDAP_OPERATIONS_ERROR; - return ld->ld_errno; - } - sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin ); - - len = sizeof( sin ); - if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) { - Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n", - 0, 0, 0 ); - ld->ld_errno = LDAP_OPERATIONS_ERROR; - return ld->ld_errno; - } - sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin ); - - memset( &secprops, '\0', sizeof( secprops ) ); - secprops.min_ssf = ld->ld_options.ldo_sasl_minssf; - secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf; - secprops.security_flags = SASL_SECURITY_LAYER; - secprops.maxbufsize = 65536; - sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops ); - - ccred.bv_val = NULL; - ccred.bv_len = 0; - - saslrc = sasl_client_start( ld->ld_sasl_context, - mechs, - NULL, - &client_interact, - &ccred.bv_val, - &credlen, - &mech ); - - ccred.bv_len = credlen; - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - ld->ld_errno = sasl_err2ldap( saslrc ); - sasl_dispose( &ld->ld_sasl_context ); - return ld->ld_errno; - } - - scred = NULL; - - do { - unsigned credlen; - sasl_interact_t *client_interact = NULL; - - rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred ); - if ( rc == LDAP_SUCCESS ) { - break; - } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) { - if ( ccred.bv_val != NULL ) { - LDAP_FREE( ccred.bv_val ); - } - sasl_dispose( &ld->ld_sasl_context ); - return ld->ld_errno; - } - - if ( ccred.bv_val != NULL ) { - LDAP_FREE( ccred.bv_val ); - ccred.bv_val = NULL; - } - - saslrc = sasl_client_step( ld->ld_sasl_context, - (scred == NULL) ? NULL : scred->bv_val, - (scred == NULL) ? 0 : scred->bv_len, - &client_interact, - &ccred.bv_val, - &credlen ); - - ccred.bv_len = credlen; - ber_bvfree( scred ); - - if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) { - ld->ld_errno = sasl_err2ldap( saslrc ); - sasl_dispose( &ld->ld_sasl_context ); - return ld->ld_errno; - } - } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); - - assert ( rc == LDAP_SUCCESS ); - - if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf ) - == SASL_OK && ssf && *ssf ) { - ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context ); - } - - return rc; -} - -/* based on sample/sample-client.c */ -static int -ldap_pvt_sasl_getsecret(sasl_conn_t *conn, - void *context, int id, sasl_secret_t **psecret) -{ - struct berval *passphrase = (struct berval *)context; - size_t len; - - if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) { - return SASL_BADPARAM; - } - - len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0; - - *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len ); - if ( *psecret == NULL ) { - return SASL_NOMEM; - } - - (*psecret)->len = passphrase->bv_len; - - if ( passphrase != NULL ) { - memcpy((*psecret)->data, passphrase->bv_val, len); - } - - return SASL_OK; -} - -static int -ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len) -{ - const char *value = (const char *)context; - - if ( result == NULL ) { - return SASL_BADPARAM; - } - - switch ( id ) { - case SASL_CB_USER: - case SASL_CB_AUTHNAME: - *result = value; - if ( len ) - *len = value ? strlen( value ) : 0; - break; - case SASL_CB_LANGUAGE: - *result = NULL; - if ( len ) - *len = 0; - break; - default: - return SASL_BADPARAM; - } - - return SASL_OK; -} - -int -ldap_pvt_sasl_get_option( LDAP *ld, int option, void *arg ) -{ - sasl_ssf_t *ssf; - - if ( ld == NULL ) - return -1; - - switch ( option ) { - case LDAP_OPT_X_SASL_MINSSF: - *(int *)arg = ld->ld_options.ldo_sasl_minssf; - break; - case LDAP_OPT_X_SASL_MAXSSF: - *(int *)arg = ld->ld_options.ldo_sasl_maxssf; - break; - case LDAP_OPT_X_SASL_ACTSSF: - if ( ld->ld_sasl_context == NULL ) { - *(int *)arg = -1; - break; - } - if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, - (void **) &ssf ) != SASL_OK ) - { - return -1; - } - *(int *)arg = *ssf; - break; - default: - return -1; - } - return 0; -} - -int -ldap_pvt_sasl_set_option( LDAP *ld, int option, void *arg ) -{ - if ( ld == NULL ) - return -1; - - switch ( option ) { - case LDAP_OPT_X_SASL_MINSSF: - ld->ld_options.ldo_sasl_minssf = *(int *)arg; - break; - case LDAP_OPT_X_SASL_MAXSSF: - ld->ld_options.ldo_sasl_maxssf = *(int *)arg; - break; - case LDAP_OPT_X_SASL_ACTSSF: - /* This option is read-only */ - default: - return -1; - } - return 0; -} - /* - * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500) - * using SASL authentication. + * ldap_sasl_interactive_bind_s - interactive SASL authentication * - * This routine attempts to authenticate the user referred by the - * authentication id using the provided password. An optional - * authorization identity may be provided. An DN is generally not - * provided [see AuthMethod]. + * This routine uses interactive callbacks. * - * If the mechanism negotiated does not require a password, the - * passwd field is ignored. [A callback mechanism should really - * be used]. - * * LDAP_SUCCESS is returned upon success, the ldap error code * otherwise. - * - * Examples: - * ldap_negotiated_sasl_bind_s( ld, NULL, - * NULL, NULL, NULL, - * NULL, NULL, NULL, NULL ); - * - * ldap_negotiated_sasl_bind_s( ld, NULL, - * "user@OPENLDAP.ORG", NULL, NULL, - * "GSSAPI", NULL, NULL, NULL ); - * - * ldap_negotiated_sasl_bind_s( ld, NULL, - * "manager", "dn:cn=user,dc=openldap,dc=org", NULL, - * "DIGEST-MD5", NULL, NULL, NULL ); - * - * ldap_negotiated_sasl_bind_s( ld, NULL, - * "root@OPENLDAP.ORG", "u:user@OPENLDAP.ORG", NULL, - * "GSSAPI", NULL, NULL, NULL ); - * - * ldap_negotiated_sasl_bind_s( ld, NULL, - * "manager", "dn:cn=user,dc=openldap,dc=org", NULL, - * "DIGEST-MD5", NULL, NULL, NULL ); */ int -ldap_negotiated_sasl_bind_s( +ldap_sasl_interactive_bind_s( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ - LDAP_CONST char *authenticationId, - LDAP_CONST char *authorizationId, /* commonly NULL */ - LDAP_CONST char *saslMechanism, - struct berval *passPhrase, + LDAP_CONST char *mechs, LDAPControl **serverControls, LDAPControl **clientControls) { - int n; - sasl_callback_t callbacks[4]; int rc; - Debug( LDAP_DEBUG_TRACE, "ldap_negotiated_sasl_bind_s\n", 0, 0, 0 ); + if( mechs == NULL || *mechs == '\0' ) { + char *smechs; - if( saslMechanism == NULL || *saslMechanism == '\0' ) { - char *mechs; - rc = ldap_pvt_sasl_getmechs( ld, &mechs ); + rc = ldap_pvt_sasl_getmechs( ld, &smechs ); if( rc != LDAP_SUCCESS ) { return rc; } - saslMechanism = mechs; - } + Debug( LDAP_DEBUG_TRACE, + "ldap_interactive_sasl_bind_s: server supports: %s\n", + smechs, 0, 0 ); - /* SASL Authentication Identity */ - callbacks[n=0].id = SASL_CB_AUTHNAME; - callbacks[n].proc = ldap_pvt_sasl_getsimple; - callbacks[n].context = (void *)authenticationId; + mechs = smechs; - /* SASL Authorization Identity (userid) */ - if( authorizationId != NULL ) { - callbacks[++n].id = SASL_CB_USER; - callbacks[n].proc = ldap_pvt_sasl_getsimple; - callbacks[n].context = (void *)authorizationId; + } else { + Debug( LDAP_DEBUG_TRACE, + "ldap_interactive_sasl_bind_s: user selected: %s\n", + mechs, 0, 0 ); } - callbacks[++n].id = SASL_CB_PASS; - callbacks[n].proc = ldap_pvt_sasl_getsecret; - callbacks[n].context = (void *)passPhrase; - - callbacks[++n].id = SASL_CB_LIST_END; - callbacks[n].proc = NULL; - callbacks[n].context = NULL; - - assert( n * sizeof(sasl_callback_t) < sizeof(callbacks) ); - - rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks, - serverControls, clientControls); + rc = ldap_int_sasl_bind( ld, dn, mechs, + serverControls, clientControls ); return rc; } -#endif /* HAVE_CYRUS_SASL */ diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 3ecb5f4c40..f31c95239b 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -59,6 +59,8 @@ static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); static SSL_CTX *tls_def_ctx = NULL; +static int tls_seed_PRNG( const char *randfile ); + #ifdef LDAP_R_COMPILE /* * provide mutexes for the SSLeay library. @@ -626,6 +628,7 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) #endif return -1; } + return 0; } @@ -668,7 +671,7 @@ ldap_pvt_tls_get_peer_issuer( LDAP *ld ) } int -ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) +ldap_int_tls_config( struct ldapoptions *lo, int option, const char *arg ) { int i; @@ -699,9 +702,9 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) if (i >= 0) return ldap_pvt_tls_set_option( lo, option, &i ); return -1; - default: - return -1; } + + return -1; } int diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c index 98a559669f..a0b51a87c7 100644 --- a/libraries/libldap/unbind.c +++ b/libraries/libldap/unbind.c @@ -148,12 +148,6 @@ ldap_ld_free( ld->ld_options.ldo_tm_net = NULL; } -#ifdef HAVE_CYRUS_SASL - if ( ld->ld_sasl_context != NULL ) { - sasl_dispose( &ld->ld_sasl_context ); - } -#endif - ber_sockbuf_free( ld->ld_sb ); LDAP_FREE( (char *) ld ); diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in index 9ade237ee5..cc66467695 100644 --- a/libraries/libldap_r/Makefile.in +++ b/libraries/libldap_r/Makefile.in @@ -12,7 +12,7 @@ PROGRAMS = apitest ltest ttest XXDIR = $(srcdir)/../libldap XXSRCS = apitest.c test.c tmpltest.c extended.c \ bind.c controls.c open.c result.c error.c compare.c search.c \ - modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \ + modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c cyrus.c \ getfilter.c sasl.c sbind.c kbind.c unbind.c friendly.c cldap.c \ free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ @@ -28,7 +28,7 @@ OBJS = threads.lo rdwr.lo tpool.lo \ thr_pth.lo thr_stub.lo \ extended.lo \ bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \ - modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \ + modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo cyrus.lo \ getfilter.lo sasl.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \ free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in index be9f2a08d5..7baa43eb98 100644 --- a/libraries/liblutil/Makefile.in +++ b/libraries/liblutil/Makefile.in @@ -13,11 +13,11 @@ NT_OBJS = ntservice.o slapdmsg.res UNIX_SRCS = detach.c UNIX_OBJS = detach.o -SRCS = base64.c debug.c entropy.c \ +SRCS = base64.c debug.c entropy.c sasl.c \ md5.c passwd.c sha1.c getpass.c lockf.c utils.c sockpair.c \ @LIBSRCS@ $(@PLAT@_SRCS) -OBJS = base64.o debug.o entropy.o \ +OBJS = base64.o debug.o entropy.o sasl.o \ md5.o passwd.o sha1.o getpass.o lockf.o utils.o sockpair.o \ @LIBOBJS@ $(@PLAT@_OBJS) diff --git a/libraries/liblutil/authpasswd.c b/libraries/liblutil/authpasswd.c index 1fc4d74c71..e179f32dbc 100644 --- a/libraries/liblutil/authpasswd.c +++ b/libraries/liblutil/authpasswd.c @@ -609,7 +609,7 @@ static int chk_kerberos( } { - char host[MAXHOSTNAMELEN]; + char host[MAXHOSTNAMELEN+1]; if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) { krb5_free_principal( context, client ); @@ -617,6 +617,8 @@ static int chk_kerberos( return 1; } + host[MAXHOSTNAMELEN] = '\0'; + ret = krb5_sname_to_principal( context, host, "ldap", KRB5_NT_SRV_HST, &server ); } @@ -926,4 +928,4 @@ static struct berval *hash_crypt( return pw_string( scheme, &hash ); } #endif -#endif \ No newline at end of file +#endif diff --git a/libraries/liblutil/passwd.c b/libraries/liblutil/passwd.c index becde0e6c5..f6f791066b 100644 --- a/libraries/liblutil/passwd.c +++ b/libraries/liblutil/passwd.c @@ -726,7 +726,7 @@ static int chk_kerberos( } { - char host[MAXHOSTNAMELEN]; + char host[MAXHOSTNAMELEN+1]; if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) { krb5_free_principal( context, client ); @@ -734,6 +734,8 @@ static int chk_kerberos( return 1; } + host[MAXHOSTNAMELEN] = '\0'; + ret = krb5_sname_to_principal( context, host, "ldap", KRB5_NT_SRV_HST, &server ); } diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c new file mode 100644 index 0000000000..65a3ef821a --- /dev/null +++ b/libraries/liblutil/sasl.c @@ -0,0 +1,114 @@ +/* $OpenLDAP$ */ +/* + * Copyright 2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#ifdef HAVE_CYRUS_SASL + +#include +#include +#include +#include + +#include + +#include +#include "lutil_ldap.h" + +static int interaction( + sasl_interact_t *interact ) +{ + char input[1024]; + + int noecho=0; + int challenge=0; + + switch( interact->id ) { + case SASL_CB_NOECHOPROMPT: + noecho = 1; + challenge = 1; + break; + case SASL_CB_ECHOPROMPT: + challenge = 1; + break; + case SASL_CB_PASS: + noecho = 1; + break; + } + + if( challenge ) { + if( interact->challenge ) { + fprintf( stderr, "Challenge: %s\n", interact->challenge ); + } + if( interact->defresult ) { + fprintf( stderr, "Default Result: %s\n", interact->defresult ); + } + } + + sprintf( input, "%s: ", + interact->prompt ? interact->prompt : "Interaction required" ); + + if( noecho ) { + interact->result = (char *) getpassphrase( input ); + interact->len = interact->result + ? strlen( interact->result ) : 0; + + } else { + /* prompt user */ + fputs( input, stderr ); + + /* get input */ + interact->result = fgets( input, sizeof(input), stdin ); + + if( interact->result == NULL ) { + interact->len = 0; + return LDAP_UNAVAILABLE; + } + + /* len of input */ + interact->len = strlen(input); + + if( interact->len > 0 && input[interact->len - 1] == '\n' ) { + /* input includes '\n', trim it */ + interact->len--; + input[interact->len] = '\0'; + } + } + + + if( interact->len > 0 ) { + /* duplicate */ + char *p = interact->result; + interact->result = strdup( p ); + + /* zap */ + memset( p, '\0', interact->len ); + + } else { + /* must be empty */ + interact->result = strdup(""); + } + + return LDAP_SUCCESS; +} + +int lutil_sasl_interact( + LDAP *ld, + void *in ) +{ + sasl_interact_t *interact = in; + + while( interact->id != SASL_CB_LIST_END ) { + int rc = interaction( interact ); + + if( rc ) return rc; + interact++; + } + + return LDAP_SUCCESS; +} + +#endif diff --git a/servers/slapd/back-dnssrv/init.c b/servers/slapd/back-dnssrv/init.c index d1e0091d86..5e25c0055c 100644 --- a/servers/slapd/back-dnssrv/init.c +++ b/servers/slapd/back-dnssrv/init.c @@ -68,12 +68,6 @@ dnssrv_back_initialize( bi->bi_acl_group = 0; bi->bi_acl_attribute = 0; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index eb62b343b0..b98945a7d0 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -78,12 +78,6 @@ ldap_back_initialize( bi->bi_acl_attribute = ldap_back_attribute; bi->bi_chk_referrals = 0; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = ldap_back_conn_destroy; diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index aff7a076b1..d81105ae8c 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -82,12 +82,6 @@ ldbm_back_initialize( bi->bi_tool_index_attr = ldbm_tool_index_attr; bi->bi_tool_sync = ldbm_tool_sync; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index a50cc73196..6cc7d08c2d 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -204,30 +204,6 @@ int ldbm_modify_internal LDAP_P((Backend *be, const char *dn, Modifications *mods, Entry *e, const char ** )); -#ifdef HAVE_CYRUS_SASL -/* - * sasl.c - */ -int ldbm_sasl_authorize LDAP_P(( - BackendDB *be, - const char *auth_identity, - const char *requested_user, - const char **user, - const char **errstring )); -int ldbm_sasl_getsecret LDAP_P(( - Backend *be, - const char *mechanism, - const char *auth_identity, - const char *realm, - sasl_secret_t **secret )); -int ldbm_sasl_putsecret LDAP_P(( - Backend *be, - const char *mechanism, - const char *auth_identity, - const char *realm, - const sasl_secret_t *secret )); -#endif /* HAVE_CYRUS_SASL */ - /* * nextid.c */ diff --git a/servers/slapd/back-ldbm/sasl.c b/servers/slapd/back-ldbm/sasl.c index 37e6c7afef..b7812a00e3 100644 --- a/servers/slapd/back-ldbm/sasl.c +++ b/servers/slapd/back-ldbm/sasl.c @@ -5,10 +5,11 @@ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ -#ifdef HAVE_CYRUS_SASL #include "portable.h" +#if 0 + #include #include diff --git a/servers/slapd/back-passwd/init.c b/servers/slapd/back-passwd/init.c index accff0551a..5190bff4c1 100644 --- a/servers/slapd/back-passwd/init.c +++ b/servers/slapd/back-passwd/init.c @@ -57,12 +57,6 @@ passwd_back_initialize( bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-perl/init.c b/servers/slapd/back-perl/init.c index e2201c2b38..aafd9fd639 100644 --- a/servers/slapd/back-perl/init.c +++ b/servers/slapd/back-perl/init.c @@ -100,12 +100,6 @@ perl_back_initialize( bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-shell/init.c b/servers/slapd/back-shell/init.c index b05b029132..ddebb961ef 100644 --- a/servers/slapd/back-shell/init.c +++ b/servers/slapd/back-shell/init.c @@ -61,12 +61,6 @@ shell_back_initialize( bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; -#ifdef HAVE_CYRUS_SASL - bi->bi_sasl_authorize = 0; - bi->bi_sasl_getsecret = 0; - bi->bi_sasl_putsecret = 0; -#endif /* HAVE_CYRUS_SASL */ - bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index 8239c9c3ef..cc53421bcb 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -37,6 +37,7 @@ do_bind( ber_int_t version; ber_tag_t method; char *mech; + char *saslmech; char *dn; char *ndn; ber_tag_t tag; @@ -204,30 +205,15 @@ do_bind( goto cleanup; } - if( !charray_inlist( supportedSASLMechanisms, mech ) ) { - Debug( LDAP_DEBUG_ANY, - "do_bind: sasl mechanism=\"%s\" not supported.\n", - mech, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED, - NULL, "SASL mechanism not supported", NULL, NULL ); - goto cleanup; - } - ldap_pvt_thread_mutex_lock( &conn->c_mutex ); if ( conn->c_sasl_bind_mech != NULL ) { /* SASL bind is in progress */ -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context != NULL ); -#endif + saslmech = NULL; if((strcmp(conn->c_sasl_bind_mech, mech) != 0)) { /* mechanism changed */ -#ifdef HAVE_CYRUS_SASL - /* dispose of context */ - sasl_dispose(&conn->c_sasl_bind_context); - conn->c_sasl_bind_context = NULL; -#endif + slap_sasl_reset(conn); } free( conn->c_sasl_bind_mech ); @@ -236,39 +222,28 @@ do_bind( #ifdef LDAP_DEBUG } else { /* SASL bind is NOT in progress */ + saslmech = mech; assert( conn->c_sasl_bind_mech == NULL ); -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context == NULL ); -#endif #endif } ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); edn = NULL; - rc = sasl_bind( conn, op, dn, ndn, mech, &cred, &edn ); + rc = slap_sasl_bind( conn, op, dn, ndn, saslmech, &cred, &edn ); if( rc == LDAP_SUCCESS ) { ldap_pvt_thread_mutex_lock( &conn->c_mutex ); -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context == NULL ); -#endif conn->c_dn = edn; + conn->c_authmech = mech; ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); } else if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) { -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context != NULL ); -#endif conn->c_sasl_bind_mech = mech; - mech = NULL; - -#ifdef HAVE_CYRUS_SASL - } else { - assert( conn->c_sasl_bind_context == NULL ); -#endif } + mech = NULL; + goto cleanup; } else { @@ -281,18 +256,11 @@ do_bind( free(conn->c_sasl_bind_mech); conn->c_sasl_bind_mech = NULL; -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context != NULL ); - sasl_dispose(&conn->c_sasl_bind_context); - conn->c_sasl_bind_context = NULL; -#endif } else { assert( !conn->c_sasl_bind_in_progress ); -#ifdef HAVE_CYRUS_SASL - assert( conn->c_sasl_bind_context == NULL ); -#endif } + slap_sasl_reset( conn ); ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); } @@ -390,14 +358,6 @@ cleanup: free( conn->c_sasl_bind_mech ); conn->c_sasl_bind_mech = NULL; -#ifdef HAVE_CYRUS_SASL - if( conn->c_sasl_bind_context != NULL ) { - /* dispose of context */ - sasl_dispose(&conn->c_sasl_bind_context); - conn->c_sasl_bind_context = NULL; - } -#endif - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); } diff --git a/servers/slapd/config.c b/servers/slapd/config.c index e031402ec8..e778c4ae63 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -116,7 +116,7 @@ read_config( const char *fname ) if( bi == NULL ) { Debug( LDAP_DEBUG_ANY, - "backend %s initialization failed.n", + "backend %s initialization failed.\n", cargv[1], 0, 0 ); return( 1 ); } @@ -135,7 +135,7 @@ read_config( const char *fname ) if( be == NULL ) { Debug( LDAP_DEBUG_ANY, - "database %s initialization failed.n", + "database %s initialization failed.\n", cargv[1], 0, 0 ); return( 1 ); } @@ -208,7 +208,7 @@ read_config( const char *fname ) } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) { if ( cargc < 2 ) { Debug( LDAP_DEBUG_ANY, - "%s: line %d: missing realm in \"password-hash \" line\n", + "%s: line %d: missing hash in \"password-hash \" line\n", fname, lineno, 0 ); return( 1 ); } @@ -222,11 +222,11 @@ read_config( const char *fname ) default_passwd_hash = ch_strdup( cargv[1] ); } - /* set DIGEST realm */ - } else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) { + /* set SASL realm */ + } else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) { if ( cargc < 2 ) { Debug( LDAP_DEBUG_ANY, - "%s: line %d: missing realm in \"digest-realm \" line\n", + "%s: line %d: missing realm in \"sasl-realm \" line\n", fname, lineno, 0 ); return( 1 ); } @@ -243,6 +243,25 @@ read_config( const char *fname ) global_realm = ch_strdup( cargv[1] ); } + /* SASL security properties */ + } else if ( strcasecmp( cargv[0], "sasl-secprops" ) == 0 ) { + char *txt; + + if ( cargc < 2 ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: missing flags in \"sasl-secprops \" line\n", + fname, lineno, 0 ); + return 1; + } + + txt = slap_sasl_secprops( cargv[1] ); + if ( txt != NULL ) { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: sasl-secprops: %s\n", + fname, lineno, txt ); + return 1; + } + /* set time limit */ } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) { if ( cargc < 2 ) { diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index adadffe8fc..e0d6fdf6de 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -288,7 +288,9 @@ long connection_init( const char* dnsname, const char* peername, const char* sockname, - int use_tls ) + int use_tls, + unsigned ssf, + char *authid ) { unsigned long id; Connection *c; @@ -376,9 +378,7 @@ long connection_init( c->c_pending_ops = NULL; c->c_sasl_bind_mech = NULL; -#ifdef HAVE_CYRUS_SASL - c->c_sasl_bind_context = NULL; -#endif + c->c_sasl_context = NULL; c->c_sb = ber_sockbuf_alloc( ); c->c_currentber = NULL; @@ -404,9 +404,7 @@ long connection_init( assert( c->c_ops == NULL ); assert( c->c_pending_ops == NULL ); assert( c->c_sasl_bind_mech == NULL ); -#ifdef HAVE_CYRUS_SASL - assert( c->c_sasl_bind_context == NULL ); -#endif + assert( c->c_sasl_context == NULL ); assert( c->c_currentber == NULL ); c->c_listener_url = ch_strdup( url ); @@ -441,6 +439,7 @@ long connection_init( s, c->c_peer_name, 0 ); } + id = c->c_connid = conn_nextid++; c->c_conn_state = SLAP_C_INACTIVE; @@ -455,6 +454,8 @@ long connection_init( c->c_needs_tls_accept = 0; } #endif + slap_sasl_open( c ); + slap_sasl_external( c, ssf, authid ); ldap_pvt_thread_mutex_unlock( &c->c_mutex ); ldap_pvt_thread_mutex_unlock( &connections_mutex ); @@ -531,12 +532,8 @@ connection_destroy( Connection *c ) free(c->c_sasl_bind_mech); c->c_sasl_bind_mech = NULL; } -#ifdef HAVE_CYRUS_SASL - if(c->c_sasl_bind_context != NULL ) { - sasl_dispose( &c->c_sasl_bind_context ); - c->c_sasl_bind_context = NULL; - } -#endif + + slap_sasl_close( c ); if ( c->c_currentber != NULL ) { ber_free( c->c_currentber, 1 ); @@ -917,8 +914,14 @@ int connection_read(ber_socket_t s) NULL); } connection_close( c ); + } else if ( rc == 0 ) { c->c_needs_tls_accept = 0; + +#if 0 + /* we need to let SASL know */ + slap_sasl_external( c, ssf, authid ); +#endif } connection_return( c ); ldap_pvt_thread_mutex_unlock( &connections_mutex ); diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 8c496ab0bc..56f52a6163 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -828,6 +828,8 @@ slapd_daemon_task( ber_int_t s; socklen_t len = sizeof(from); long id; + unsigned ssf = 0; + char *authid = NULL; char *dnsname; char *peeraddr; @@ -899,6 +901,7 @@ slapd_daemon_task( # ifdef LDAP_PF_LOCAL case AF_LOCAL: sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path ); + ssf = LDAP_PVT_SASL_LOCAL_SSF; break; #endif /* LDAP_PF_LOCAL */ @@ -966,18 +969,22 @@ slapd_daemon_task( #endif /* HAVE_TCPD */ } - if( (id = connection_init(s, + id = connection_init(s, slap_listeners[l]->sl_url, dnsname != NULL ? dnsname : "unknown", peername, slap_listeners[l]->sl_name, #ifdef HAVE_TLS - slap_listeners[l]->sl_is_tls + slap_listeners[l]->sl_is_tls, #else - 0 + 0, #endif - )) < 0 ) - { + ssf, + authid ); + + if( authid ) ch_free(authid); + + if( id < 0 ) { Debug( LDAP_DEBUG_ANY, "daemon: connection_init(%ld, %s, %s) failed.\n", (long) s, diff --git a/servers/slapd/init.c b/servers/slapd/init.c index 2e25add973..5c41461dff 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -107,7 +107,11 @@ slap_init( int mode, const char *name ) ldap_pvt_thread_mutex_init( &crypt_mutex ); #endif - rc = backend_init( ); + rc = slap_sasl_init(); + + if( rc == 0 ) { + rc = backend_init( ); + } break; default: @@ -130,10 +134,6 @@ int slap_startup( Backend *be ) rc = backend_startup( be ); - if( rc == 0 ) { - rc = sasl_init(); - } - return rc; } @@ -145,7 +145,7 @@ int slap_shutdown( Backend *be ) "%s shutdown: initiated\n", slap_name, 0, 0 ); - sasl_destroy(); + slap_sasl_destroy(); /* let backends do whatever cleanup they need to do */ rc = backend_shutdown( be ); diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 27cf5cedff..d95a2b50c4 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -268,7 +268,9 @@ LDAP_SLAPD_F (long) connection_init LDAP_P(( const char* dnsname, const char* peername, const char* sockname, - int use_tls )); + int use_tls, + unsigned ssf, + char *id )); LDAP_SLAPD_F (void) connection_closing LDAP_P(( Connection *c )); LDAP_SLAPD_F (int) connection_state_closing LDAP_P(( Connection *c )); @@ -526,12 +528,22 @@ LDAP_SLAPD_F (int) str2result LDAP_P(( char *s, /* * sasl.c */ -LDAP_SLAPD_F (char **) supportedSASLMechanisms; -LDAP_SLAPD_F (int) sasl_init(void); -LDAP_SLAPD_F (int) sasl_destroy(void); -LDAP_SLAPD_F (int) sasl_errldap LDAP_P(( int )); -LDAP_SLAPD_F (int) sasl_bind LDAP_P(( +LDAP_SLAPD_F (int) slap_sasl_init(void); +LDAP_SLAPD_F (char *) slap_sasl_secprops( const char * ); +LDAP_SLAPD_F (int) slap_sasl_destroy(void); + +LDAP_SLAPD_F (int) slap_sasl_open( Connection *c ); +LDAP_SLAPD_F (char **) slap_sasl_mechs( Connection *c ); + +LDAP_SLAPD_F (int) slap_sasl_external( Connection *c, + unsigned ssf, /* relative strength of external security */ + char *authid ); /* asserted authenication id */ + +LDAP_SLAPD_F (int) slap_sasl_reset( Connection *c ); +LDAP_SLAPD_F (int) slap_sasl_close( Connection *c ); + +LDAP_SLAPD_F (int) slap_sasl_bind LDAP_P(( Connection *conn, Operation *op, const char *dn, const char *ndn, const char *mech, struct berval *cred, @@ -820,7 +832,9 @@ LDAP_SLAPD_F (int) config_info LDAP_P(( Entry **e, const char **text )); LDAP_SLAPD_F (int) root_dse_info LDAP_P(( - Entry **e, const char **text )); + Connection *conn, + Entry **e, + const char **text )); LDAP_SLAPD_F (int) do_abandon LDAP_P((Connection *conn, Operation *op)); LDAP_SLAPD_F (int) do_add LDAP_P((Connection *conn, Operation *op)); diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index f987948c1e..8a9cfc653c 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -18,13 +18,17 @@ #include "slap.h" int -root_dse_info( Entry **entry, const char **text ) +root_dse_info( + Connection *conn, + Entry **entry, + const char **text ) { char buf[BUFSIZ]; Entry *e; struct berval val; struct berval *vals[2]; int i, j; + char ** supportedSASLMechanisms; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_namingContexts = slap_schema.si_ad_namingContexts; @@ -85,6 +89,8 @@ root_dse_info( Entry **entry, const char **text ) } /* supportedSASLMechanism */ + supportedSASLMechanisms = slap_sasl_mechs( conn ); + if( supportedSASLMechanisms != NULL ) { for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) { val.bv_val = supportedSASLMechanisms[i]; diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c index 23dfaae8fa..01018aa809 100644 --- a/servers/slapd/sasl.c +++ b/servers/slapd/sasl.c @@ -15,41 +15,18 @@ #include #include -char **supportedSASLMechanisms = NULL; -char *sasl_host = NULL; - #ifdef HAVE_CYRUS_SASL +#include +#include + +#include #ifdef SLAPD_SPASSWD #include #endif -static void *slap_sasl_mutex_new(void) -{ - ldap_pvt_thread_mutex_t *mutex; - - mutex = (ldap_pvt_thread_mutex_t *) ch_malloc( sizeof(ldap_pvt_thread_mutex_t) ); - if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) { - return mutex; - } - return NULL; -} - -static int slap_sasl_mutex_lock(void *mutex) -{ - return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex ); -} - -static int slap_sasl_mutex_unlock(void *mutex) -{ - return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex ); -} - -static void slap_sasl_mutex_dispose(void *mutex) -{ - (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex ); - free( mutex ); -} +static char *sasl_host = NULL; +static sasl_security_properties_t sasl_secprops; static int slap_sasl_err2ldap( int saslerr ) @@ -60,9 +37,6 @@ slap_sasl_err2ldap( int saslerr ) case SASL_CONTINUE: rc = LDAP_SASL_BIND_IN_PROGRESS; break; - case SASL_OK: - rc = LDAP_SUCCESS; - break; case SASL_FAIL: rc = LDAP_OTHER; break; @@ -89,24 +63,33 @@ slap_sasl_err2ldap( int saslerr ) return rc; } +#endif -int sasl_init( void ) +int slap_sasl_init( void ) { +#ifdef HAVE_CYRUS_SASL int rc; - char *mechs; sasl_conn_t *server = NULL; + static sasl_callback_t server_callbacks[] = { + { SASL_CB_LIST_END, NULL, NULL } + }; - sasl_set_alloc( ch_malloc, ch_calloc, ch_realloc, ch_free ); + sasl_set_alloc( + ch_malloc, + ch_calloc, + ch_realloc, + ch_free ); sasl_set_mutex( - slap_sasl_mutex_new, - slap_sasl_mutex_lock, - slap_sasl_mutex_unlock, - slap_sasl_mutex_dispose ); + ldap_pvt_sasl_mutex_new, + ldap_pvt_sasl_mutex_lock, + ldap_pvt_sasl_mutex_unlock, + ldap_pvt_sasl_mutex_dispose ); + /* should provide callbacks for logging */ /* server name should be configurable */ - rc = sasl_server_init( NULL, "slapd" ); + rc = sasl_server_init( server_callbacks, "slapd" ); if( rc != SASL_OK ) { Debug( LDAP_DEBUG_ANY, "sasl_server_init failed\n", @@ -123,69 +106,165 @@ int sasl_init( void ) } } - rc = sasl_server_new( "ldap", sasl_host, NULL, NULL, - SASL_SECURITY_LAYER, - &server ); + Debug( LDAP_DEBUG_TRACE, + "slap_sasl_init: %s initialized!\n", + sasl_host, 0, 0 ); - if( rc != SASL_OK ) { - Debug( LDAP_DEBUG_ANY, "sasl_server_new failed\n", - 0, 0, 0 ); + /* default security properties */ + memset( &sasl_secprops, '\0', sizeof(sasl_secprops) ); + sasl_secprops.max_ssf = UINT_MAX; + sasl_secprops.maxbufsize = 65536; + sasl_secprops.security_flags = SASL_SEC_NOPLAINTEXT|SASL_SEC_NOANONYMOUS; + +#ifdef SLAPD_SPASSWD + lutil_passwd_sasl_conn = server; +#else + sasl_dispose( &server ); +#endif + +#endif + return 0; +} + +int slap_sasl_destroy( void ) +{ +#ifdef HAVE_CYRUS_SASL +#ifdef SLAPD_SPASSWD + sasl_dispose( &lutil_passwd_sasl_conn ); +#endif + sasl_done(); +#endif + return 0; +} + +int slap_sasl_open( Connection *conn ) +{ + int sc = LDAP_SUCCESS; + +#ifdef HAVE_CYRUS_SASL + sasl_conn_t *ctx = NULL; + + /* create new SASL context */ + sc = sasl_server_new( "ldap", sasl_host, global_realm, NULL, +#ifdef LDAP_SASL_SECURITY_LAYER + SASL_SECURITY_LAYER, +#else + 0, +#endif + &ctx ); + + + if( sc != SASL_OK ) { + Debug( LDAP_DEBUG_ANY, "sasl_server_new failed: %d\n", + sc, 0, 0 ); return -1; } -#ifndef SLAPD_IGNORE_RFC2829 - { - /* security flags should be configurable */ - sasl_security_properties_t secprops; - memset(&secprops, '\0', sizeof(secprops)); - secprops.security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS; - secprops.property_names = NULL; - secprops.property_values = NULL; - - rc = sasl_setprop( server, SASL_SEC_PROPS, &secprops ); - - if( rc != SASL_OK ) { - Debug( LDAP_DEBUG_ANY, "sasl_setprop failed\n", - 0, 0, 0 ); + conn->c_sasl_context = ctx; + + if( sc == SASL_OK ) { + sc = sasl_setprop( ctx, + SASL_SEC_PROPS, &sasl_secprops ); + + if( sc != SASL_OK ) { + Debug( LDAP_DEBUG_ANY, "sasl_setprop failed: %d\n", + sc, 0, 0 ); + slap_sasl_close( conn ); return -1; } } + + sc = slap_sasl_err2ldap( sc ); #endif + return sc; +} - rc = sasl_listmech( server, NULL, NULL, ",", NULL, - &mechs, NULL, NULL); +int slap_sasl_external( + Connection *conn, + unsigned ssf, + char *auth_id ) +{ +#ifdef HAVE_CYRUS_SASL + int sc; + sasl_conn_t *ctx = conn->c_sasl_context; + sasl_external_properties_t extprops; - if( rc != SASL_OK ) { - Debug( LDAP_DEBUG_ANY, "sasl_listmech failed: %d\n", - rc, 0, 0 ); - return -1; + if ( ctx == NULL ) { + return LDAP_UNAVAILABLE; } - Debug( LDAP_DEBUG_TRACE, "SASL mechanisms: %s\n", - mechs, 0, 0 ); + memset( &extprops, 0L, sizeof(extprops) ); + extprops.ssf = ssf; + extprops.auth_id = auth_id; - supportedSASLMechanisms = str2charray( mechs, "," ); + sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, + (void *) &extprops ); -#ifdef SLAPD_SPASSWD - lutil_passwd_sasl_conn = server; -#else - sasl_dispose( &server ); + if ( sc != SASL_OK ) { + return LDAP_OTHER; + } #endif - return 0; + return LDAP_SUCCESS; } -int sasl_destroy( void ) +int slap_sasl_reset( Connection *conn ) { -#ifdef SLAPD_SPASSWD - sasl_dispose( &lutil_passwd_sasl_conn ); +#ifdef HAVE_CYRUS_SASL + sasl_conn_t *ctx = conn->c_sasl_context; + + if( ctx != NULL ) { + } #endif - charray_free( supportedSASLMechanisms ); - return 0; + /* must return "anonymous" */ + return LDAP_SUCCESS; } +char ** slap_sasl_mechs( Connection *conn ) +{ + char **mechs = NULL; + #ifdef HAVE_CYRUS_SASL -int sasl_bind( + sasl_conn_t *ctx = conn->c_sasl_context; + + if( ctx != NULL ) { + int sc; + char *mechstr; + + sc = sasl_listmech( ctx, + NULL, NULL, ",", NULL, + &mechstr, NULL, NULL ); + + if( sc != SASL_OK ) { + Debug( LDAP_DEBUG_ANY, "slap_sasl_listmech failed: %d\n", + sc, 0, 0 ); + return NULL; + } + + mechs = str2charray( mechstr, "," ); + + ch_free( mechstr ); + } +#endif + + return mechs; +} + +int slap_sasl_close( Connection *conn ) +{ +#ifdef HAVE_CYRUS_SASL + sasl_conn_t *ctx = conn->c_sasl_context; + + if( ctx != NULL ) { + sasl_dispose( &ctx ); + } + + conn->c_sasl_context = NULL; +#endif + return LDAP_SUCCESS; +} + +int slap_sasl_bind( Connection *conn, Operation *op, const char *dn, @@ -194,112 +273,98 @@ int sasl_bind( struct berval *cred, char **edn ) { + int rc = 1; + +#ifdef HAVE_CYRUS_SASL + sasl_conn_t *ctx = conn->c_sasl_context; struct berval response; + unsigned reslen; const char *errstr; int sc; - int rc = 1; Debug(LDAP_DEBUG_ARGS, "==> sasl_bind: dn=\"%s\" mech=%s cred->bv_len=%d\n", dn, mech, cred ? cred->bv_len : 0 ); - if ( conn->c_sasl_bind_context == NULL ) { - sasl_callback_t callbacks[4]; - int cbnum = 0; - -#if 0 - if (be->be_sasl_authorize) { - callbacks[cbnum].id = SASL_CB_PROXY_POLICY; - callbacks[cbnum].proc = be->be_sasl_authorize; - callbacks[cbnum].context = be; - ++cbnum; - } - - if (be->be_sasl_getsecret) { - callbacks[cbnum].id = SASL_CB_SERVER_GETSECRET; - callbacks[cbnum].proc = be->be_sasl_getsecret; - callbacks[cbnum].context = be; - ++cbnum; - } - - if (be->be_sasl_putsecret) { - callbacks[cbnum].id = SASL_CB_SERVER_PUTSECRET; - callbacks[cbnum].proc = be->be_sasl_putsecret; - callbacks[cbnum].context = be; - ++cbnum; - } -#endif - - callbacks[cbnum].id = SASL_CB_LIST_END; - callbacks[cbnum].proc = NULL; - callbacks[cbnum].context = NULL; - - /* create new SASL context */ - sc = sasl_server_new( "ldap", sasl_host, global_realm, - callbacks, SASL_SECURITY_LAYER, &conn->c_sasl_bind_context ); - - if( sc != SASL_OK ) { - send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ), - NULL, "could not create new SASL context", NULL, NULL ); + if( ctx == NULL ) { + send_ldap_result( conn, op, LDAP_UNAVAILABLE, + NULL, "SASL unavailable on this session", NULL, NULL ); + return rc; + } - } else { - unsigned reslen; - conn->c_authmech = ch_strdup( mech ); - - sc = sasl_server_start( conn->c_sasl_bind_context, - conn->c_authmech, - cred->bv_val, cred->bv_len, - (char **)&response.bv_val, &reslen, &errstr ); - - response.bv_len = reslen; - - if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) { - send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ), - NULL, errstr, NULL, NULL ); - } - } + if ( mech != NULL ) { + sc = sasl_server_start( ctx, + mech, + cred->bv_val, cred->bv_len, + (char **)&response.bv_val, &reslen, &errstr ); } else { - unsigned reslen; - sc = sasl_server_step( conn->c_sasl_bind_context, + sc = sasl_server_step( ctx, cred->bv_val, cred->bv_len, (char **)&response.bv_val, &reslen, &errstr ); - - response.bv_len = reslen; - - if ( (sc != SASL_OK) && (sc != SASL_CONTINUE) ) { - send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ), - NULL, errstr, NULL, NULL ); - } } + response.bv_len = reslen; + if ( sc == SASL_OK ) { - char *authzid; + char *username = NULL; - sc = sasl_getprop( conn->c_sasl_bind_context, SASL_USERNAME, - (void **)&authzid ); + sc = sasl_getprop( ctx, + SASL_USERNAME, (void **)&username ); if ( sc != SASL_OK ) { + Debug(LDAP_DEBUG_TRACE, + "slap_sasl_bind: getprop(USERNAME) failed!\n", + 0, 0, 0); + send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ), NULL, "no SASL username", NULL, NULL ); + } else if ( username == NULL || *username == '\0' ) { + Debug(LDAP_DEBUG_TRACE, + "slap_sasl_bind: getprop(USERNAME) returned NULL!\n", + 0, 0, 0); + + send_ldap_result( conn, op, rc = LDAP_INSUFFICIENT_ACCESS, + NULL, "no SASL username", NULL, NULL ); + } else { - Debug(LDAP_DEBUG_TRACE, "sasl_bind: username=%s\n", - authzid, 0, 0); + char *realm = NULL; + sasl_ssf_t ssf = 0; + + (void) sasl_getprop( ctx, + SASL_REALM, (void **)&realm ); + + (void) sasl_getprop( ctx, + SASL_SSF, (void *)&ssf ); + + Debug(LDAP_DEBUG_TRACE, + "slap_sasl_bind: username=\"%s\" realm=\"%s\" ssf=%lu\n", + username ? username : "", + realm ? realm : "", + (unsigned long) ssf ); - if( !strncasecmp( authzid, "anonymous", sizeof("anonyous")-1 ) && - ( ( authzid[sizeof("anonymous")] == '\0' ) || - ( authzid[sizeof("anonymous")] == '@' ) ) ) + if( !strncasecmp( username, "anonymous", sizeof("anonyous")-1 ) && + ( ( username[sizeof("anonymous")] == '\0' ) || + ( username[sizeof("anonymous")] == '@' ) ) ) { - Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: anonymous\n", + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: anonymous\n", 0, 0, 0); } else { - *edn = ch_malloc( sizeof( "authzid=" ) + strlen( authzid ) ); - strcpy( *edn, "authzid=" ); - strcat( *edn, authzid ); + *edn = ch_malloc( sizeof( "uid= + realm=" ) + + ( username ? strlen( username ) : 0 ) + + ( realm ? strlen( realm ) : 0 ) ); - Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: authzdn: \"%s\"\n", + strcpy( *edn, "uid=" ); + strcat( *edn, username ); + + if( realm && *realm ) { + strcat( *edn, " + realm=" ); + strcat( *edn, realm ); + } + + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: authzdn: \"%s\"\n", *edn, 0, 0); } @@ -310,38 +375,29 @@ int sasl_bind( } else if ( sc == SASL_CONTINUE ) { send_ldap_sasl( conn, op, rc = LDAP_SASL_BIND_IN_PROGRESS, NULL, NULL, NULL, NULL, &response ); - } - if ( sc != SASL_CONTINUE && conn->c_sasl_bind_context != NULL ) { - sasl_dispose( &conn->c_sasl_bind_context ); - conn->c_sasl_bind_context = NULL; + } else { + send_ldap_result( conn, op, rc = slap_sasl_err2ldap( sc ), + NULL, errstr, NULL, NULL ); } - Debug(LDAP_DEBUG_TRACE, "<== sasl_bind: rc=%d\n", rc, 0, 0); - - return rc; -} -#endif /* HAVE_CYRUS_SASL */ + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: rc=%d\n", rc, 0, 0); #else -/* no SASL support */ -int sasl_bind( - Connection *conn, - Operation *op, - const char *dn, - const char *ndn, - const char *mech, - struct berval *cred, - char **edn ) -{ - int rc; - - send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, - NULL, "SASL unavailable", NULL, NULL ); + send_ldap_result( conn, op, rc = LDAP_UNAVAILABLE, + NULL, "SASL not supported", NULL, NULL ); +#endif return rc; } -int sasl_init( void ) { return 0; } -int sasl_destroy( void ) { return 0; } +char* slap_sasl_secprops( const char *in ) +{ +#ifdef HAVE_CYRUS_SASL + int rc = ldap_pvt_sasl_secprops( in, &sasl_secprops ); + + return rc == LDAP_SUCCESS ? NULL : "Invalid security properties"; +#else + return "SASL not supported"; #endif +} diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 3959645337..653fb886fa 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -159,7 +159,7 @@ do_search( Entry *entry = NULL; if ( strcasecmp( nbase, LDAP_ROOT_DSE ) == 0 ) { - rc = root_dse_info( &entry, &text ); + rc = root_dse_info( conn, &entry, &text ); } #if defined( SLAPD_MONITOR_DN ) diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index c55f231966..61e1a4dabc 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -19,10 +19,6 @@ #include #include -#ifdef HAVE_CYRUS_SASL -#include -#endif - #include "avl.h" #ifndef ldap_debug @@ -796,12 +792,6 @@ struct slap_backend_db { #define be_index_attr bd_info->bi_tool_index_attr #define be_index_change bd_info->bi_tool_index_change #define be_sync bd_info->bi_tool_sync -#endif - -#ifdef HAVE_CYRUS_SASL -#define be_sasl_authorize bd_info->bi_sasl_authorize -#define be_sasl_getsecret bd_info->bi_sasl_getsecret -#define be_sasl_putsecret bd_info->bi_sasl_putsecret #endif /* these should be renamed from be_ to bd_ */ @@ -977,18 +967,6 @@ struct slap_backend_info { struct berval **bv, ID id, int op )); int (*bi_tool_sync) LDAP_P(( BackendDB *be )); -#ifdef HAVE_CYRUS_SASL - int (*bi_sasl_authorize) LDAP_P(( BackendDB *be, - const char *authnid, const char *authzid, - const char **canon_authzid, const char **errstr )); - int (*bi_sasl_getsecret) LDAP_P(( BackendDB *be, - const char *mechanism, const char *authzid, - const char *realm, sasl_secret_t **secret )); - int (*bi_sasl_putsecret) LDAP_P(( BackendDB *be, - const char *mechanism, const char *auth_identity, - const char *realm, const sasl_secret_t *secret )); -#endif /* HAVE_CYRUS_SASL */ - #define SLAP_INDEX_ADD_OP 0x0001 #define SLAP_INDEX_DELETE_OP 0x0002 @@ -1012,18 +990,8 @@ typedef struct slap_op { ber_tag_t o_tag; /* tag of the request */ time_t o_time; /* time op was initiated */ -#ifdef SLAP_AUTHZID - /* should only be used for reporting purposes */ - char *o_authc_dn; /* authentication DN */ - - /* should be used as the DN of the User */ - char *o_authz_dn; /* authorization DN */ - char *o_authz_ndn; /* authorizaiton NDN */ - -#else char *o_dn; /* dn bound when op was initiated */ char *o_ndn; /* normalized dn bound when op was initiated */ -#endif ber_int_t o_protocol; /* version of the LDAP protocol used by client */ ber_tag_t o_authtype; /* auth method used to bind dn */ @@ -1071,9 +1039,6 @@ typedef struct slap_conn { /* only can be changed by binding thread */ int c_sasl_bind_in_progress; /* multi-op bind in progress */ char *c_sasl_bind_mech; /* mech in progress */ -#ifdef HAVE_CYRUS_SASL - sasl_conn_t *c_sasl_bind_context; /* Cyrus SASL state data */ -#endif /* authentication backend */ Backend *c_authc_backend; @@ -1081,19 +1046,8 @@ typedef struct slap_conn { /* authorization backend - normally same as c_authc_backend */ Backend *c_authz_backend; -#ifdef SLAP_AUTHZID - /* authentication backend */ - /* should only be used for reporting purposes */ - char *c_authc_dn; /* authentication DN */ - - /* should be used as the DN of the User */ - char *c_authz_dn; /* authorization DN */ - char *c_authz_ndn; /* authorization NDN */ - -#else char *c_cdn; /* DN provided by the client */ char *c_dn; /* DN bound to this conn */ -#endif ber_int_t c_protocol; /* version of the LDAP protocol used by client */ ber_tag_t c_authtype;/* auth method used to bind c_dn */ @@ -1112,6 +1066,7 @@ typedef struct slap_conn { int c_is_tls; /* true if this LDAP over raw TLS */ int c_needs_tls_accept; /* true if SSL_accept should be called */ #endif + void *c_sasl_context; /* SASL session context */ long c_n_ops_received; /* num of ops received (next op_id) */ long c_n_ops_executing; /* num of ops currently executing */ diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index a2d8f742a5..6747c05716 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -136,24 +136,19 @@ struct berval **get_entry_referrals( return NULL; } -int sasl_init(void) { - return 0; +int slap_sasl_init(void) +{ + return; } -int sasl_destroy(void) { - return 0; +int slap_sasl_destroy(void) +{ + return; } -#ifdef HAVE_CYRUS_SASL -int sasl_bind( - Connection *conn, - Operation *op, - const char *dn, - const char *ndn, - const char *mech, - struct berval *cred, - char **edn) +char * slap_sasl_secprops( const char *in ) { - return -1; + assert(0); + return NULL; } -#endif + diff --git a/tests/data/slapd-dnssrv.conf b/tests/data/slapd-dnssrv.conf index b95d3932c3..d0be943237 100644 --- a/tests/data/slapd-dnssrv.conf +++ b/tests/data/slapd-dnssrv.conf @@ -9,6 +9,10 @@ schemacheck on pidfile ./test-db/slapd.pid argsfile ./test-db/slapd.args +sasl-secprops noanonymous +sasl-realm "" +#sasl-secprops none + ####################################################################### # ldbm database definitions ####################################################################### -- 2.39.5