From c02d7e2cb6afb75c6896869d89f7f2f0e378cd31 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Thu, 20 Apr 2000 09:23:51 +0000 Subject: [PATCH] ITS#503: Extend ldap tools to support SASL/TLS Submitted by Gabor Gombas --- clients/tools/ldapdelete.c | 206 +++++++++++++++++++++++++++++----- clients/tools/ldapmodify.c | 200 +++++++++++++++++++++++++++------ clients/tools/ldapmodrdn.c | 208 +++++++++++++++++++++++++++++----- clients/tools/ldappasswd.c | 164 +++++++++++++++++++++++---- clients/tools/ldapsearch.c | 209 +++++++++++++++++++++++++++++------ doc/man/man1/ldapdelete.1 | 54 +++++++++ doc/man/man1/ldapmodify.1 | 74 +++++++++++++ doc/man/man1/ldapmodrdn.1 | 54 +++++++++ doc/man/man1/ldappasswd.1 | 56 +++++++++- doc/man/man1/ldapsearch.1 | 54 +++++++++ include/ldap.h | 5 + include/ldap_pvt.h | 8 +- libraries/libldap/init.c | 10 ++ libraries/libldap/ldap-int.h | 4 + libraries/libldap/options.c | 8 ++ libraries/libldap/sasl.c | 52 +++++++++ 16 files changed, 1224 insertions(+), 142 deletions(-) diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c index c2fa16cbc2..bd2a61f1bf 100644 --- a/clients/tools/ldapdelete.c +++ b/clients/tools/ldapdelete.c @@ -23,7 +23,15 @@ static char *binddn = NULL; static char *passwd = NULL; static char *ldaphost = NULL; static int ldapport = 0; -static int prune = 0; +static int prune = 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; +#endif +static int use_tls = 0; static int not, verbose, contoper; static LDAP *ld; @@ -34,12 +42,48 @@ static int dodelete LDAP_P(( static int deletechildren LDAP_P(( LDAP *ld, char *dn )); +static void +usage( const char *s ) +{ + fprintf( stderr, +"Delete entries from an LDAP server\n\n" +"usage: %s [options] [dn]...\n" +" dn: list of DNs to delete. If not given, it will be readed from stdin\n" +" or from the file specified with \"-f file\".\n" +"options:\n" +" -c\t\tcontinuous operation mode (do not stop on errors)\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" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" +" -r\t\tdelete recursively\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -w passwd\tbind passwd (for simple authentication)\n" +" -W\t\tprompt for bind passwd\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" +, s ); + + exit( EXIT_FAILURE ); +} + + int main( int argc, char **argv ) { - char *usage = "usage: %s [-n] [-v] [-k] [-W] [-M[M]] [-r] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n"; - char buf[ 4096 ]; - FILE *fp; + char buf[ 4096 ]; + FILE *fp; int i, rc, authmethod, want_bindpw, version, debug, manageDSAit; not = verbose = contoper = want_bindpw = debug = manageDSAit = 0; @@ -47,14 +91,13 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "WMnvkKcrh:P:p:D:w:d:f:" )) != EOF ) { + while (( i = getopt( argc, argv, "cD:d:Ef:h:IKkMnP:p:rU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - fprintf( stderr, usage, argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -62,8 +105,7 @@ main( int argc, char **argv ) #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - fprintf( stderr, usage, argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -125,30 +167,96 @@ main( int argc, char **argv ) break; default: fprintf( stderr, "protocol version should be 2 or 3\n" ); - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); + } + break; + case 'I': +#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++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = 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 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = 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 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = 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 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif break; default: - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); } } - if( authmethod != LDAP_AUTH_SIMPLE ) { - if( version == LDAP_VERSION3 ) { - fprintf(stderr, "Kerberos requires LDAPv2\n"); - return EXIT_FAILURE; + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version != LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); } - version = LDAP_VERSION2; } if( manageDSAit ) { - if( version == LDAP_VERSION2 ) { + if( version != LDAP_VERSION3 ) { fprintf(stderr, "manage DSA control requires LDAPv3\n"); return EXIT_FAILURE; } - version = LDAP_VERSION3; } if ( fp == NULL ) { @@ -190,13 +298,61 @@ main( int argc, char **argv ) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + if (want_bindpw) passwd = getpass("Enter LDAP Password: "); - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); - } + 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 ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } if ( manageDSAit ) { int err; @@ -308,7 +464,7 @@ static int deletechildren( LDAP *ld, { printf( "\tremoving %s\n", ldap_get_dn( ld, e ) ); } - if ( rc = ldap_delete_s( ld, ldap_get_dn( ld, e ) ) == -1 ) + if ( ( rc = ldap_delete_s( ld, ldap_get_dn( ld, e ) ) ) == -1 ) { ldap_perror( ld, "ldap_delete" ); return rc; diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c index d9985939fb..eed0b3f181 100644 --- a/clients/tools/ldapmodify.c +++ b/clients/tools/ldapmodify.c @@ -16,7 +16,9 @@ #include #include +#ifdef HAVE_SYS_STAT_H #include +#endif #ifdef HAVE_SYS_FILE_H #include @@ -36,6 +38,14 @@ static char *binddn = NULL; static char *passwd = 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; +#endif +static int use_tls = 0; static int new, replace, not, verbose, contoper, force, valsfromfiles; static LDAP *ld; @@ -76,23 +86,34 @@ static void usage( const char *prog ) { fprintf( stderr, - "Add or modify entries from an LDAP server\n\n" - "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n" - " [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n" - " a - add values (default%s)\n" - " b - read values from files (for binary attributes)\n" - " c - continuous operation\n" - " D - bind DN\n" - " M - enable Manage DSA IT control (-MM for critical)\n" - " d - debug level\n" - " f - read from file\n" - " F - force all changes records to be used\n" - " h - ldap host\n" - " n - print adds, don't actually do them\n" - " p - LDAP port\n" - " r - replace values\n" - " v - verbose mode\n" - " w - password\n" +"Add or modify entries from an LDAP server\n\n" +"usage: %s [options]\n" +" The list of desired operations are read from stdin or from the file\n" +" specified by \"-f file\".\n" +"options:\n" +" -a\t\tadd values (default%s)\n" +" -b\t\tread values from files (for binary attributes)\n" +" -c\t\tcontinuous operation\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 adds, don't actually do them\n" +" -p port\t\tport on LDAP server\n" +" -r\t\treplace values\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\tverbose mode\n" +" -w passwd\tbind password (for Simple authentication)\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") ); exit( EXIT_FAILURE ); } @@ -123,7 +144,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; version = -1; - while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) { + while (( i = getopt( argc, argv, "abcD:d:EFf:h:IKkMnP:p:rtU:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'a': /* add */ new = 1; @@ -141,8 +162,7 @@ main( int argc, char **argv ) #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -150,8 +170,7 @@ main( int argc, char **argv ) #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); - usage( argv[0] ); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif break; @@ -210,6 +229,67 @@ main( int argc, char **argv ) usage( argv[0] ); } break; + case 'I': +#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++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = 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 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = 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 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = 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 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage( prog ); } @@ -218,20 +298,25 @@ main( int argc, char **argv ) if ( argc != optind ) usage( prog ); - if( authmethod != LDAP_AUTH_SIMPLE ) { - if( version == LDAP_VERSION3 ) { - fprintf(stderr, "Kerberos requires LDAPv2\n"); - return EXIT_FAILURE; + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version != LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); } - version = LDAP_VERSION2; } if( manageDSAit ) { - if( version == LDAP_VERSION2 ) { + if( version != LDAP_VERSION3 ) { fprintf(stderr, "manage DSA control requires LDAPv3\n"); return EXIT_FAILURE; } - version = LDAP_VERSION3; } if ( infile != NULL ) { @@ -277,13 +362,62 @@ main( int argc, char **argv ) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION to %d\n", version ); } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + if (want_bindpw) passwd = getpass("Enter LDAP Password: "); - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); + 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 ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif } + else { + if ( ldap_bind_s( ld, binddn, passwd, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } + } rc = 0; @@ -377,7 +511,7 @@ process_ldif_rec( char *rbuf, int count ) new_entry = new; - rc = got_all = saw_replica = delete_entry = expect_modop = 0; + rc = got_all = saw_replica = delete_entry = modop = expect_modop = 0; expect_deleteoldrdn = expect_newrdn = expect_newsup = 0; expect_sep = expect_ct = 0; linenum = 0; diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c index 31782bd88b..dbfe1629f8 100644 --- a/clients/tools/ldapmodrdn.c +++ b/clients/tools/ldapmodrdn.c @@ -35,6 +35,14 @@ static char *binddn = NULL; static char *passwd = 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; +#endif +static int use_tls = 0; static int not, verbose, contoper; static LDAP *ld; @@ -45,11 +53,48 @@ static int domodrdn( char *newSuperior, int remove ); /* flag: remove old RDN */ +static void +usage( const char *s ) +{ + fprintf( stderr, +"Rename LDAP entries\n\n" +"usage: %s [options] [dn rdn]\n" +" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n" +" If not given, the list of modifications is read from stdin or\n" +" from the file specified by \"-f file\" (see man page).\n" +"options:\n" +" -c\t\tcontinuous operation mode (do not stop on errors)\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" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" +" -r\t\tremove old RDN\n" +" -s newsuperior\tnew superior entry\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -w passwd\tbind passwd (for simple authentication)\n" +" -W\t\tprompt for bind passwd\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" +, s ); + + exit( EXIT_FAILURE ); +} + int main(int argc, char **argv) { - char *usage = "usage: %s [-nvkWc] [-M[M]] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n"; - char *myname,*infile, *entrydn, *rdn, buf[ 4096 ]; + char *myname,*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ]; FILE *fp; int rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit; char *newSuperior=NULL; @@ -61,24 +106,24 @@ main(int argc, char **argv) myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname; - while (( i = getopt( argc, argv, "WkKMcnvrh:P:p:D:w:d:f:s:" )) != EOF ) { + while (( i = getopt( argc, argv, "cD:d:Ef:h:IKkMnP:p:rs:U:vWw:X:Y:Z" )) != EOF ) { switch( i ) { case 'k': /* kerberos bind */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif - break; + break; case 'K': /* kerberos bind, part one only */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); return( EXIT_FAILURE ); #endif - break; + break; case 'c': /* continuous operation mode */ ++contoper; break; @@ -138,30 +183,96 @@ main(int argc, char **argv) break; default: fprintf( stderr, "protocol version should be 2 or 3\n" ); - fprintf( stderr, usage, argv[0] ); - return( EXIT_FAILURE ); + usage( argv[0] ); + return( EXIT_FAILURE ); + } + break; + case 'I': +#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++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = 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 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = 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 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = 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 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif break; default: - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } } - if( authmethod != LDAP_AUTH_SIMPLE ) { - if( version == LDAP_VERSION3 ) { - fprintf(stderr, "Kerberos requires LDAPv2\n"); - return EXIT_FAILURE; + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version != LDAP_VERSION2 ) { + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); } - version = LDAP_VERSION2; } if( manageDSAit ) { - if( version == LDAP_VERSION2 ) { + if( version != LDAP_VERSION3 ) { fprintf(stderr, "manage DSA control requires LDAPv3\n"); return EXIT_FAILURE; } - version = LDAP_VERSION3; } if (newSuperior != NULL) { @@ -169,12 +280,9 @@ main(int argc, char **argv) fprintf( stderr, "%s: version conflict!, -s newSuperior requires LDAPv3\n", myname); - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } - - /* promote to LDAPv3 */ - version = LDAP_VERSION3; } havedn = 0; @@ -190,7 +298,7 @@ main(int argc, char **argv) ++havedn; } else if ( argc - optind != 0 ) { fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname); - fprintf( stderr, usage, argv[0] ); + usage( argv[0] ); return( EXIT_FAILURE ); } @@ -236,13 +344,61 @@ main(int argc, char **argv) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + if (want_bindpw) passwd = getpass("Enter LDAP Password: "); - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - return( EXIT_FAILURE ); - } + 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 ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } + } if ( manageDSAit ) { int err; diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index 04b4d469c9..70de7e6689 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -27,19 +27,29 @@ static void usage(const char *s) { fprintf(stderr, - "Usage: %s [options] dn\n" - " -A\t\tprompt for old password\n" - " -a secret\told password\n" - " -D binddn\tbind dn\n" - " -d level\tdebugging level\n" - " -h host\tldap server (default: localhost)\n" - " -n\t\tmake no modifications\n" - " -p port\tldap port\n" - " -S\t\tprompt for new password\n" - " -s secret\tnew password\n" - " -v\t\tincrease verbosity\n" - " -W\t\tprompt for bind password\n" - " -w passwd\tbind password (for simple authentication)\n" +"Change the password of an LDAP entry\n\n" +"usage: %s [options] dn\n" +" dn: the DN of the entry whose password must be changed\n" +"options:\n" +" -a secret\told password\n" +" -A\t\tprompt for old password\n" +" -d level\tdebugging level\n" +" -D binddn\tbind DN\n" +" -E\t\trequest SASL privacy (-EE to make it critical)\n" +" -h host\t\tLDAP server (default: localhost)\n" +" -I\t\trequest SASL integrity checking (-II to make it\n" +" \tcritical)\n" +" -n\t\tmake no modifications\n" +" -p port\t\tport on LDAP server\n" +" -S\t\tprompt for new password\n" +" -s secret\tnew password\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\tverbose mode\n" +" -w passwd\tbind password (for simple authentication)\n" +" -W\t\tprompt for bind password\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , s ); exit( EXIT_FAILURE ); @@ -67,6 +77,15 @@ main( int argc, char *argv[] ) int ldapport = 0; int debug = 0; int version = -1; + int authmethod = LDAP_AUTH_SIMPLE; +#ifdef HAVE_CYRUS_SASL + char *sasl_authc_id = NULL; + char *sasl_authz_id = NULL; + char *sasl_mech = NULL; + int sasl_integrity = 0; + int sasl_privacy = 0; +#endif + int use_tls = 0; LDAP *ld; struct berval *bv = NULL; @@ -77,7 +96,7 @@ main( int argc, char *argv[] ) usage (argv[0]); while( (i = getopt( argc, argv, - "Aa:D:d:h:np:Ss:vWw:" )) != EOF ) + "Aa:D:d:EIh:np:Ss:U:vWw:X:Y:Z" )) != EOF ) { switch (i) { case 'A': /* prompt for oldr password */ @@ -150,6 +169,68 @@ main( int argc, char *argv[] ) } break; + case 'I': +#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++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && + strcmp( optarg, "*" ) ) { + sasl_mech = 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 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = 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 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = 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 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS " + "support\n", argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage (argv[0]); @@ -228,12 +309,57 @@ main( int argc, char *argv[] ) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } - rc = ldap_bind_s( ld, binddn, bindpw, LDAP_AUTH_SIMPLE ); + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } - if ( rc != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); - ldap_unbind( ld ); - return EXIT_FAILURE; + 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 ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, bindpw, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } } if( dn != NULL || oldpw != NULL || newpw != NULL ) { diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c index d28c9a3b2d..ab700a729b 100644 --- a/clients/tools/ldapsearch.c +++ b/clients/tools/ldapsearch.c @@ -3,6 +3,7 @@ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ + #include "portable.h" #include @@ -37,38 +38,48 @@ usage( const char *s ) "\t\t+ -- all operational attributes\n" "\t\tempty list -- all non-operational attributes\n" "options:\n" -" -n\t\tshow what would be done but don't actually search\n" -" -v\t\trun in verbose mode (diagnostics to standard output)\n" -" -t\t\twrite binary values to files in TMPDIR\n" -" -tt\t\twrite all values to files in TMPDIR\n" -" -T path\twrite files to directory specified by path (default: \"/tmp\")\n" -" -V prefix\tURL prefix for files (default: \"file://tmp/\"\n" -" -u\t\tinclude User Friendly entry names in the output\n" +" -a deref\tone of `never', `always', `search', or `find' (alias\n" +" \tdereferencing)\n" " -A\t\tretrieve attribute names only (no values)\n" +" -b basedn\tbase dn for search\n" " -B\t\tdo not suppress printing of binary values\n" -" -F sep\tprint `sep' instead of `=' between attribute names and values\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\tperform sequence of searches listed in `file'\n" +" -F sep\t\tprint `sep' instead of `=' between attribute names and\n" +" \tvalues\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" +" -l limit\ttime limit (in seconds) for search\n" " -L\t\tprint entries in LDIF format (implies -B)\n" " -LL\t\tprint entries in LDIF format without comments\n" -" -LLL\t\tprint entries in LDIF format without comments and version\n" +" -LLL\t\tprint entries in LDIF format without comments and\n" +" \tversion\n" " -M\t\tenable Manage DSA IT control (-MM to make critical)\n" +" -n\t\tshow what would be done but don't actually search\n" +" -p port\t\tport on LDAP server\n" +" -P version\tprocotol version (2 or 3)\n" " -R\t\tdo not automatically follow referrals\n" -" -S attr\tsort the results by attribute `attr'\n" -" -d level\tset LDAP debugging level to `level'\n" -" -f file\tperform sequence of searches listed in `file'\n" -" -b basedn\tbase dn for search\n" " -s scope\tone of base, one, or sub (search scope)\n" -" -a deref\tone of never, always, search, or find (alias dereferencing)\n" -" -l limit\ttime limit (in seconds) for search\n" -" -z limit\tsize limit (in entries) for search\n" -" -D binddn\tbind dn\n" +" -S attr\t\tsort the results by attribute `attr'\n" +" -t\t\twrite binary values to files in TMPDIR\n" +" -tt\t\twrite all values to files in TMPDIR\n" +" -T path\t\twrite files to directory specified by path (default:\n" +" \t\"/tmp\")\n" +" -u\t\tinclude User Friendly entry names in the output\n" +" -U user\t\tSASL authentication identity (username)\n" +" -v\t\trun in verbose mode (diagnostics to standard output)\n" +" -V prefix\tURL prefix for files (default: \"file://tmp/\")\n" " -w passwd\tbind passwd (for simple authentication)\n" " -W\t\tprompt for bind passwd\n" -#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND -" -k\t\tuse Kerberos instead of Simple Password authentication\n" -#endif -" -h host\tldap server\n" -" -p port\tport on ldap server\n" -" -P version\tprocotol version (2 or 3)\n" +" -X id\t\tSASL authorization identity (\"dn:\" or \"u:\")\n" +" -Y mech\t\tSASL mechanism\n" +" -z limit\tsize limit (in entries) for search\n" +" -Z\t\trequest the use of TLS (-ZZ to make it critical)\n" , s ); exit( EXIT_FAILURE ); @@ -105,6 +116,14 @@ static char *passwd = NULL; static char *base = 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; +#endif +static int use_tls = 0; static char *sep = DEFSEP; static char *sortattr = NULL; static int skipsortattr = 0; @@ -114,7 +133,7 @@ int main( int argc, char **argv ) { char *infile, *filtpattern, **attrs, line[ BUFSIZ ]; - FILE *fp; + FILE *fp = NULL; int rc, i, first, scope, deref, attrsonly, manageDSAit; int referrals, timelimit, sizelimit, debug; int authmethod, version, want_bindpw; @@ -130,7 +149,7 @@ main( int argc, char **argv ) authmethod = LDAP_AUTH_SIMPLE; while (( i = getopt( argc, argv, - "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:T:V:")) != EOF ) + "Aa:Bb:D:d:EF:f:h:IKkLl:MnP:p:RS:s:T:tU:uV:vWw:X:Y:Zz:")) != EOF ) { switch( i ) { case 'n': /* do Not do any searches */ @@ -146,16 +165,19 @@ main( int argc, char **argv ) #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV4; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); + return( EXIT_FAILURE ); #endif break; case 'K': /* use kerberos bind, 1st part only */ #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND authmethod = LDAP_AUTH_KRBV41; #else - fprintf (stderr, "%s was not compiled with Kerberos support\n", argv[0]); + fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] ); + return( EXIT_FAILURE ); #endif break; + break; case 'u': /* include UFN */ ++includeufn; break; @@ -268,6 +290,67 @@ main( int argc, char **argv ) usage( argv[0] ); } break; + case 'I': +#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++; + authmethod = LDAP_AUTH_SASL; +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; + case 'Y': +#ifdef HAVE_CYRUS_SASL + if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) { + sasl_mech = 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 'U': +#ifdef HAVE_CYRUS_SASL + sasl_authc_id = 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 'X': +#ifdef HAVE_CYRUS_SASL + sasl_authz_id = 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 'Z': +#ifdef HAVE_TLS + use_tls++; +#else + fprintf( stderr, "%s was not compiled with TLS support\n", + argv[0] ); + return( EXIT_FAILURE ); +#endif + break; default: usage( argv[0] ); } @@ -278,20 +361,26 @@ main( int argc, char **argv ) if( ldif < 1 ) ldif = 1; #endif - if( authmethod != LDAP_AUTH_SIMPLE ) { - if( version == LDAP_VERSION3 ) { - fprintf(stderr, "Kerberos requires LDAPv2\n"); - return EXIT_FAILURE; + if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod == + LDAP_AUTH_KRBV41 ) ) { + if( version != LDAP_VERSION2 ) { + + fprintf( stderr, "Kerberos requires LDAPv2\n" ); + return( EXIT_FAILURE ); + } + } + else if ( authmethod == LDAP_AUTH_SASL ) { + if( version != LDAP_VERSION3 ) { + fprintf( stderr, "SASL requires LDAPv3\n" ); + return( EXIT_FAILURE ); } - version = LDAP_VERSION2; } if( manageDSAit ) { - if( version == LDAP_VERSION2 ) { + if( version != LDAP_VERSION3 ) { fprintf(stderr, "manage DSA control requires LDAPv3\n"); return EXIT_FAILURE; } - version = LDAP_VERSION3; } if ( argc - optind < 1 ) { @@ -405,13 +494,61 @@ main( int argc, char **argv ) fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version ); } + if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) { + if ( use_tls > 1 ) { + ldap_perror( ld, "ldap_start_tls" ); + return( EXIT_FAILURE ); + } + } + if (want_bindpw) { passwd = getpass("Enter LDAP Password: "); } - if ( ldap_bind_s( ld, binddn, passwd, authmethod ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_bind" ); + 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 ); + } + + if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id, + sasl_authz_id, sasl_mech, NULL, NULL, NULL ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind" ); + return( EXIT_FAILURE ); + } +#else + fprintf( stderr, "%s was not compiled with SASL support\n", + argv[0] ); return( EXIT_FAILURE ); +#endif + } + else { + if ( ldap_bind_s( ld, binddn, passwd, authmethod ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_bind" ); + return( EXIT_FAILURE ); + } } if ( manageDSAit ) { diff --git a/doc/man/man1/ldapdelete.1 b/doc/man/man1/ldapdelete.1 index 2a6fa2f9e3..60840f5755 100644 --- a/doc/man/man1/ldapdelete.1 +++ b/doc/man/man1/ldapdelete.1 @@ -35,6 +35,18 @@ ldapdelete \- LDAP delete entry tool [\c .BI \-p \ ldapport\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .IR dn ]... .SH DESCRIPTION .I ldapdelete @@ -117,6 +129,48 @@ Do a recursive delete. If the DN specified isn't a leaf, its children, and all their children are deleted down the tree. No verification is done, so if you add this switch, ldapdelete will happily delete large portions of your tree. Use with care. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH EXAMPLE The following command: .LP diff --git a/doc/man/man1/ldapmodify.1 b/doc/man/man1/ldapmodify.1 index 74fe4acbd2..0da3282795 100644 --- a/doc/man/man1/ldapmodify.1 +++ b/doc/man/man1/ldapmodify.1 @@ -21,6 +21,8 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BR \-k ] [\c +.BR \-K ] +[\c .BR \-M[M] ] [\c .BI \-d \ debuglevel\fR] @@ -37,6 +39,18 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BI \-P \ 2\fR\||\|\fI3\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] .LP .B ldapadd @@ -55,16 +69,34 @@ ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools [\c .BR \-K ] [\c +.BR \-M[M] ] +[\c .BI \-d \ debuglevel\fR] [\c .BI \-D \ binddn\fR] [\c +.BR \-W ] +[\c .BI \-w \ passwd\fR] [\c .BI \-h \ ldaphost\fR] [\c .BI \-p \ ldapport\fR] [\c +.BI \-P \ 2\fR\||\|\fI3\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] .SH DESCRIPTION .B ldapmodify @@ -162,6 +194,48 @@ Specify an alternate TCP port where the ldap server is listening. .TP .BI \-P \ 2\fR\||\|\fI3 Specify the LDAP protocol version to use. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH INPUT FORMAT The contents of \fIfile\fP (or standard input if no \-f flag is given on the command line) should conform to the format defined in diff --git a/doc/man/man1/ldapmodrdn.1 b/doc/man/man1/ldapmodrdn.1 index 3d13f0aef9..31b7842dbf 100644 --- a/doc/man/man1/ldapmodrdn.1 +++ b/doc/man/man1/ldapmodrdn.1 @@ -35,6 +35,18 @@ ldapmodrdn \- LDAP rename entry tool [\c .BI \-P \ 2\fR\||\|\fI3\fR] [\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] +[\c .BI \-f \ file\fR] [\c .I dn rdn\fR] @@ -113,6 +125,48 @@ Specify an alternate TCP port where the ldap server is listening. .TP .BI \-P \ 2\fR\||\|\fI3 Specify the LDAP protocol version to use. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH INPUT FORMAT If the command-line arguments \fIdn\fP and \fIrdn\fP are given, \fIrdn\fP will replace the RDN of the entry specified by the DN, \fIdn\fP. diff --git a/doc/man/man1/ldappasswd.1 b/doc/man/man1/ldappasswd.1 index 1e7e585968..63f7892e7b 100644 --- a/doc/man/man1/ldappasswd.1 +++ b/doc/man/man1/ldappasswd.1 @@ -29,6 +29,18 @@ ldappasswd \- change the password of an LDAP entry .BR \-W ] [\c .BI \-w \ passwd\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] .SH DESCRIPTION .B ldappasswd is a tool to set the password of an LDAP user. @@ -88,10 +100,50 @@ This is used instead of specifying the password on the command line. .TP .BI \-w \ passwd Use \fIpasswd\fP as the password to bind with. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH SEE ALSO .BR ldap_bind (3) -.SH BUGS -No transport security layer is provided. .SH ACKNOWLEDGEMENTS .B OpenLDAP is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). diff --git a/doc/man/man1/ldapsearch.1 b/doc/man/man1/ldapsearch.1 index f9427001e0..a4974c95ba 100644 --- a/doc/man/man1/ldapsearch.1 +++ b/doc/man/man1/ldapsearch.1 @@ -56,6 +56,18 @@ ldapsearch \- LDAP search tool .BI \-l \ timelimit\fR] [\c .BI \-z \ sizelimit\fR] +[\c +.BR \-E[E] ] +[\c +.BR \-I[I] ] +[\c +.BI \-U \ username\fR] +[\c +.BI \-X \ authzid\fR] +[\c +.BI \-Y \ mech\fR] +[\c +.BR \-Z[Z] ] .I filter [\c .IR attrs... ] @@ -225,6 +237,48 @@ of limit. A server may impose a maximal sizelimit which only the root user may override. +.TP +.B \-E[E] +Requset the use of SASL privacy (encryption). If the server allows it, data +sent between the client and the server will be encrypted. If the server +requires the use of encryption and this flag is not specified, the command +will fail. If you use +.B \-EE\c +, the command will fail if the server does not support encryption. +.B \-E[E] +implies +.B \-I[I] +.TP +.B \-I[I] +Request the use of SASL integrity checking. It protects data sent between the +client and the server from being modified along the way, but it does not +prevent sniffing. If the server requires the use of integrity checking and +this flag is not specified, the command will fail.If you use +.B \-II\c +, the command will fail if the server does not support this function. +.TP +.BI \-U \ username +Specify the username for SASL bind. The syntax of the username depends on the +actual SASL mechanism used. +.TP +.BI \-X \ authzid +Specify the requested authorization ID for SASL bind. +.I authzid +must be one of the following formats: +.B dn:\c +.I +or +.B u:\c +.I +.TP +.BI \-Y \ mech +Specify the SASL mechanism to be used for authentication. If it's not +specified, the program will choose the best mechanism the server knows. +.TP +.B \-Z[Z] +Request the use of TLS (Transport Layer Security). If you use +.B \-ZZ\c +, the command will fail if TLS negotiation does not succeed for some reason. .SH OUTPUT FORMAT If one or more entries are found, each entry is written to standard output in the form: diff --git a/include/ldap.h b/include/ldap.h index 2de0acf8fc..f81cf4e5a9 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -129,6 +129,11 @@ LDAP_BEGIN_DECL #define LDAP_OPT_X_TLS_ALLOW 3 #define LDAP_OPT_X_TLS_TRY 4 +/* SASL options */ +#define LDAP_OPT_X_SASL_MINSSF 0x6100 +#define LDAP_OPT_X_SASL_MAXSSF 0x6101 +#define LDAP_OPT_X_SASL_ACTSSF 0x6102 + /* on/off values */ #define LDAP_OPT_ON ((void *) 1) #define LDAP_OPT_OFF ((void *) 0) diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 660fa1d612..14b6a97bbe 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -114,7 +114,13 @@ LIBLDAP_F (int) ldap_pvt_unhex( int c ); LIBLDAP_F (int) ldap_pvt_sasl_init LDAP_P(( void )); /* clientside init */ LIBLDAP_F (int) ldap_pvt_sasl_install LDAP_P(( Sockbuf *, void * )); LIBLDAP_F (int) ldap_pvt_sasl_err2ldap LDAP_P(( int )); -LIBLDAP_F (int) ldap_pvt_sasl_bind LDAP_P(( LDAP *, LDAP_CONST char *, LDAP_CONST char *, LDAP_CONST sasl_callback_t *, LDAPControl **, LDAPControl ** )); +LIBLDAP_F (int) ldap_pvt_sasl_bind LDAP_P(( LDAP *, LDAP_CONST char *, + LDAP_CONST char *, LDAP_CONST sasl_callback_t *, LDAPControl **, + LDAPControl ** )); +LIBLDAP_F (int) ldap_pvt_sasl_get_option LDAP_P(( LDAP *ld, int option, + void *arg )); +LIBLDAP_F (int) ldap_pvt_sasl_set_option LDAP_P(( LDAP *ld, int option, + void *arg )); #endif /* HAVE_CYRUS_SASL */ /* search.c */ diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index 57faabda7b..816cc28881 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -75,6 +75,12 @@ static const struct ol_attribute { {0, ATTR_TLS, "TLS_CACERT", NULL, LDAP_OPT_X_TLS_CACERTFILE}, {0, ATTR_TLS, "TLS_CACERTDIR",NULL, LDAP_OPT_X_TLS_CACERTDIR}, {0, ATTR_TLS, "TLS_REQCERT", NULL, LDAP_OPT_X_TLS_REQUIRE_CERT}, +#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} }; @@ -375,6 +381,10 @@ void ldap_int_initialize( void ) #ifdef HAVE_TLS gopts.ldo_tls_ctx = NULL; #endif +#ifdef HAVE_CYRUS_SASL + gopts.ldo_sasl_minssf = 0; + gopts.ldo_sasl_maxssf = INT_MAX; +#endif gopts.ldo_valid = LDAP_INITIALIZED; diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 0cc4ac0b07..a19ea260e8 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -124,6 +124,10 @@ struct ldapoptions { /* tls context */ void *ldo_tls_ctx; int ldo_tls_mode; +#endif +#ifdef HAVE_CYRUS_SASL + sasl_ssf_t ldo_sasl_minssf; + sasl_ssf_t ldo_sasl_maxssf; #endif LDAP_BOOLEANS ldo_booleans; /* boolean options */ }; diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c index 93f95640da..fcf7cc7ca5 100644 --- a/libraries/libldap/options.c +++ b/libraries/libldap/options.c @@ -289,6 +289,10 @@ ldap_get_option( #ifdef HAVE_TLS if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 ) return LDAP_OPT_SUCCESS; +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 ) + return LDAP_OPT_SUCCESS; #endif /* bad param */ break; @@ -565,6 +569,10 @@ ldap_set_option( #ifdef HAVE_TLS if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 ) return LDAP_OPT_SUCCESS; +#endif +#ifdef HAVE_CYRUS_SASL + if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 ) + return LDAP_OPT_SUCCESS; #endif /* bad param */ break; diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index f62fa99737..31c9e063cb 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -782,6 +782,58 @@ ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len) 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, &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. -- 2.39.5