diff options
author | Rich Megginson <rmeggins@redhat.com> | 2009-07-06 12:11:01 -0600 |
---|---|---|
committer | Rich Megginson <rmeggins@redhat.com> | 2009-07-07 08:32:42 -0600 |
commit | 209521323f731daad54682fd98715f7b22c88c78 (patch) | |
tree | 74a1fa8df06641fe543c8518e4db4357ab610828 /ldap/servers | |
parent | 3116dbec570b65d2d0a1df5bd000f6e63439e8ee (diff) | |
download | ds-209521323f731daad54682fd98715f7b22c88c78.tar.gz ds-209521323f731daad54682fd98715f7b22c88c78.tar.xz ds-209521323f731daad54682fd98715f7b22c88c78.zip |
OpenLDAP supportcleanup
These changes allow the server to be built with OpenLDAP (2.4.17+). A brief summary of the changes:
* #defines not provided by OpenLDAP were copied into slapi-plugin.h and protected with #ifndef blocks
* where it made sense, I created slapi wrapper functions for things like URL and LDIF processing to abstract way the differences in the APIs
* I created a new file utf8.c which contains the UTF8 functions from MozLDAP - this is only compiled when using OpenLDAP
* I tried to clean up the code - use the _ext versions of LDAP functions everywhere since the older versions should be considered deprecated
* I removed some unused code
NOTE that this should still be considered a work in progress since it depends on functionality not yet present in a released version of OpenLDAP, for NSS crypto and for the LDIF public API.
Diffstat (limited to 'ldap/servers')
81 files changed, 3022 insertions, 1783 deletions
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c index f7f58650..b708cada 100644 --- a/ldap/servers/plugins/acl/acl.c +++ b/ldap/servers/plugins/acl/acl.c @@ -195,9 +195,9 @@ static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, char *dn, } } } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); } - ldap_value_free( dns ); + slapi_ldap_value_free( dns ); } return(retCode); diff --git a/ldap/servers/plugins/acl/aclutil.c b/ldap/servers/plugins/acl/aclutil.c index f0c1da5d..599fdbd0 100644 --- a/ldap/servers/plugins/acl/aclutil.c +++ b/ldap/servers/plugins/acl/aclutil.c @@ -585,8 +585,8 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e ) cleanup: - ldap_value_free ( a_dns ); - ldap_value_free ( e_dns ); + slapi_ldap_value_free ( a_dns ); + slapi_ldap_value_free ( e_dns ); if ( 0 != rc ) /* error */ { slapi_ch_free ( (void **) &buf ); buf = NULL; diff --git a/ldap/servers/plugins/chainingdb/cb.h b/ldap/servers/plugins/chainingdb/cb.h index 209fdd37..a93950d9 100644 --- a/ldap/servers/plugins/chainingdb/cb.h +++ b/ldap/servers/plugins/chainingdb/cb.h @@ -485,7 +485,6 @@ int cb_back_cleanup (Slapi_PBlock *pb ); long cb_atol(char *str); Slapi_Entry * cb_LDAPMessage2Entry(LDAP * ctx, LDAPMessage * msg, int attrsonly); -char * cb_urlparse_err2string( int err ); char * cb_get_rootdn(); struct berval ** referrals2berval(char ** referrals); cb_backend_instance * cb_get_instance(Slapi_Backend * be); diff --git a/ldap/servers/plugins/chainingdb/cb_bind.c b/ldap/servers/plugins/chainingdb/cb_bind.c index d8c9f87b..638404a6 100644 --- a/ldap/servers/plugins/chainingdb/cb_bind.c +++ b/ldap/servers/plugins/chainingdb/cb_bind.c @@ -162,7 +162,7 @@ cb_sasl_bind_once_s( cb_conn_pool *pool, char *dn, int method, char * mechanism, char * matcheddnp2, * errmsgp2; matcheddnp2=errmsgp2=NULL; - rc = ldap_get_lderrno( ld, &matcheddnp2, &errmsgp2 ); + rc = slapi_ldap_get_lderrno( ld, &matcheddnp2, &errmsgp2 ); /* Need to allocate errmsgs */ if (matcheddnp2) @@ -185,7 +185,7 @@ cb_sasl_bind_once_s( cb_conn_pool *pool, char *dn, int method, char * mechanism, &referrals, resctrlsp, 1 ); if ( referrals != NULL ) { *refurlsp = referrals2berval( referrals ); - ldap_value_free( referrals ); + slapi_ldap_value_free( referrals ); } /* realloc matcheddn & errmsg because the mem alloc model */ /* may differ from malloc */ diff --git a/ldap/servers/plugins/chainingdb/cb_instance.c b/ldap/servers/plugins/chainingdb/cb_instance.c index f813cec0..1c08bd9f 100644 --- a/ldap/servers/plugins/chainingdb/cb_instance.c +++ b/ldap/servers/plugins/chainingdb/cb_instance.c @@ -714,15 +714,16 @@ static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int p char *url = (char *) value; LDAPURLDesc *ludp=NULL; int rc=LDAP_SUCCESS; + int secure = 0; - if (( rc = ldap_url_parse( url, &ludp )) != 0 ) { - PL_strncpyz(errorbuf,cb_urlparse_err2string( rc ), SLAPI_DSE_RETURNTEXT_SIZE); + if (( rc = slapi_ldap_url_parse( url, &ludp, 0, &secure )) != 0 ) { + PL_strncpyz(errorbuf,slapi_urlparse_err2string( rc ), SLAPI_DSE_RETURNTEXT_SIZE); if (CB_CONFIG_PHASE_INITIALIZATION == phase) inst->pool->url=slapi_ch_strdup(""); return(LDAP_INVALID_SYNTAX); } - if (ludp && (ludp->lud_options & LDAP_URL_OPT_SECURE) && inst && inst->rwl_config_lock) { + if (ludp && secure && inst && inst->rwl_config_lock) { int isgss = 0; PR_RWLock_Rlock(inst->rwl_config_lock); isgss = inst->pool->mech && !PL_strcasecmp(inst->pool->mech, "GSSAPI"); @@ -768,7 +769,7 @@ static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int p inst->pool->hostname = slapi_ch_strdup( ludp->lud_host ); } inst->pool->url = slapi_ch_strdup( url); - inst->pool->secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ); + inst->pool->secure = secure; if ((ludp->lud_port==0) && inst->pool->secure) inst->pool->port=CB_LDAP_SECURE_PORT; diff --git a/ldap/servers/plugins/chainingdb/cb_search.c b/ldap/servers/plugins/chainingdb/cb_search.c index 94b680f7..895d6f2b 100644 --- a/ldap/servers/plugins/chainingdb/cb_search.c +++ b/ldap/servers/plugins/chainingdb/cb_search.c @@ -298,7 +298,7 @@ chainingdb_build_candidate_list ( Slapi_PBlock *pb ) switch ( rc ) { case -1: /* An error occurred. return now */ - rc = ldap_get_lderrno(ld,NULL,NULL); + rc = slapi_ldap_get_lderrno(ld,NULL,NULL); /* tuck away some errors in a OPERATION_ERROR */ if (CB_LDAP_CONN_ERROR(rc)) { cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL, @@ -366,7 +366,7 @@ chainingdb_build_candidate_list ( Slapi_PBlock *pb ) rc=-1; } else if ( rc != LDAP_SUCCESS ) { - ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg ); + slapi_ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg ); cb_send_ldap_result( pb, rc, matched_msg, error_msg,0,NULL); /* BEWARE: matched_msg and error_msg points */ @@ -558,7 +558,7 @@ chainingdb_next_search_entry ( Slapi_PBlock *pb ) case -1: /* An error occurred. */ - rc = ldap_get_lderrno( ctx->ld, NULL, NULL ); + rc = slapi_ldap_get_lderrno( ctx->ld, NULL, NULL ); slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL); slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL); @@ -670,7 +670,7 @@ chainingdb_next_search_entry ( Slapi_PBlock *pb ) } if (referrals != NULL) { - ldap_value_free( referrals ); + slapi_ldap_value_free( referrals ); } return 0; @@ -694,7 +694,7 @@ chainingdb_next_search_entry ( Slapi_PBlock *pb ) retcode=-1; } else if ( rc != LDAP_SUCCESS ) { - ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg ); + slapi_ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg ); cb_send_ldap_result( pb, rc, matched_msg, NULL, 0, NULL); /* BEWARE: Don't free matched_msg && error_msg */ diff --git a/ldap/servers/plugins/chainingdb/cb_utils.c b/ldap/servers/plugins/chainingdb/cb_utils.c index 128c2adc..4878e1a8 100644 --- a/ldap/servers/plugins/chainingdb/cb_utils.c +++ b/ldap/servers/plugins/chainingdb/cb_utils.c @@ -94,7 +94,7 @@ Slapi_Entry * cb_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) } } if ( NULL != ber ) - ldap_ber_free( ber, 0 ); + ber_free( ber, 0 ); return e; } @@ -120,35 +120,6 @@ struct berval ** referrals2berval(char ** referrals) { return val; } - -char * -cb_urlparse_err2string( int err ) -{ - char *s="internal error"; - - switch( err ) { - case 0: - s = "no error"; - break; - case LDAP_URL_ERR_NOTLDAP: - s = "missing ldap:// or ldaps://"; - break; - case LDAP_URL_ERR_NODN: - s = "missing suffix"; - break; - case LDAP_URL_ERR_BADSCOPE: - s = "invalid search scope"; - break; - case LDAP_URL_ERR_MEM: - s = "unable to allocate memory"; - break; - case LDAP_URL_ERR_PARAM: - s = "bad parameter to an LDAP URL function"; - break; - } - - return( s ); -} /* ** Return LDAP_SUCCESS if an internal operation needs to be forwarded to diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c index 0f509c05..b198ef3a 100644 --- a/ldap/servers/plugins/dna/dna.c +++ b/ldap/servers/plugins/dna/dna.c @@ -53,7 +53,6 @@ #include "dirlite_strings.h" #include "dirver.h" #include "prclist.h" -#include "ldif.h" /* Required to get portable printf/scanf format macros */ #ifdef HAVE_INTTYPES_H @@ -1499,7 +1498,10 @@ static int dna_request_range(struct configEntry *config_entry, int set_extend_flag = 0; int ret = LDAP_OPERATIONS_ERROR; int port = 0; - + int timelimit; +#if defined(USE_OPENLDAP) + struct timeval timeout; +#endif /* See if we're allowed to send a range request now */ slapi_lock_mutex(config_entry->extend_lock); if (config_entry->extend_in_progress) { @@ -1543,9 +1545,15 @@ static int dna_request_range(struct configEntry *config_entry, /* Disable referrals and set timelimit and a connect timeout */ ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); - ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &config_entry->timeout); + timelimit = config_entry->timeout / 1000; /* timeout is in msec */ + ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit); +#if defined(USE_OPENLDAP) + timeout.tv_sec = config_entry->timeout / 1000; + timeout.tv_usec = (config_entry->timeout % 1000) * 1000; + ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); +#else ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &config_entry->timeout); - +#endif /* Bind to the replica server */ ret = slapi_ldap_bind(ld, bind_dn, bind_passwd, bind_method, NULL, NULL, NULL, NULL); diff --git a/ldap/servers/plugins/passthru/passthru.h b/ldap/servers/plugins/passthru/passthru.h index 022a57ae..34f8f696 100644 --- a/ldap/servers/plugins/passthru/passthru.h +++ b/ldap/servers/plugins/passthru/passthru.h @@ -163,6 +163,5 @@ void passthru_close_all_connections( PassThruConfig *cfg ); struct berval **passthru_strs2bervals( char **ss ); char ** passthru_bervals2strs( struct berval **bvs ); void passthru_free_bervals( struct berval **bvs ); -char *passthru_urlparse_err2string( int err ); #endif /* _PASSTHRU_H_ */ diff --git a/ldap/servers/plugins/passthru/ptbind.c b/ldap/servers/plugins/passthru/ptbind.c index 2cce0b57..063ba150 100644 --- a/ldap/servers/plugins/passthru/ptbind.c +++ b/ldap/servers/plugins/passthru/ptbind.c @@ -158,7 +158,7 @@ passthru_simple_bind_once_s( PassThruServer *srvr, char *dn, /* * Some other error occurred (no result received). */ - rc = ldap_get_lderrno( ld, matcheddnp, errmsgp ); + rc = slapi_ldap_get_lderrno( ld, matcheddnp, errmsgp ); } else { /* * Got a result from remote server -- parse it. @@ -167,7 +167,7 @@ passthru_simple_bind_once_s( PassThruServer *srvr, char *dn, &referrals, resctrlsp, 1 ); if ( referrals != NULL ) { *refurlsp = passthru_strs2bervals( referrals ); - ldap_value_free( referrals ); + slapi_ldap_value_free( referrals ); } } diff --git a/ldap/servers/plugins/passthru/ptconfig.c b/ldap/servers/plugins/passthru/ptconfig.c index b7bb1386..fac0c5bd 100644 --- a/ldap/servers/plugins/passthru/ptconfig.c +++ b/ldap/servers/plugins/passthru/ptconfig.c @@ -131,6 +131,7 @@ passthru_config( int argc, char **argv ) */ prevsrvr = NULL; for ( i = 0; i < argc; ++i ) { + int secure = 0; char *p = NULL; srvr = (PassThruServer *)slapi_ch_calloc( 1, sizeof( PassThruServer )); srvr->ptsrvr_url = slapi_ch_strdup( argv[i] ); @@ -230,10 +231,10 @@ passthru_config( int argc, char **argv ) /* * parse the LDAP URL */ - if (( rc = ldap_url_parse( srvr->ptsrvr_url, &ludp )) != 0 ) { + if (( rc = slapi_ldap_url_parse( srvr->ptsrvr_url, &ludp, 0, &secure )) != 0 ) { slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM, "unable to parse LDAP URL \"%s\" (%s)\n", - srvr->ptsrvr_url, passthru_urlparse_err2string( rc )); + srvr->ptsrvr_url, slapi_urlparse_err2string( rc )); return( LDAP_PARAM_ERROR ); } @@ -246,8 +247,7 @@ passthru_config( int argc, char **argv ) srvr->ptsrvr_hostname = slapi_ch_strdup( ludp->lud_host ); srvr->ptsrvr_port = ludp->lud_port; - srvr->ptsrvr_secure = - (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ); + srvr->ptsrvr_secure = secure; if (starttls) { srvr->ptsrvr_secure = 2; } @@ -265,7 +265,7 @@ passthru_config( int argc, char **argv ) /* * split the DN into multiple suffixes (separated by ';') */ - if (( suffixarray = ldap_str2charray( ludp->lud_dn, ";" )) == NULL ) { + if (( suffixarray = slapi_str2charray( ludp->lud_dn, ";" )) == NULL ) { slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM, "unable to parse suffix string \"%s\" within \"%s\"\n", ludp->lud_dn, srvr->ptsrvr_url ); diff --git a/ldap/servers/plugins/passthru/ptutil.c b/ldap/servers/plugins/passthru/ptutil.c index 399e5b5a..48f3c405 100644 --- a/ldap/servers/plugins/passthru/ptutil.c +++ b/ldap/servers/plugins/passthru/ptutil.c @@ -116,33 +116,3 @@ passthru_free_bervals( struct berval **bvs ) } slapi_ch_free( (void **)&bvs ); } - - -char * -passthru_urlparse_err2string( int err ) -{ - char *s; - - switch( err ) { - case 0: - s = "no error"; - break; - case LDAP_URL_ERR_NOTLDAP: - s = "missing ldap:// or ldaps://"; - break; - case LDAP_URL_ERR_NODN: - s = "missing suffix"; - break; - case LDAP_URL_ERR_BADSCOPE: - s = "invalid search scope"; - break; - case LDAP_URL_ERR_MEM: - s = "unable to allocate memory"; - break; - case LDAP_URL_ERR_PARAM: - s = "bad parameter to an LDAP URL function"; - break; - } - - return( s ); -} diff --git a/ldap/servers/plugins/pwdstorage/clear_pwd.c b/ldap/servers/plugins/pwdstorage/clear_pwd.c index fd8ab46b..19011ac6 100644 --- a/ldap/servers/plugins/pwdstorage/clear_pwd.c +++ b/ldap/servers/plugins/pwdstorage/clear_pwd.c @@ -52,13 +52,13 @@ #include "pwdstorage.h" int -clear_pw_cmp( char *userpwd, char *dbpwd ) +clear_pw_cmp( const char *userpwd, const char *dbpwd ) { return( strcmp( userpwd, dbpwd )); } char * -clear_pw_enc( char *pwd ) +clear_pw_enc( const char *pwd ) { /* Just return NULL if pwd is NULL */ if (!pwd) diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c index 02ec7d08..666fd4b3 100644 --- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c +++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c @@ -79,7 +79,7 @@ crypt_init() } int -crypt_pw_cmp( char *userpwd, char *dbpwd ) +crypt_pw_cmp( const char *userpwd, const char *dbpwd ) { int rc; char *cp; @@ -96,7 +96,7 @@ crypt_pw_cmp( char *userpwd, char *dbpwd ) } char * -crypt_pw_enc( char *pwd ) +crypt_pw_enc( const char *pwd ) { char *cry, salt[3]; char *enc= NULL; diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c b/ldap/servers/plugins/pwdstorage/md5_pwd.c index b63c5b04..7dec2d47 100644 --- a/ldap/servers/plugins/pwdstorage/md5_pwd.c +++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c @@ -57,7 +57,7 @@ #define MD5_SUBSYSTEM_NAME "MD5 password hash" int -md5_pw_cmp( char *userpwd, char *dbpwd ) +md5_pw_cmp( const char *userpwd, const char *dbpwd ) { int rc=-1; char * bver; @@ -96,7 +96,7 @@ loser: } char * -md5_pw_enc( char *pwd ) +md5_pw_enc( const char *pwd ) { char * bver, *enc=NULL; PK11Context *ctx=NULL; diff --git a/ldap/servers/plugins/pwdstorage/ns-mta-md5_pwd.c b/ldap/servers/plugins/pwdstorage/ns-mta-md5_pwd.c index 467766fb..3dc7e34d 100644 --- a/ldap/servers/plugins/pwdstorage/ns-mta-md5_pwd.c +++ b/ldap/servers/plugins/pwdstorage/ns-mta-md5_pwd.c @@ -77,7 +77,7 @@ ns_mta_hexify(char *buffer, char *str, int len) } static char * -ns_mta_hash_alg(char *buffer, char *salt, char *passwd) +ns_mta_hash_alg(char *buffer, char *salt, const char *passwd) { mta_MD5_CTX context; char *saltstr; @@ -102,7 +102,7 @@ ns_mta_hash_alg(char *buffer, char *salt, char *passwd) } int -ns_mta_md5_pw_cmp(char * clear, char *mangled) +ns_mta_md5_pw_cmp(const char * clear, const char *mangled) { char mta_hash[33]; char mta_salt[33]; diff --git a/ldap/servers/plugins/pwdstorage/pwdstorage.h b/ldap/servers/plugins/pwdstorage/pwdstorage.h index ccd0deee..975d789e 100644 --- a/ldap/servers/plugins/pwdstorage/pwdstorage.h +++ b/ldap/servers/plugins/pwdstorage/pwdstorage.h @@ -46,6 +46,7 @@ #include "slapi-plugin.h" #include <ssl.h> #include "nspr.h" +#include "plbase64.h" #include "ldif.h" #include "md5.h" @@ -54,7 +55,7 @@ #define PWD_HASH_PREFIX_START '{' #define PWD_HASH_PREFIX_END '}' -#define MAX_SHA_HASH_SIZE 64 +#define MAX_SHA_HASH_SIZE HASH_LENGTH_MAX #define SHA1_SCHEME_NAME "SHA" #define SHA1_NAME_LEN 3 @@ -81,31 +82,31 @@ #define MD5_SCHEME_NAME "MD5" #define MD5_NAME_LEN 3 -SECStatus sha_salted_hash(unsigned char *hash_out, char *pwd, struct berval *salt, unsigned int secOID); -int sha_pw_cmp( char *userpwd, char *dbpwd, unsigned int shaLen ); -char * sha_pw_enc( char *pwd, unsigned int shaLen ); -char * salted_sha_pw_enc( char *pwd, unsigned int shaLen ); -int sha1_pw_cmp( char *userpwd, char *dbpwd ); -char * sha1_pw_enc( char *pwd ); -char * salted_sha1_pw_enc( char *pwd ); -int sha256_pw_cmp( char *userpwd, char *dbpwd ); -char * sha256_pw_enc( char *pwd ); -char * salted_sha256_pw_enc( char *pwd ); -int sha384_pw_cmp( char *userpwd, char *dbpwd ); -char * sha384_pw_enc( char *pwd ); -char * salted_sha384_pw_enc( char *pwd ); -int sha512_pw_cmp( char *userpwd, char *dbpwd ); -char * sha512_pw_enc( char *pwd ); -char * salted_sha512_pw_enc( char *pwd ); -int clear_pw_cmp( char *userpwd, char *dbpwd ); -char *clear_pw_enc( char *pwd ); +SECStatus sha_salted_hash(char *hash_out, const char *pwd, struct berval *salt, unsigned int secOID); +int sha_pw_cmp( const char *userpwd, const char *dbpwd, unsigned int shaLen ); +char * sha_pw_enc( const char *pwd, unsigned int shaLen ); +char * salted_sha_pw_enc( const char *pwd, unsigned int shaLen ); +int sha1_pw_cmp( const char *userpwd, const char *dbpwd ); +char * sha1_pw_enc( const char *pwd ); +char * salted_sha1_pw_enc( const char *pwd ); +int sha256_pw_cmp( const char *userpwd, const char *dbpwd ); +char * sha256_pw_enc( const char *pwd ); +char * salted_sha256_pw_enc( const char *pwd ); +int sha384_pw_cmp( const char *userpwd, const char *dbpwd ); +char * sha384_pw_enc( const char *pwd ); +char * salted_sha384_pw_enc( const char *pwd ); +int sha512_pw_cmp( const char *userpwd, const char *dbpwd ); +char * sha512_pw_enc( const char *pwd ); +char * salted_sha512_pw_enc( const char *pwd ); +int clear_pw_cmp( const char *userpwd, const char *dbpwd ); +char *clear_pw_enc( const char *pwd ); #ifndef _WIN32 void crypt_init(); -int crypt_pw_cmp( char *userpwd, char *dbpwd ); -char *crypt_pw_enc( char *pwd ); +int crypt_pw_cmp( const char *userpwd, const char *dbpwd ); +char *crypt_pw_enc( const char *pwd ); #endif -int ns_mta_md5_pw_cmp( char *userpwd, char *dbpwd ); -int md5_pw_cmp( char *userpwd, char *dbpwd ); -char *md5_pw_enc( char *pwd ); +int ns_mta_md5_pw_cmp( const char *userpwd, const char *dbpwd ); +int md5_pw_cmp( const char *userpwd, const char *dbpwd ); +char *md5_pw_enc( const char *pwd ); #endif /* _PWDSTORAGE_H */ diff --git a/ldap/servers/plugins/pwdstorage/sha_pwd.c b/ldap/servers/plugins/pwdstorage/sha_pwd.c index ea0afdd0..e54feab7 100644 --- a/ldap/servers/plugins/pwdstorage/sha_pwd.c +++ b/ldap/servers/plugins/pwdstorage/sha_pwd.c @@ -67,20 +67,21 @@ static char *plugin_name = "NSPwdStoragePlugin"; */ int -sha_pw_cmp (char *userpwd, char *dbpwd, unsigned int shaLen ) +sha_pw_cmp (const char *userpwd, const char *dbpwd, unsigned int shaLen ) { /* * SHA passwords are stored in the database as shaLen bytes of * hash, followed by zero or more bytes of salt, all BASE64 encoded. */ int result = 1; /* failure */ - unsigned char userhash[MAX_SHA_HASH_SIZE]; - unsigned char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3]; - unsigned char *dbhash = quick_dbhash; + char userhash[MAX_SHA_HASH_SIZE]; + char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3]; + char *dbhash = quick_dbhash; struct berval salt; int hash_len; /* must be a signed valued -- see below */ unsigned int secOID; char *schemeName; + char *hashresult = NULL; /* Determine which algorithm we're using */ switch (shaLen) { @@ -107,24 +108,20 @@ sha_pw_cmp (char *userpwd, char *dbpwd, unsigned int shaLen ) /* * Decode hash stored in database. - * - * Note that ldif_base64_decode() returns a value less than zero to - * indicate that a decoding error occurred, so it is critical that - * hash_len be a signed value. */ - hash_len = (((strlen(dbpwd) + 3) / 4) * 3); /* maybe less */ + hash_len = (strlen(dbpwd) * 3) / 4; /* includes the trailing = if any */ if ( hash_len > sizeof(quick_dbhash) ) { /* get more space: */ - dbhash = (unsigned char*) slapi_ch_malloc( hash_len ); + dbhash = (char*) slapi_ch_malloc( hash_len ); if ( dbhash == NULL ) goto loser; } - hash_len = ldif_base64_decode( dbpwd, dbhash ); - if (hash_len < 0) { + hashresult = PL_Base64Decode( dbpwd, 0, dbhash ); + if (NULL == hashresult) { slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, hasherrmsg, schemeName, dbpwd ); goto loser; } else if ( hash_len >= shaLen ) { salt.bv_val = (void*)(dbhash + shaLen); - salt.bv_len = hash_len - shaLen; - } else if ( hash_len == DS40B1_SALTED_SHA_LENGTH ) { + salt.bv_len = SHA_SALT_LENGTH; + } else if ( hash_len >= DS40B1_SALTED_SHA_LENGTH ) { salt.bv_val = (void*)dbhash; salt.bv_len = 8; } else { /* unsupported, invalid BASE64 (hash_len < 0), or similar */ @@ -139,19 +136,19 @@ sha_pw_cmp (char *userpwd, char *dbpwd, unsigned int shaLen ) } /* the proof is in the comparison... */ - result = ( hash_len == DS40B1_SALTED_SHA_LENGTH ) ? - ( memcmp( userhash, dbhash + 8, hash_len - 8 )) : - ( memcmp( userhash, dbhash, shaLen )); + result = ( hash_len >= shaLen ) ? + ( memcmp( userhash, dbhash, shaLen )) : /* include salt */ + ( memcmp( userhash, dbhash + 8, hash_len - 8 )); /* exclude salt */ loser: - if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free( (void**)&dbhash ); + if ( dbhash && dbhash != quick_dbhash ) slapi_ch_free_string( &dbhash ); return result; } char * -sha_pw_enc( char *pwd, unsigned int shaLen ) +sha_pw_enc( const char *pwd, unsigned int shaLen ) { - unsigned char hash[MAX_SHA_HASH_SIZE]; + char hash[MAX_SHA_HASH_SIZE]; char *enc; char *schemeName; unsigned int schemeNameLen; @@ -196,8 +193,7 @@ sha_pw_enc( char *pwd, unsigned int shaLen ) sprintf( enc, "%c%s%c", PWD_HASH_PREFIX_START, schemeName, PWD_HASH_PREFIX_END ); - (void)ldif_base64_encode( hash, enc + 2 + schemeNameLen, - shaLen, -1 ); + (void)PL_Base64Encode( hash, shaLen, enc + 2 + schemeNameLen ); return( enc ); } @@ -206,25 +202,25 @@ sha_pw_enc( char *pwd, unsigned int shaLen ) * Wrapper password comparison functions */ int -sha1_pw_cmp (char *userpwd, char *dbpwd ) +sha1_pw_cmp (const char *userpwd, const char *dbpwd ) { return sha_pw_cmp( userpwd, dbpwd, SHA1_LENGTH ); } int -sha256_pw_cmp (char *userpwd, char *dbpwd ) +sha256_pw_cmp (const char *userpwd, const char *dbpwd ) { return sha_pw_cmp( userpwd, dbpwd, SHA256_LENGTH ); } int -sha384_pw_cmp (char *userpwd, char *dbpwd ) +sha384_pw_cmp (const char *userpwd, const char *dbpwd ) { return sha_pw_cmp( userpwd, dbpwd, SHA384_LENGTH ); } int -sha512_pw_cmp (char *userpwd, char *dbpwd ) +sha512_pw_cmp (const char *userpwd, const char *dbpwd ) { return sha_pw_cmp( userpwd, dbpwd, SHA512_LENGTH ); } @@ -233,25 +229,25 @@ sha512_pw_cmp (char *userpwd, char *dbpwd ) * Wrapper password encryption functions */ char * -sha1_pw_enc( char *pwd ) +sha1_pw_enc( const char *pwd ) { return sha_pw_enc( pwd, SHA1_LENGTH ); } char * -sha256_pw_enc( char *pwd ) +sha256_pw_enc( const char *pwd ) { return sha_pw_enc( pwd, SHA256_LENGTH ); } char * -sha384_pw_enc( char *pwd ) +sha384_pw_enc( const char *pwd ) { return sha_pw_enc( pwd, SHA384_LENGTH ); } char * -sha512_pw_enc( char *pwd ) +sha512_pw_enc( const char *pwd ) { return sha_pw_enc( pwd, SHA512_LENGTH ); } diff --git a/ldap/servers/plugins/pwdstorage/ssha_pwd.c b/ldap/servers/plugins/pwdstorage/ssha_pwd.c index 048eee42..14b8d443 100644 --- a/ldap/servers/plugins/pwdstorage/ssha_pwd.c +++ b/ldap/servers/plugins/pwdstorage/ssha_pwd.c @@ -74,7 +74,7 @@ ssha_rand_array(void *randx, size_t len) } SECStatus -sha_salted_hash(unsigned char *hash_out, char *pwd, struct berval *salt, unsigned int secOID) +sha_salted_hash(char *hash_out, const char *pwd, struct berval *salt, unsigned int secOID) { PK11Context *ctx; unsigned int outLen; @@ -108,7 +108,7 @@ sha_salted_hash(unsigned char *hash_out, char *pwd, struct berval *salt, unsigne PK11_DigestBegin(ctx); PK11_DigestOp(ctx, (unsigned char*)pwd, strlen(pwd)); PK11_DigestOp(ctx, (unsigned char*)(salt->bv_val), salt->bv_len); - PK11_DigestFinal(ctx, hash_out, &outLen, shaLen); + PK11_DigestFinal(ctx, (unsigned char*)hash_out, &outLen, shaLen); PK11_DestroyContext(ctx, 1); if (outLen == shaLen) rc = SECSuccess; @@ -118,17 +118,17 @@ sha_salted_hash(unsigned char *hash_out, char *pwd, struct berval *salt, unsigne } else { /*backward compatibility*/ - rc = PK11_HashBuf(secOID, hash_out, (unsigned char *)pwd, strlen(pwd)); + rc = PK11_HashBuf(secOID, (unsigned char*)hash_out, (unsigned char *)pwd, strlen(pwd)); } return rc; } char * -salted_sha_pw_enc( char *pwd, unsigned int shaLen ) +salted_sha_pw_enc( const char *pwd, unsigned int shaLen ) { - unsigned char hash[ MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH ]; - unsigned char *salt = hash + shaLen; + char hash[ MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH ]; + char *salt = hash + shaLen; struct berval saltval; char *enc; char *schemeName; @@ -184,8 +184,7 @@ salted_sha_pw_enc( char *pwd, unsigned int shaLen ) sprintf( enc, "%c%s%c", PWD_HASH_PREFIX_START, schemeName, PWD_HASH_PREFIX_END ); - (void)ldif_base64_encode( hash, enc + 2 + schemeNameLen, - (shaLen + SHA_SALT_LENGTH), -1 ); + (void)PL_Base64Encode( hash, (shaLen + SHA_SALT_LENGTH), enc + 2 + schemeNameLen ); return( enc ); } @@ -194,25 +193,25 @@ salted_sha_pw_enc( char *pwd, unsigned int shaLen ) * Wrapper functions for password encoding */ char * -salted_sha1_pw_enc( char *pwd ) +salted_sha1_pw_enc( const char *pwd ) { return salted_sha_pw_enc( pwd, SHA1_LENGTH ); } char * -salted_sha256_pw_enc( char *pwd ) +salted_sha256_pw_enc( const char *pwd ) { return salted_sha_pw_enc( pwd, SHA256_LENGTH ); } char * -salted_sha384_pw_enc( char *pwd ) +salted_sha384_pw_enc( const char *pwd ) { return salted_sha_pw_enc( pwd, SHA384_LENGTH ); } char * -salted_sha512_pw_enc( char *pwd ) +salted_sha512_pw_enc( const char *pwd ) { return salted_sha_pw_enc( pwd, SHA512_LENGTH ); } diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c index b0c9f4e7..dfc5765d 100644 --- a/ldap/servers/plugins/replication/cl5_api.c +++ b/ldap/servers/plugins/replication/cl5_api.c @@ -1308,9 +1308,14 @@ done:; */ int cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) { - FILE *file; +#if defined(USE_OPENLDAP) + LDIFFP *file = NULL; + int buflen; +#else + FILE *file = NULL; +#endif int rc; - char *buff; + char *buff = NULL; int lineno = 0; slapi_operation_parameters op; Object *replica = NULL; @@ -1345,7 +1350,11 @@ int cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) } /* open LDIF file */ +#if defined(USE_OPENLDAP) + file = ldif_open (ldifFile, "r"); +#else file = fopen (ldifFile, "r"); /* XXXggood Does fopen reliably work if > 255 files open? */ +#endif if (file == NULL) { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, @@ -1374,10 +1383,14 @@ int cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) } /* read entries and write them to changelog */ +#if defined(USE_OPENLDAP) + while (ldif_read_record( file, &lineno, &buff, &buflen )) +#else while ((buff = ldif_get_entry( file, &lineno )) != NULL) +#endif { rc = _cl5LDIF2Operation (buff, &op, &replGen); - slapi_ch_free ((void**)&buff); + slapi_ch_free_string(&buff); if (rc != CL5_SUCCESS) { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, @@ -1394,7 +1407,7 @@ int cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) "cl5ImportLDIF: failed to locate replica for target dn (%s) and " "replica generation %s\n", op.target_address.dn, replGen); - slapi_ch_free ((void**)&replGen); + slapi_ch_free_string(&replGen); operation_parameters_done (&op); goto done; } @@ -1409,18 +1422,25 @@ int cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "cl5ImportLDIF: failed to write operation to the changelog\n"); object_release (replica); - slapi_ch_free ((void**)&replGen); + slapi_ch_free_string(&replGen); operation_parameters_done (&op); goto done; } } object_release (replica); - slapi_ch_free ((void**)&replGen); + slapi_ch_free_string(&replGen); operation_parameters_done (&op); } done:; + if (file) { +#if defined(USE_OPENLDAP) + ldif_close(file); +#else + fclose(file); +#endif + } _cl5Close (); PR_RWLock_Unlock (s_cl5Desc.stLock); return rc; @@ -5041,46 +5061,46 @@ static int _cl5Operation2LDIF (const slapi_operation_parameters *op, const char } /* fill buffer */ - ldif_put_type_and_value(&buff, T_CHANGETYPESTR, (char*)strType, strlen (strType)); - ldif_put_type_and_value(&buff, T_REPLGEN, (char*)replGen, strlen (replGen)); - ldif_put_type_and_value(&buff, T_CSNSTR, (char*)strCSN, strlen (strCSN)); - ldif_put_type_and_value(&buff, T_UNIQUEIDSTR, op->target_address.uniqueid, - strlen (op->target_address.uniqueid)); + slapi_ldif_put_type_and_value_with_options(&buff, T_CHANGETYPESTR, (char*)strType, strlen (strType), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_REPLGEN, (char*)replGen, strlen (replGen), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_CSNSTR, (char*)strCSN, strlen (strCSN), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_UNIQUEIDSTR, op->target_address.uniqueid, + strlen (op->target_address.uniqueid), 0); switch (op->operation_type) { case SLAPI_OPERATION_ADD: if (op->p.p_add.parentuniqueid) - ldif_put_type_and_value(&buff, T_PARENTIDSTR, - op->p.p_add.parentuniqueid, strlen (op->p.p_add.parentuniqueid)); - ldif_put_type_and_value(&buff, T_DNSTR, rawDN, strlen (rawDN)); - ldif_put_type_and_value(&buff, T_CHANGESTR, l->ls_buf, l->ls_len); + slapi_ldif_put_type_and_value_with_options(&buff, T_PARENTIDSTR, + op->p.p_add.parentuniqueid, strlen (op->p.p_add.parentuniqueid), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_DNSTR, rawDN, strlen (rawDN), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_CHANGESTR, l->ls_buf, l->ls_len, 0); slapi_ch_free ((void**)&rawDN); break; - case SLAPI_OPERATION_MODIFY: ldif_put_type_and_value(&buff, T_DNSTR, op->target_address.dn, - strlen (op->target_address.dn)); - ldif_put_type_and_value(&buff, T_CHANGESTR, l->ls_buf, l->ls_len); + case SLAPI_OPERATION_MODIFY: slapi_ldif_put_type_and_value_with_options(&buff, T_DNSTR, op->target_address.dn, + strlen (op->target_address.dn), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_CHANGESTR, l->ls_buf, l->ls_len, 0); break; - case SLAPI_OPERATION_MODRDN: ldif_put_type_and_value(&buff, T_DNSTR, op->target_address.dn, - strlen (op->target_address.dn)); - ldif_put_type_and_value(&buff, T_NEWRDNSTR, op->p.p_modrdn.modrdn_newrdn, - strlen (op->p.p_modrdn.modrdn_newrdn)); - ldif_put_type_and_value(&buff, T_DRDNFLAGSTR, strDeleteOldRDN, - strlen (strDeleteOldRDN)); + case SLAPI_OPERATION_MODRDN: slapi_ldif_put_type_and_value_with_options(&buff, T_DNSTR, op->target_address.dn, + strlen (op->target_address.dn), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_NEWRDNSTR, op->p.p_modrdn.modrdn_newrdn, + strlen (op->p.p_modrdn.modrdn_newrdn), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_DRDNFLAGSTR, strDeleteOldRDN, + strlen (strDeleteOldRDN), 0); if (op->p.p_modrdn.modrdn_newsuperior_address.dn) - ldif_put_type_and_value(&buff, T_NEWSUPERIORDNSTR, + slapi_ldif_put_type_and_value_with_options(&buff, T_NEWSUPERIORDNSTR, op->p.p_modrdn.modrdn_newsuperior_address.dn, - strlen (op->p.p_modrdn.modrdn_newsuperior_address.dn)); + strlen (op->p.p_modrdn.modrdn_newsuperior_address.dn), 0); if (op->p.p_modrdn.modrdn_newsuperior_address.uniqueid) - ldif_put_type_and_value(&buff, T_NEWSUPERIORIDSTR, + slapi_ldif_put_type_and_value_with_options(&buff, T_NEWSUPERIORIDSTR, op->p.p_modrdn.modrdn_newsuperior_address.uniqueid, - strlen (op->p.p_modrdn.modrdn_newsuperior_address.uniqueid)); - ldif_put_type_and_value(&buff, T_CHANGESTR, l->ls_buf, l->ls_len); + strlen (op->p.p_modrdn.modrdn_newsuperior_address.uniqueid), 0); + slapi_ldif_put_type_and_value_with_options(&buff, T_CHANGESTR, l->ls_buf, l->ls_len, 0); break; - case SLAPI_OPERATION_DELETE: ldif_put_type_and_value(&buff, T_DNSTR, op->target_address.dn, - strlen (op->target_address.dn)); + case SLAPI_OPERATION_DELETE: slapi_ldif_put_type_and_value_with_options(&buff, T_DNSTR, op->target_address.dn, + strlen (op->target_address.dn), 0); break; } @@ -5101,7 +5121,11 @@ static int _cl5LDIF2Operation (char *ldifEntry, slapi_operation_parameters *op, char **replGen) { int rc; +#if defined(USE_OPENLDAP) + ber_len_t vlen; +#else int vlen; +#endif char *next, *line; char *type, *value; Slapi_Mods *mods; diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c index 5a171cb5..47d07be4 100644 --- a/ldap/servers/plugins/replication/repl5_connection.c +++ b/ldap/servers/plugins/replication/repl5_connection.c @@ -52,8 +52,14 @@ replica locked. Seems like right thing to do. */ #include "repl5.h" +#if defined(USE_OPENLDAP) +#include "ldap.h" +#else #include "ldappr.h" #include "ldap-extension.h" +#endif +#include "nspr.h" +#include "private/pprio.h" #include "nss.h" typedef struct repl_connection @@ -365,7 +371,7 @@ conn_read_result_ex(Repl_Connection *conn, char **retoidp, struct berval **retda if (0 == rc) { /* Timeout */ - rc = ldap_get_lderrno(conn->ld, NULL, NULL); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, NULL); conn->last_ldap_error = LDAP_TIMEOUT; return_value = CONN_TIMEOUT; } @@ -383,7 +389,7 @@ conn_read_result_ex(Repl_Connection *conn, char **retoidp, struct berval **retda /* Error */ char *s = NULL; - rc = ldap_get_lderrno(conn->ld, NULL, &s); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, &s); conn->last_ldap_errmsg = s; conn->last_ldap_error = rc; /* some errors will require a disconnect and retry the connection @@ -485,6 +491,61 @@ conn_read_result(Repl_Connection *conn, int *message_id) * on the same connection), we need to _first_ verify that the connection * is writable. If it isn't, we can deadlock if we proceed any further... */ +#if defined(USE_OPENLDAP) +/* openldap has LBER_SB_OPT_DATA_READY but that doesn't really + work for our purposes - so we grab the openldap fd from the + ber sockbuf layer, import it into a PR Poll FD, then + do the poll +*/ +static ConnResult +see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) +{ + PRFileDesc *pollfd = NULL; + PRPollDesc polldesc; + ber_socket_t fd = 0; + int rc; + + /* get the sockbuf */ + ldap_get_option(conn->ld, LDAP_OPT_DESC, &fd); + if (fd <= 0) { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "%s: invalid connection insee_if_write_available \n", + agmt_get_long_name(conn->agmt)); + conn->last_ldap_error = LDAP_PARAM_ERROR; + return CONN_OPERATION_FAILED; + } + /* wrap the sockbuf fd with a NSPR FD created especially + for use with polling, and only with polling */ + pollfd = PR_CreateSocketPollFd(fd); + polldesc.fd = pollfd; + polldesc.in_flags = PR_POLL_WRITE|PR_POLL_EXCEPT; + polldesc.out_flags = 0; + + /* do the poll */ + rc = PR_Poll(&polldesc, 1, timeout); + + /* unwrap the socket */ + PR_DestroySocketPollFd(pollfd); + + /* check */ + if (rc == 0) { /* timeout */ + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: poll timed out - poll interval [%d]\n", + agmt_get_long_name(conn->agmt), + timeout); + return CONN_TIMEOUT; + } else if ((rc < 0) || ((polldesc.out_flags|PR_POLL_WRITE) == 0)) { /* error */ + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: error during poll attempt [%d:%s]\n", + agmt_get_long_name(conn->agmt), + PR_GetError(), slapd_pr_strerror(PR_GetError())); + conn->last_ldap_error = LDAP_PARAM_ERROR; + return CONN_OPERATION_FAILED; + } + + return CONN_OPERATION_SUCCESS; +} +#else /* ! USE_OPENLDAP */ /* Since we're poking around with ldap c sdk internals, we have to be careful since the PR layer stores different session and socket info than the NSS SSL layer than the SASL layer - and they all @@ -504,7 +565,7 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) memset(&iofns, 0, sizeof(iofns)); iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE; if (ldap_get_option(conn->ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns) < 0) { - rc = ldap_get_lderrno(conn->ld, NULL, NULL); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, NULL); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Failed call to ldap_get_option to get extiofns in " "see_if_write_available: LDAP error %d (%s)\n", @@ -517,7 +578,7 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) /* set up the poll structure */ if (ldap_get_option(conn->ld, LDAP_OPT_DESC, &pollstr.lpoll_fd) < 0) { - rc = ldap_get_lderrno(conn->ld, NULL, NULL); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, NULL); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Failed call to ldap_get_option for poll_fd in " "see_if_write_available: LDAP error %d (%s)\n", @@ -529,7 +590,7 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) if (ldap_get_option(conn->ld, LDAP_X_OPT_SOCKETARG, &pollstr.lpoll_socketarg) < 0) { - rc = ldap_get_lderrno(conn->ld, NULL, NULL); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, NULL); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Failed call to ldap_get_option for socketarg in " "see_if_write_available: LDAP error %d (%s)\n", @@ -553,6 +614,7 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) return CONN_OPERATION_SUCCESS; } +#endif /* ! USE_OPENLDAP */ /* * Common code to send an LDAPv3 operation and collect the result. @@ -1010,7 +1072,9 @@ conn_connect(Repl_Connection *conn) } if (return_value == CONN_OPERATION_SUCCESS) { +#if !defined(USE_OPENLDAP) int io_timeout_ms; +#endif /* Now we initialize the LDAP Structure and set options */ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, @@ -1055,10 +1119,13 @@ conn_connect(Repl_Connection *conn) ldap_set_option(conn->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); /* override the default timeout with the specified timeout */ +#if defined(USE_OPENLDAP) + ldap_set_option(conn->ld, LDAP_OPT_NETWORK_TIMEOUT, &conn->timeout); +#else io_timeout_ms = conn->timeout.tv_sec * 1000 + conn->timeout.tv_usec / 1000; prldap_set_session_option(conn->ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT, io_timeout_ms); - +#endif /* We've got an ld. Now bind to the server. */ conn->last_operation = CONN_BIND; @@ -1066,7 +1133,7 @@ conn_connect(Repl_Connection *conn) if ( bind_and_check_pwp(conn, binddn, conn->plain) == CONN_OPERATION_FAILED ) { - conn->last_ldap_error = ldap_get_lderrno (conn->ld, NULL, NULL); + conn->last_ldap_error = slapi_ldap_get_lderrno (conn->ld, NULL, NULL); conn->state = STATE_DISCONNECTED; return_value = CONN_OPERATION_FAILED; } @@ -1308,36 +1375,38 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type, const char *value) { int return_value = 0; + ber_len_t vallen; if (NULL != entry) { char *atype = NULL; BerElement *ber = NULL; + vallen = strlen(value); atype = ldap_first_attribute(ld, entry, &ber); while (NULL != atype && 0 == return_value) { if (strcasecmp(atype, type) == 0) { - char **strvals = ldap_get_values(ld, entry, atype); + struct berval **vals = ldap_get_values_len(ld, entry, atype); int i; - for (i = 0; return_value == 0 && NULL != strvals && NULL != strvals[i]; i++) + for (i = 0; return_value == 0 && NULL != vals && NULL != vals[i]; i++) { - if (strcmp(strvals[i], value) == 0) + if ((vallen == vals[i]->bv_len) && !strncmp(vals[i]->bv_val, value, vallen)) { return_value = 1; } } - if (NULL != strvals) + if (NULL != vals) { - ldap_value_free(strvals); + ldap_value_free_len(vals); } } ldap_memfree(atype); atype = ldap_next_attribute(ld, entry, ber); } if (NULL != ber) - ldap_ber_free(ber, 0); + ber_free(ber, 0); /* The last atype has not been freed yet */ if (NULL != atype) ldap_memfree(atype); @@ -1659,7 +1728,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password) char *errmsg = NULL; conn->last_ldap_error = rc; /* errmsg is a pointer directly into the ld structure - do not free */ - rc = ldap_get_lderrno( ld, NULL, &errmsg ); + rc = slapi_ldap_get_lderrno( ld, NULL, &errmsg ); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Replication bind with %s auth failed: LDAP error %d (%s) (%s)\n", agmt_get_long_name(conn->agmt), diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c index 30b7ee9c..5f280b1d 100644 --- a/ldap/servers/plugins/replication/repl5_replica.c +++ b/ldap/servers/plugins/replication/repl5_replica.c @@ -1011,10 +1011,10 @@ replica_set_referrals(Replica *r,const Slapi_ValueSet *vs) while (vv) { const char *ref = slapi_value_get_string(vv); - struct ldap_url_desc *lud = NULL; - int myrc = ldap_url_parse(ref, &lud); + LDAPURLDesc *lud = NULL; + int myrc = slapi_ldap_url_parse(ref, &lud, 0, NULL); /* see if the dn is already in the referral URL */ - if (myrc == LDAP_URL_ERR_NODN || !lud || !lud->lud_dn) { + if (!lud || !lud->lud_dn) { /* add the dn */ Slapi_Value *newval = NULL; int len = strlen(ref); diff --git a/ldap/servers/plugins/replication/repl5_total.c b/ldap/servers/plugins/replication/repl5_total.c index e82d8da3..a555bec6 100644 --- a/ldap/servers/plugins/replication/repl5_total.c +++ b/ldap/servers/plugins/replication/repl5_total.c @@ -472,7 +472,7 @@ static int my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted) { struct berval *attrval = NULL; - ber_len_t len; + ber_len_t len = -1; ber_tag_t tag; CSN *csn = NULL; char csnstring[CSN_STRSIZE + 1]; diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c index c1a86255..8703c7c2 100644 --- a/ldap/servers/plugins/replication/replutil.c +++ b/ldap/servers/plugins/replication/replutil.c @@ -381,9 +381,9 @@ make_changes_string(LDAPMod **ldm, char **includeattrs) ldm[ i ]->mod_bvalues[ j ]->bv_len ) + 1; buf = slapi_ch_malloc( len ); bufp = buf; - ldif_put_type_and_value( &bufp, ldm[ i ]->mod_type, + slapi_ldif_put_type_and_value_with_options( &bufp, ldm[ i ]->mod_type, ldm[ i ]->mod_bvalues[ j ]->bv_val, - ldm[ i ]->mod_bvalues[ j ]->bv_len ); + ldm[ i ]->mod_bvalues[ j ]->bv_len, 0 ); *bufp = '\0'; addlenstr( l, buf ); @@ -739,10 +739,10 @@ repl_set_mtn_state_and_referrals( /* next, add the repl root dn to each referral if not present */ for (ii = 0; referrals_to_set && referrals_to_set[ii]; ++ii) { - struct ldap_url_desc *lud = NULL; - int myrc = ldap_url_parse(referrals_to_set[ii], &lud); + LDAPURLDesc *lud = NULL; + int myrc = slapi_ldap_url_parse(referrals_to_set[ii], &lud, 0, NULL); /* see if the dn is already in the referral URL */ - if (myrc == LDAP_URL_ERR_NODN || !lud || !lud->lud_dn) { + if (!lud || !lud->lud_dn) { /* add the dn */ int len = strlen(referrals_to_set[ii]); const char *cdn = slapi_sdn_get_dn(repl_root_sdn); diff --git a/ldap/servers/plugins/replication/urp_glue.c b/ldap/servers/plugins/replication/urp_glue.c index 6bceb5a0..15b29d41 100644 --- a/ldap/servers/plugins/replication/urp_glue.c +++ b/ldap/servers/plugins/replication/urp_glue.c @@ -186,7 +186,7 @@ do_create_glue_entry(const Slapi_RDN *rdn, const Slapi_DN *superiordn, const cha rdnstr = slapi_ch_realloc(rdnstr, alloc_len); rdnpair = &rdnstr[rdnstr_len]; } - ldif_put_type_and_value_with_options(&rdnpair, rdntype, + slapi_ldif_put_type_and_value_with_options(&rdnpair, rdntype, rdnval, rdnval_len, LDIF_OPT_NOWRAP); *rdnpair = '\0'; } diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c index 01b61cf9..b9643b5f 100644 --- a/ldap/servers/plugins/replication/windows_connection.c +++ b/ldap/servers/plugins/replication/windows_connection.c @@ -53,7 +53,9 @@ replica locked. Seems like right thing to do. #include "repl5.h" #include "windowsrepl.h" +#if !defined(USE_OPENLDAP) #include "ldappr.h" +#endif #include "slap.h" #include "nss.h" @@ -352,7 +354,7 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn, if (0 == rc) { /* Timeout */ - rc = ldap_get_lderrno(conn->ld, NULL, NULL); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, NULL); conn->last_ldap_error = LDAP_TIMEOUT; return_value = CONN_TIMEOUT; } @@ -361,7 +363,7 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn, /* Error */ char *s = NULL; - rc = ldap_get_lderrno(conn->ld, NULL, &s); + rc = slapi_ldap_get_lderrno(conn->ld, NULL, &s); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Received error %d: %s for %s operation\n", agmt_get_long_name(conn->agmt), @@ -591,7 +593,7 @@ windows_LDAPMessage2Entry(Repl_Connection *conn, LDAPMessage * msg, int attrsonl } if ( NULL != ber ) { - ldap_ber_free( ber, 0 ); + ber_free( ber, 0 ); } windows_private_set_raw_entry(conn->agmt, rawentry); /* windows private now owns rawentry */ @@ -1214,7 +1216,9 @@ windows_conn_connect(Repl_Connection *conn) } if (return_value == CONN_OPERATION_SUCCESS) { +#if !defined(USE_OPENLDAP) int io_timeout_ms; +#endif /* Now we initialize the LDAP Structure and set options */ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, @@ -1260,10 +1264,13 @@ windows_conn_connect(Repl_Connection *conn) ldap_set_option(conn->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); /* override the default timeout with the specified timeout */ +#if defined(USE_OPENLDAP) + ldap_set_option(conn->ld, LDAP_OPT_NETWORK_TIMEOUT, &conn->timeout); +#else io_timeout_ms = conn->timeout.tv_sec * 1000 + conn->timeout.tv_usec / 1000; prldap_set_session_option(conn->ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT, io_timeout_ms); - +#endif /* We've got an ld. Now bind to the server. */ conn->last_operation = CONN_BIND; @@ -1271,7 +1278,7 @@ windows_conn_connect(Repl_Connection *conn) if ( bind_and_check_pwp(conn, binddn, conn->plain) == CONN_OPERATION_FAILED ) { - conn->last_ldap_error = ldap_get_lderrno (conn->ld, NULL, NULL); + conn->last_ldap_error = slapi_ldap_get_lderrno (conn->ld, NULL, NULL); conn->state = STATE_DISCONNECTED; return_value = CONN_OPERATION_FAILED; } @@ -1594,6 +1601,7 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type, const char *value) { int return_value = 0; + ber_len_t vallen; LDAPDebug( LDAP_DEBUG_TRACE, "=> attribute_string_value_present\n", 0, 0, 0 ); @@ -1602,30 +1610,31 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type, char *atype = NULL; BerElement *ber = NULL; + vallen = strlen(value); atype = ldap_first_attribute(ld, entry, &ber); while (NULL != atype && 0 == return_value) { if (strcasecmp(atype, type) == 0) { - char **strvals = ldap_get_values(ld, entry, atype); + struct berval **vals = ldap_get_values_len(ld, entry, atype); int i; - for (i = 0; return_value == 0 && NULL != strvals && NULL != strvals[i]; i++) + for (i = 0; return_value == 0 && NULL != vals && NULL != vals[i]; i++) { - if (strcmp(strvals[i], value) == 0) + if ((vallen == vals[i]->bv_len) && !strncmp(vals[i]->bv_val, value, vallen)) { return_value = 1; } } - if (NULL != strvals) + if (NULL != vals) { - ldap_value_free(strvals); + ldap_value_free_len(vals); } } ldap_memfree(atype); atype = ldap_next_attribute(ld, entry, ber); } if (NULL != ber) - ldap_ber_free(ber, 0); + ber_free(ber, 0); /* The last atype has not been freed yet */ if (NULL != atype) ldap_memfree(atype); @@ -1768,7 +1777,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password) char *errmsg = NULL; conn->last_ldap_error = rc; /* errmsg is a pointer directly into the ld structure - do not free */ - rc = ldap_get_lderrno( ld, NULL, &errmsg ); + rc = slapi_ldap_get_lderrno( ld, NULL, &errmsg ); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: Replication bind with %s auth failed: LDAP error %d (%s) (%s)\n", agmt_get_long_name(conn->agmt), @@ -1816,13 +1825,13 @@ do_simple_bind (Repl_Connection *conn, LDAP *ld, char * binddn, char *password) LDAPDebug( LDAP_DEBUG_TRACE, "=> do_simple_bind\n", 0, 0, 0 ); - if( ( msgid = ldap_simple_bind( ld, binddn, password ) ) == -1 ) + if( ( msgid = slapi_ldap_bind( ld, binddn, password, LDAP_SASL_SIMPLE, NULL, NULL, NULL, &msgid ) ) == -1 ) { char *ldaperrtext = NULL; int ldaperr; int prerr = PR_GetError(); - ldaperr = ldap_get_lderrno( ld, NULL, &ldaperrtext ); + ldaperr = slapi_ldap_get_lderrno( ld, NULL, &ldaperrtext ); /* Do not report the same error over and over again */ if (conn->last_ldap_error != ldaperr) { diff --git a/ldap/servers/plugins/retrocl/retrocl_po.c b/ldap/servers/plugins/retrocl/retrocl_po.c index d9844b83..a29fefbe 100644 --- a/ldap/servers/plugins/retrocl/retrocl_po.c +++ b/ldap/servers/plugins/retrocl/retrocl_po.c @@ -126,9 +126,9 @@ static lenstr *make_changes_string(LDAPMod **ldm, const char **includeattrs) ldm[ i ]->mod_bvalues[ j ]->bv_len ) + 1; buf = slapi_ch_malloc( len ); bufp = buf; - ldif_put_type_and_value( &bufp, ldm[ i ]->mod_type, + slapi_ldif_put_type_and_value_with_options( &bufp, ldm[ i ]->mod_type, ldm[ i ]->mod_bvalues[ j ]->bv_val, - ldm[ i ]->mod_bvalues[ j ]->bv_len ); + ldm[ i ]->mod_bvalues[ j ]->bv_len, 0 ); *bufp = '\0'; addlenstr( l, buf ); diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c index 1bd2d2f2..df683a90 100644 --- a/ldap/servers/slapd/add.c +++ b/ldap/servers/slapd/add.c @@ -80,7 +80,7 @@ do_add( Slapi_PBlock *pb ) Slapi_Operation *operation; BerElement *ber; char *last; - ber_len_t len; + ber_len_t len = -1; ber_tag_t tag; Slapi_Entry *e = NULL; int err; @@ -130,6 +130,7 @@ do_add( Slapi_PBlock *pb ) tag = ber_next_element( ber, &len, last ) ) { char *type = NULL, *normtype = NULL; struct berval **vals = NULL; + len = -1; /* reset - not used in loop */ if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, @@ -196,7 +197,7 @@ do_add( Slapi_PBlock *pb ) goto free_and_return; } - if ( tag == LBER_DEFAULT ) { + if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c index 7a757845..3cca975f 100644 --- a/ldap/servers/slapd/auditlog.c +++ b/ldap/servers/slapd/auditlog.c @@ -195,9 +195,9 @@ write_audit_file( len = LDIF_SIZE_NEEDED( len, mods[j]->mod_bvalues[i]->bv_len ) + 1; buf = slapi_ch_malloc( len ); bufp = buf; - ldif_put_type_and_value( &bufp, mods[j]->mod_type, + slapi_ldif_put_type_and_value_with_options( &bufp, mods[j]->mod_type, mods[j]->mod_bvalues[i]->bv_val, - mods[j]->mod_bvalues[i]->bv_len ); + mods[j]->mod_bvalues[i]->bv_len, 0 ); *bufp = '\0'; addlenstr( l, buf ); slapi_ch_free( (void**)&buf ); diff --git a/ldap/servers/slapd/auth.c b/ldap/servers/slapd/auth.c index 064b3318..3a500eb7 100644 --- a/ldap/servers/slapd/auth.c +++ b/ldap/servers/slapd/auth.c @@ -83,7 +83,7 @@ slapu_search_s( LDAP* ld, const char* baseDN, int scope, const char* filter, LDAPControl **ctrls; if (ld != internal_ld) { - return ldap_search_s (ld, baseDN, scope, filter, attrs, attrsonly, result); + return ldap_search_ext_s (ld, baseDN, scope, filter, attrs, attrsonly, NULL, NULL, NULL, -1, result); } LDAPDebug (LDAP_DEBUG_TRACE, "=> slapu_search_s (\"%s\", %i, %s)\n", baseDN, scope, filter); @@ -240,7 +240,7 @@ static void LDAP_CALL LDAP_CALLBACK slapu_ber_free( LDAP* ld, BerElement* iter, int freebuf ) { if (ld != internal_ld) { - ldap_ber_free (iter, freebuf); + ber_free (iter, freebuf); } else { free ((Slapi_Attr**)iter); } diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c index c3edea06..59d77223 100644 --- a/ldap/servers/slapd/back-ldbm/ancestorid.c +++ b/ldap/servers/slapd/back-ldbm/ancestorid.c @@ -904,8 +904,8 @@ int slapi_sdn_suffix_cmp( slapi_sdn_get_dn(common), 0, 0); out: - ldap_value_free(rdns1); - ldap_value_free(rdns2); + slapi_ldap_value_free(rdns1); + slapi_ldap_value_free(rdns2); LDAPDebug(LDAP_DEBUG_TRACE, "slapi_sdn_suffix_cmp(<%s>, <%s>) => %d\n", slapi_sdn_get_dn(left), slapi_sdn_get_dn(right), ret); diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c index 7cde2bfc..e0f00750 100644 --- a/ldap/servers/slapd/back-ldbm/import-threads.c +++ b/ldap/servers/slapd/back-ldbm/import-threads.c @@ -274,7 +274,11 @@ import_get_version(char *str) char *valuecharptr; char *mystr, *ms; int offset; +#if defined(USE_OPENLDAP) + ber_len_t valuelen; +#else int valuelen; +#endif int my_version = 0; int retmalloc = 0; diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c index d13495b9..eccf8543 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c @@ -44,8 +44,6 @@ #include "back-ldbm.h" -extern char **str2charray(); - struct attrinfo * attrinfo_new() { @@ -186,11 +184,11 @@ attr_index_config( char *p; int *substrlens = NULL; - attrs = str2charray( argv[0], "," ); + attrs = slapi_str2charray( argv[0], "," ); if ( argc > 1 ) { - indexes = str2charray( argv[1], "," ); + indexes = slapi_str2charray( argv[1], "," ); if ( argc > 2 ) { - index_rules = str2charray( argv[2], "," ); + index_rules = slapi_str2charray( argv[2], "," ); } } for ( i = 0; attrs[i] != NULL; i++ ) { diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c index bc6215a6..5aa3669b 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c @@ -1132,7 +1132,7 @@ ldbm_config_exclude_from_export_set( void *arg, void *value, char *errorbuf, if ( NULL != value ) { char *dupvalue = slapi_ch_strdup( value ); - li->li_attrs_to_exclude_from_export = str2charray( dupvalue, " " ); + li->li_attrs_to_exclude_from_export = slapi_str2charray( dupvalue, " " ); slapi_ch_free((void**)&dupvalue); } } diff --git a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c index ba7789bc..7df0b892 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c @@ -415,8 +415,8 @@ ldbm_instance_index_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry *e, origIndexTypes = attrinfo2ConfIndexes(ainfo); origMatchingRules = attrinfo2ConfMatchingRules(ainfo); - origIndexTypesArray = str2charray(origIndexTypes, ","); - origMatchingRulesArray = str2charray(origMatchingRules, ","); + origIndexTypesArray = slapi_str2charray(origIndexTypes, ","); + origMatchingRulesArray = slapi_str2charray(origMatchingRules, ","); for (i = 0; mods[i] != NULL; i++) { config_attr = (char *)mods[i]->mod_type; @@ -621,13 +621,13 @@ int ldbm_instance_config_add_index_entry( } PL_strncpyz(tmpAttrsStr,argv[0], sizeof(tmpAttrsStr)); - attrs = str2charray( tmpAttrsStr, "," ); + attrs = slapi_str2charray( tmpAttrsStr, "," ); PL_strncpyz(tmpIndexesStr,argv[1], sizeof(tmpIndexesStr)); - indexes = str2charray( tmpIndexesStr, ","); + indexes = slapi_str2charray( tmpIndexesStr, ","); if(argc > 2) { PL_strncpyz(tmpMatchingRulesStr,argv[2], sizeof(tmpMatchingRulesStr)); - matchingRules = str2charray( tmpMatchingRulesStr, ","); + matchingRules = slapi_str2charray( tmpMatchingRulesStr, ","); } for(i=0; attrs[i] !=NULL; i++) diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c index c71dd8ee..ce4c8797 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c @@ -660,7 +660,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; } } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); if (DB_LOCK_DEADLOCK == retval) { /* Retry txn */ @@ -1055,8 +1055,8 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla */ if (!op_shared_is_allowed_attr (type, is_repl_op)) { - ldap_value_free( rdns ); - ldap_value_free( dns ); + slapi_ldap_value_free( rdns ); + slapi_ldap_value_free( dns ); slapi_ch_free_string(&dn); return LDAP_UNWILLING_TO_PERFORM; } @@ -1064,13 +1064,13 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla slapi_mods_add_modbvps( smods_wsi, LDAP_MOD_DELETE, type, bvps ); } } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); } else { badrdn = 1; } - ldap_value_free( dns ); + slapi_ldap_value_free( dns ); } else { @@ -1106,7 +1106,7 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla slapi_mods_add_modbvps( smods_wsi, LDAP_MOD_ADD, type, bvps ); } } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); } else { @@ -1313,7 +1313,7 @@ moddn_rename_child_entry( strcat(newdn,", "); } } - ldap_value_free( olddns ); + slapi_ldap_value_free( olddns ); slapi_entry_set_dn( ec->ep_entry, newdn ); add_update_entrydn_operational_attributes (ec); @@ -1369,7 +1369,7 @@ moddn_rename_children( char **parentdns; parentdns = ldap_explode_dn( slapi_sdn_get_dn(dn_parentdn), 0 ); for(;parentdns[parentdncomps]!=NULL;parentdncomps++); - ldap_value_free( parentdns ); + slapi_ldap_value_free( parentdns ); } /* @@ -1392,7 +1392,7 @@ moddn_rename_children( i++; } } - ldap_value_free( newsuperiordns ); + slapi_ldap_value_free( newsuperiordns ); return retval; } diff --git a/ldap/servers/slapd/back-ldbm/sort.c b/ldap/servers/slapd/back-ldbm/sort.c index 2694338e..639fdd52 100644 --- a/ldap/servers/slapd/back-ldbm/sort.c +++ b/ldap/servers/slapd/back-ldbm/sort.c @@ -294,7 +294,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) BerElement *ber = NULL; sort_spec_thing *listhead = NULL; ber_tag_t tag = 0; - ber_len_t len = 0; + ber_len_t len = -1; char *last = NULL; sort_spec_thing *listpointer = NULL; char *type = NULL; @@ -318,6 +318,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) sort_spec_thing *s = NULL; ber_tag_t return_value; + len = -1; /* reset - not used here */ next_tag = ber_first_element( ber, &len, &inner_last ); /* The type is not optional */ @@ -334,6 +335,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) /* Now look for the next tag. */ + len = -1; /* reset - not used here */ next_tag = ber_next_element(ber,&len, inner_last); /* Are we done ? */ @@ -343,6 +345,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) /* If so, get it */ ber_scanf(ber,"a",&matchrule); /* That can be followed by a reverse indicator */ + len = -1; /* reset - not used here */ next_tag = ber_next_element(ber,&len, inner_last); if (LDAP_TAG_SK_REVERSE == next_tag) { /* Get the reverse sort indicator here */ @@ -355,7 +358,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) } } else { /* Perhaps we're done now ? */ - if (LBER_END_OF_SEQORSET != next_tag) { + if ((LBER_END_OF_SEQORSET != next_tag) && (len != -1)) { /* Protocol error---we got a matching rule, but followed by something other * than reverse or end of sequence. */ @@ -390,7 +393,7 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) if (NULL == listhead) { listhead = s; } - + len = -1; /* reset for next loop iter */ } if (NULL == listhead) { /* LP - defect #559792 - don't return null listhead */ diff --git a/ldap/servers/slapd/back-ldbm/vlv_srch.c b/ldap/servers/slapd/back-ldbm/vlv_srch.c index 63c63485..af68d1c5 100644 --- a/ldap/servers/slapd/back-ldbm/vlv_srch.c +++ b/ldap/servers/slapd/back-ldbm/vlv_srch.c @@ -567,7 +567,7 @@ vlvIndex_delete(struct vlvIndex** ppvs) } } } - ldap_free_sort_keylist((*ppvs)->vlv_sortkey); + internal_ldap_free_sort_keylist((*ppvs)->vlv_sortkey); attrinfo_delete(&((*ppvs)->vlv_attrinfo)); slapi_ch_free((void**)&((*ppvs)->vlv_name)); slapi_ch_free((void**)&((*ppvs)->vlv_filename)); @@ -602,7 +602,7 @@ vlvIndex_init(struct vlvIndex* p, backend *be, struct vlvSearch* pSearch, const p->vlv_search= pSearch; /* Convert the textual sort specification into a keylist structure */ - ldap_create_sort_keylist(&(p->vlv_sortkey),p->vlv_sortspec); + internal_ldap_create_sort_keylist(&(p->vlv_sortkey),p->vlv_sortspec); { /* * For each sort attribute find the appropriate syntax plugin, @@ -938,3 +938,23 @@ vlv_isvlv(char *filename) return 1; return 0; } + +void +internal_ldap_free_sort_keylist(LDAPsortkey **sortKeyList) +{ +#if defined(USE_OPENLDAP) + ldap_free_sort_keylist((LDAPSortKey **)sortKeyList); +#else + ldap_free_sort_keylist(sortKeyList); +#endif +} + +int +internal_ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, const char *string_rep) +{ +#if defined(USE_OPENLDAP) + return ldap_create_sort_keylist((LDAPSortKey ***)sortKeyList, (char *)string_rep); +#else + return ldap_create_sort_keylist(sortKeyList, string_rep); +#endif +} diff --git a/ldap/servers/slapd/back-ldbm/vlv_srch.h b/ldap/servers/slapd/back-ldbm/vlv_srch.h index 71d8f27a..e32cf88b 100644 --- a/ldap/servers/slapd/back-ldbm/vlv_srch.h +++ b/ldap/servers/slapd/back-ldbm/vlv_srch.h @@ -55,6 +55,17 @@ extern char* const type_vlvFilename; extern char* const type_vlvEnabled; extern char* const type_vlvUses; +#if defined(USE_OPENLDAP) +typedef struct LDAPsortkey { /* structure for a sort-key */ + char * sk_attrtype; + char * sk_matchruleoid; + int sk_reverseorder; +} LDAPsortkey; +#endif + +void internal_ldap_free_sort_keylist(LDAPsortkey **sortKeyList); +int internal_ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, const char *string_rep); + /* * This structure is the internal representation of a VLV Search. */ diff --git a/ldap/servers/slapd/charray.c b/ldap/servers/slapd/charray.c index e57d9099..6ab492e1 100644 --- a/ldap/servers/slapd/charray.c +++ b/ldap/servers/slapd/charray.c @@ -320,9 +320,9 @@ charray_dup( char **a ) } char ** -str2charray( char *str, char *brkstr ) +slapi_str2charray( char *str, char *brkstr ) { - return( str2charray_ext( str, brkstr, 1 )); + return( slapi_str2charray_ext( str, brkstr, 1 )); } /* @@ -330,7 +330,7 @@ str2charray( char *str, char *brkstr ) * duplicate values into the array. */ char ** -str2charray_ext( char *str, char *brkstr, int allow_dups ) +slapi_str2charray_ext( char *str, char *brkstr, int allow_dups ) { char **res; char *s; diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c index e777d35b..8b1e2e5a 100644 --- a/ldap/servers/slapd/connection.c +++ b/ldap/servers/slapd/connection.c @@ -1465,6 +1465,48 @@ struct Conn_private size_t c_buffer_offset; /* offset to the location of new data in the buffer */ }; +#if defined(USE_OPENLDAP) +/* Copy up to bytes_to_read bytes from b into return_buffer. + * Returns a count of bytes copied (always >= 0). + */ +ber_slen_t +openldap_read_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + Connection *conn = NULL; + /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */ + ber_slen_t bytes_to_copy = 0; + char *readbuf; /* buffer to "read" from */ + size_t max; /* number of bytes currently stored in the buffer */ + size_t offset; /* offset to the location of new data in the buffer */ + + PR_ASSERT(sbiod); + PR_ASSERT(sbiod->sbiod_pvt); + + conn = (Connection *)sbiod->sbiod_pvt; + + PR_ASSERT(conn->c_private->c_buffer); + + readbuf = conn->c_private->c_buffer; + max = conn->c_private->c_buffer_bytes; + offset = conn->c_private->c_buffer_offset; + + if (len <= (max - offset)) { + bytes_to_copy = len; /* we have enough buffered data */ + } else { + bytes_to_copy = max - offset; /* just return what we have */ + } + + if (bytes_to_copy <= 0) { + bytes_to_copy = 0; /* never return a negative result */ + } else { + /* copy buffered data into output buf */ + SAFEMEMCPY(buf, readbuf + offset, bytes_to_copy); + conn->c_private->c_buffer_offset += bytes_to_copy; + } + return bytes_to_copy; +} +#endif + int connection_new_private(Connection *conn) { @@ -1640,14 +1682,29 @@ get_next_from_buffer( void *buffer, size_t buffer_size, ber_len_t *lenp, ber_len_t bytes_scanned = 0; *lenp = 0; +#if defined(USE_OPENLDAP) + *tagp = ber_get_next( conn->c_sb, &bytes_scanned, ber ); +#else *tagp = ber_get_next_buffer_ext( buffer, buffer_size, lenp, ber, &bytes_scanned, conn->c_sb ); - if ((LBER_OVERFLOW == *tagp || LBER_DEFAULT == *tagp) && 0 == bytes_scanned) +#endif + /* openldap ber_get_next doesn't return partial bytes_scanned if it hasn't + read a whole pdu - so we have to check the errno for the + "would block" condition meaning openldap needs more data to read */ + if ((LBER_OVERFLOW == *tagp || LBER_DEFAULT == *tagp) && 0 == bytes_scanned && + !SLAPD_SYSTEM_WOULD_BLOCK_ERROR(errno)) { if (LBER_OVERFLOW == *tagp) { err = SLAPD_DISCONNECT_BER_TOO_BIG; } + else if (errno == ERANGE) + { + /* openldap does not differentiate between length == 0 + and length > max - all we know is that there was a + problem with the length - assume too big */ + err = SLAPD_DISCONNECT_BER_TOO_BIG; + } else { err = SLAPD_DISCONNECT_BAD_BER_TAG; @@ -1664,8 +1721,13 @@ get_next_from_buffer( void *buffer, size_t buffer_size, ber_len_t *lenp, return -1; } + /* openldap_read_function will advance c_buffer_offset */ +#if !defined(USE_OPENLDAP) /* success, or need to wait for more data */ + /* if openldap could not read a whole pdu, bytes_scanned will be zero - + it does not return partial results */ conn->c_private->c_buffer_offset += bytes_scanned; +#endif return 0; } diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c index 3a0a86ce..29c6f8e7 100644 --- a/ldap/servers/slapd/conntable.c +++ b/ldap/servers/slapd/conntable.c @@ -67,10 +67,17 @@ connection_table_new(int table_size) /* DBDB---move this out of here once everything works */ ct->c[i].c_sb = ber_sockbuf_alloc(); invalid_socket = SLAPD_INVALID_SOCKET; - ber_sockbuf_set_option( ct->c[i].c_sb, LBER_SOCKBUF_OPT_DESC, &invalid_socket ); ct->c[i].c_sd = SLAPD_INVALID_SOCKET; +#if defined(USE_OPENLDAP) + ber_sockbuf_ctrl( ct->c[i].c_sb, LBER_SB_OPT_SET_FD, &invalid_socket ); + ber_sockbuf_ctrl( ct->c[i].c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize ); +#else + ber_sockbuf_set_option( ct->c[i].c_sb, LBER_SOCKBUF_OPT_DESC, &invalid_socket ); + /* openldap by default does not use readahead - the implementation is + via a sockbuf_io layer */ ber_sockbuf_set_option( ct->c[i].c_sb, LBER_SOCKBUF_OPT_NO_READ_AHEAD, LBER_OPT_ON ); ber_sockbuf_set_option( ct->c[i].c_sb, LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE, &maxbersize ); +#endif /* !USE_OPENLDAP */ #ifndef _WIN32 /* all connections start out invalid */ ct->fd[i].fd = SLAPD_INVALID_SOCKET; diff --git a/ldap/servers/slapd/control.c b/ldap/servers/slapd/control.c index aadf201b..f187f8d0 100644 --- a/ldap/servers/slapd/control.c +++ b/ldap/servers/slapd/control.c @@ -200,7 +200,7 @@ get_ldapmessage_controls_ext( { LDAPControl **ctrls, *new; ber_tag_t tag; - ber_len_t len; + ber_len_t len = -1; int rc, maxcontrols, curcontrols; char *last; int managedsait, pwpolicy_ctrl; @@ -277,6 +277,7 @@ get_ldapmessage_controls_ext( for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( ber, &len, last ) ) { + len = -1; /* reset */ if ( curcontrols >= maxcontrols - 1 ) { #define CONTROL_GRABSIZE 6 maxcontrols += CONTROL_GRABSIZE; @@ -301,6 +302,7 @@ get_ldapmessage_controls_ext( /* absent is synonomous with FALSE */ new->ldctl_iscritical = 0; } + len = -1; /* reset */ /* if we are ignoring criticality, treat as FALSE */ if (ignore_criticality) { new->ldctl_iscritical = 0; @@ -345,9 +347,10 @@ get_ldapmessage_controls_ext( (new->ldctl_value).bv_val = NULL; (new->ldctl_value).bv_len = 0; } + len = -1; /* reset for next loop iter */ } - if ( tag == LBER_ERROR ) { + if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { goto free_and_return; } diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c index 760cbb3f..59ae3a03 100644 --- a/ldap/servers/slapd/daemon.c +++ b/ldap/servers/slapd/daemon.c @@ -128,6 +128,8 @@ static int readsignalpipe = SLAPD_INVALID_SOCKET; #define FDS_SIGNAL_PIPE 0 + + static int get_configured_connection_table_size(); #ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS static void get_loopback_by_addr( void ); @@ -1652,104 +1654,17 @@ slapd_poll( void *handle, int output ) return rc; } -/* The following 4 functions each read or write count bytes from or to - * a socket handle. If all goes well, they return the same count; - * otherwise they return -1 and PR_GetError() explains the problem. - * Revision: handle changed to struct lextiof_socket_private * and first - * argument which used to be handle is now ignored. - */ -int -read_function( int ignore, void *buffer, int count, struct lextiof_socket_private *handle ) -{ - int gotbytes = 0; - int bytes; - int ioblock_timeout = config_get_ioblocktimeout(); - PRIntervalTime pr_timeout = PR_MillisecondsToInterval(ioblock_timeout); - int fd = PR_FileDesc2NativeHandle((PRFileDesc *)handle); - - if (handle == SLAPD_INVALID_SOCKET) { - PR_SetError(PR_NOT_SOCKET_ERROR, EBADF); - } else { - while (1) { - bytes = PR_Recv( (PRFileDesc *)handle, (char *)buffer + gotbytes, - count - gotbytes, 0, pr_timeout ); - if (bytes > 0) { - gotbytes += bytes; - } else if (bytes < 0) { - PRErrorCode prerr = PR_GetError(); - -#ifdef _WIN32 - /* we need to do this because on NT, once an I/O - times out on an NSPR socket, that socket must - be closed before any other I/O can happen in - this thread. - */ - if (prerr == PR_IO_TIMEOUT_ERROR) { - Connection *conn = connection_table_get_connection_from_fd(the_connection_table,(PRFileDesc *)handle); - if (conn == NULL) - return -1; - - disconnect_server (conn, conn->c_connid, -1, SLAPD_DISCONNECT_NTSSL_TIMEOUT, 0); - /* Disconnect_server just tells the poll thread that the - * socket should be closed. We'll sleep 2 seconds here to - * to make sure that the poll thread has time to run - * and close this socket. */ - DS_Sleep(PR_SecondsToInterval(2)); - - LDAPDebug(LDAP_DEBUG_CONNS, "PR_Recv(%d) " - SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", - fd, prerr, slapd_pr_strerror(prerr)); - - return -1; - } -#endif - - LDAPDebug(LDAP_DEBUG_CONNS, - "PR_Recv(%d) error %d (%s)\n", - fd, prerr, slapd_pr_strerror(prerr)); - if ( !SLAPD_PR_WOULD_BLOCK_ERROR(prerr) ) { - LDAPDebug(LDAP_DEBUG_ANY, - "PR_Recv(%d) error %d (%s)\n", - fd, prerr, slapd_pr_strerror(prerr)); - break; /* fatal error */ - } - } else if (bytes == 0) { /* PR_Recv says bytes == 0 means conn closed */ - PRErrorCode prerr = PR_GetError(); - LDAPDebug(LDAP_DEBUG_CONNS, - "PR_Recv(%d) - 0 (EOF) %d:%s\n", /* disconnected */ - fd, prerr, slapd_pr_strerror(prerr)); - PR_SetError(PR_PIPE_ERROR, EPIPE); - break; - } else if (gotbytes < count) { - LDAPDebug(LDAP_DEBUG_CONNS, - "PR_Recv(%d) received only %d bytes (expected %d bytes) - 0 (EOF)\n", /* disconnected */ - fd, gotbytes, count); - PR_SetError(PR_PIPE_ERROR, EPIPE); - break; - } - if (gotbytes == count) { /* success */ - return count; - } else if (gotbytes > count) { /* too many bytes */ - LDAPDebug(LDAP_DEBUG_ANY, - "PR_Recv(%d) overflow - received %d bytes (expected %d bytes) - error\n", - fd, gotbytes, count); - PR_SetError(PR_BUFFER_OVERFLOW_ERROR, EMSGSIZE); - break; - } else if (slapd_poll(handle, SLAPD_POLLIN) < 0) { /* error */ - break; - } - } - } - return -1; -} - - /* - * Revision: handle changed to struct lextiof_socket_private * and first - * argument which used to be handle is now ignored. + * Revision: handle changed to void * and first + * argument which used to be integer system fd is now ignored. */ -int +#if defined(USE_OPENLDAP) +static int +write_function( int ignore, void *buffer, int count, void *handle ) +#else +static int write_function( int ignore, const void *buffer, int count, struct lextiof_socket_private *handle ) +#endif { int sentbytes = 0; int bytes; @@ -1805,6 +1720,63 @@ write_function( int ignore, const void *buffer, int count, struct lextiof_socket return -1; } +#if defined(USE_OPENLDAP) +/* The argument is a pointer to the socket descriptor */ +static int +openldap_io_setup(Sockbuf_IO_Desc *sbiod, void *arg) +{ + PR_ASSERT(sbiod); + + if (arg != NULL) { + sbiod->sbiod_pvt = arg; + } + return 0; +} + +static ber_slen_t +openldap_write_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +{ + Connection *conn = NULL; + PRFileDesc *fd = NULL; + + PR_ASSERT(sbiod); + PR_ASSERT(sbiod->sbiod_pvt); + + conn = (Connection *)sbiod->sbiod_pvt; + + PR_ASSERT(conn->c_prfd); + + fd = (PRFileDesc *)conn->c_prfd; + + PR_ASSERT(fd != SLAPD_INVALID_SOCKET); + + return write_function(0, buf, len, fd); +} + +static int +openldap_io_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +{ + PR_ASSERT(0); /* not sure if this is needed */ + return -1; +} + +static int +openldap_io_close(Sockbuf_IO_Desc *sbiod) +{ + return 0; /* closing done in connection_cleanup() */ +} + +static Sockbuf_IO openldap_sockbuf_io = { + openldap_io_setup, /* sbi_setup */ + NULL, /* sbi_remove */ + openldap_io_ctrl, /* sbi_ctrl */ + openldap_read_function, /* sbi_read */ /* see connection.c */ + openldap_write_function, /* sbi_write */ + openldap_io_close /* sbi_close */ +}; + +#endif /* USE_OPENLDAP */ + int connection_type = -1; /* The type number assigned by the Factory for 'Connection' */ @@ -2145,11 +2117,15 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i /* fds[ns].out_flags = 0; */ #endif +#if defined(USE_OPENLDAP) + ber_sockbuf_add_io( conn->c_sb, &openldap_sockbuf_io, + LBER_SBIOD_LEVEL_PROVIDER, conn ); +#else /* !USE_OPENLDAP */ { struct lber_x_ext_io_fns func_pointers; memset(&func_pointers, 0, sizeof(func_pointers)); func_pointers.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; - func_pointers.lbextiofn_read = read_function; + func_pointers.lbextiofn_read = NULL; /* see connection_read_function */ func_pointers.lbextiofn_write = write_function; func_pointers.lbextiofn_writev = NULL; #ifdef _WIN32 @@ -2160,6 +2136,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i ber_sockbuf_set_option( conn->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, &func_pointers); } +#endif /* !USE_OPENLDAP */ if( secure && config_get_SSLclientAuth() != SLAPD_SSLCLIENTAUTH_OFF ) { /* Prepare to handle the client's certificate (if any): */ diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c index 04a1b356..63abaa6f 100644 --- a/ldap/servers/slapd/dse.c +++ b/ldap/servers/slapd/dse.c @@ -1204,9 +1204,9 @@ entry_dn_cmp( caddr_t d1, caddr_t d2 ) retval = len1 - len2; if (dnlist1) - ldap_value_free(dnlist1); + slapi_ldap_value_free(dnlist1); if (dnlist2) - ldap_value_free(dnlist2); + slapi_ldap_value_free(dnlist2); } } /* else entries are equal if dns are equal */ diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c index 72b3e340..fea08814 100644 --- a/ldap/servers/slapd/entry.c +++ b/ldap/servers/slapd/entry.c @@ -196,12 +196,17 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) { Slapi_Attr **a; char *valuecharptr=NULL; +#if defined(USE_OPENLDAP) + ber_len_t valuelen; +#else int valuelen; +#endif int value_state= VALUE_NOTFOUND; int attr_state= ATTRIBUTE_NOTFOUND; int maxvals; int del_maxvals; char *type; + int freetype = 0; if ( *s == '\n' || *s == '\0' ) { break; @@ -212,6 +217,11 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) "<= str2entry_fast NULL (parse_line)\n", 0, 0, 0 ); continue; } +#if defined(USE_OPENLDAP) + /* openldap always mallocs the type and value arguments to ldap_parse_line */ + retmalloc = 1; + freetype = 1; +#endif /* * Extract the attribute and value CSNs from the attribute type. @@ -228,7 +238,8 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) { /* ignore deleted values and attributes */ /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } /* Ignore CSNs */ @@ -240,7 +251,8 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) */ if((ptype==NULL)||(strcasecmp(type,ptype) != 0)) { - ptype=type; + slapi_ch_free_string(&ptype); + ptype=slapi_ch_strdup(type); nvals = 0; maxvals = 0; del_nvals = 0; @@ -259,11 +271,13 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) escape_string( valuecharptr, ebuf ), 0 ); /* the memory below was not allocated by the slapi_ch_ functions */ if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } slapi_entry_set_dn(e,slapi_ch_strdup( valuecharptr )); /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } @@ -281,7 +295,8 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) attr_syntax_read_lock(); } /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } @@ -296,7 +311,7 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) Slapi_Value *value= value_new(NULL,CSN_TYPE_NONE,NULL); slapi_value_set( value, valuecharptr, valuelen ); /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); value->v_csnset= valuecsnset; valuecsnset= NULL; if(a==NULL) @@ -308,6 +323,7 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) { LDAPDebug (LDAP_DEBUG_ANY, "str2entry_fast: Error. Non-contiguous attribute values for %s\n", type, 0, 0); PR_ASSERT(0); + if (freetype) slapi_ch_free_string(&type); continue; } break; @@ -316,17 +332,20 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) { LDAPDebug (LDAP_DEBUG_ANY, "str2entry_fast: Error. Non-contiguous deleted attribute values for %s\n", type, 0, 0); PR_ASSERT(0); + if (freetype) slapi_ch_free_string(&type); continue; } break; case ATTRIBUTE_NOTFOUND: LDAPDebug (LDAP_DEBUG_ANY, "str2entry_fast: Error. Non-contiguous deleted attribute values for %s\n", type, 0, 0); PR_ASSERT(0); + if (freetype) slapi_ch_free_string(&type); continue; /* break; ??? */ } } + if (freetype) slapi_ch_free_string(&type); /* don't need type anymore */ { const CSN *distinguishedcsn= csnset_get_csn_of_type(value->v_csnset,CSN_TYPE_VALUE_DISTINGUISHED); if(distinguishedcsn!=NULL) @@ -367,6 +386,7 @@ str2entry_fast( char *s, int flags, int read_stateinfo ) csnset_free(&valuecsnset); attr_val_cnt++; } + slapi_ch_free_string(&ptype); if ( attr_val_cnt >= ENTRY_MAX_ATTRIBUTE_VALUE_COUNT ) { LDAPDebug( LDAP_DEBUG_ANY, @@ -597,7 +617,12 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) CSNSet *valuecsnset= NULL; int value_state= VALUE_NOTFOUND; int attr_state= VALUE_NOTFOUND; - int valuelen; + int freetype = 0; +#if defined(USE_OPENLDAP) + ber_len_t valuelen; +#else + int valuelen; +#endif if ( *s == '\n' || *s == '\0' ) { break; @@ -608,7 +633,11 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) "<= slapi_str2entry NULL (parse_line)\n", 0, 0, 0 ); continue; } - +#if defined(USE_OPENLDAP) + /* openldap always mallocs type and value */ + retmalloc = 1; + freetype = 1; +#endif /* * Extract the attribute and value CSNs from the attribute type. */ @@ -624,7 +653,8 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) { /* ignore deleted values and attributes */ /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } /* Ignore CSNs */ @@ -640,12 +670,14 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) escape_string( slapi_entry_get_dn_const(e), ebuf ), escape_string( valuecharptr, ebuf ), 0 ); /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } slapi_entry_set_dn(e,slapi_ch_strdup( valuecharptr )); /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } @@ -660,7 +692,8 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) slapi_entry_set_uniqueid (e, slapi_ch_strdup(valuecharptr)); } /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); continue; } @@ -702,6 +735,8 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) if (0 != entry_attrs_new(&ea)) { /* Something very bad happened */ + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); return NULL; } for ( i = 0; i < nattrs; i++ ) @@ -755,6 +790,8 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) "<= slapi_str2entry NULL (slapi_attr_type2plugin)\n", 0, 0, 0 ); slapi_entry_free( e ); e = NULL; + if (retmalloc) slapi_ch_free_string(&valuecharptr); + if (freetype) slapi_ch_free_string(&type); goto free_and_return; } /* Get the comparison function for later use */ @@ -781,11 +818,12 @@ str2entry_dupcheck( char *s, int flags, int read_stateinfo ) nattrs++; } + if (freetype) slapi_ch_free_string(&type); sa = prev_attr; /* For readability */ value= value_new(NULL,CSN_TYPE_NONE,NULL); slapi_value_set( value, valuecharptr, valuelen ); /* the memory below was not allocated by the slapi_ch_ functions */ - if (retmalloc) slapi_ch_free((void **) &valuecharptr); + if (retmalloc) slapi_ch_free_string(&valuecharptr); value->v_csnset= valuecsnset; valuecsnset= NULL; { @@ -1228,12 +1266,12 @@ entry2str_internal_put_value( const char *attrtype, const CSN *attrcsn, CSNType { type= attrtype; } + bvp = slapi_value_get_berval(v); if (entry2str_ctrl & SLAPI_DUMP_NOWRAP) options |= LDIF_OPT_NOWRAP; if (entry2str_ctrl & SLAPI_DUMP_MINIMAL_ENCODING) options |= LDIF_OPT_MINIMAL_ENCODING; - bvp = slapi_value_get_berval(v); - ldif_put_type_and_value_with_options( ecur, (char*)type, bvp->bv_val, bvp->bv_len, options ); + slapi_ldif_put_type_and_value_with_options( ecur, type, bvp->bv_val, bvp->bv_len, options ); } static void @@ -2432,12 +2470,12 @@ slapi_entry_rdn_values_present( const Slapi_Entry *e ) } } } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); } else { rc = 0; /* Failure: the RDN seems invalid */ } - ldap_value_free( dns ); + slapi_ldap_value_free( dns ); } else { @@ -2470,16 +2508,16 @@ slapi_entry_add_rdn_values( Slapi_Entry *e ) return( LDAP_INVALID_DN_SYNTAX ); } if ( (rdns = ldap_explode_rdn( dns[0], 0 )) == NULL ) { - ldap_value_free( dns ); + slapi_ldap_value_free( dns ); return( LDAP_INVALID_DN_SYNTAX ); } - ldap_value_free( dns ); + slapi_ldap_value_free( dns ); for ( i = 0; rdns[i] != NULL && rc == LDAP_SUCCESS; i++ ) { struct ava ava; char *type; if ( rdn2ava( rdns[i], &ava ) != 0 ) { - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); return( LDAP_INVALID_DN_SYNTAX ); } @@ -2528,7 +2566,7 @@ slapi_entry_add_rdn_values( Slapi_Entry *e ) slapi_ch_free( (void **)&type ); } - ldap_value_free( rdns ); + slapi_ldap_value_free( rdns ); return( rc ); } diff --git a/ldap/servers/slapd/fe.h b/ldap/servers/slapd/fe.h index fb4ed3a0..3eb1d0ad 100644 --- a/ldap/servers/slapd/fe.h +++ b/ldap/servers/slapd/fe.h @@ -175,8 +175,6 @@ void slapd_daemon( daemon_ports_t *ports ); void daemon_register_connection(); int slapd_listenhost2addr( const char *listenhost, PRNetAddr ***addr ); int daemon_register_reslimits( void ); -int read_function(int ignore, void *buffer, int count, struct lextiof_socket_private *handle ); -int write_function(int ignore, const void *buffer, int count, struct lextiof_socket_private *handle ); PRFileDesc * get_ssl_listener_fd(); int configure_pr_socket( PRFileDesc **pr_socket, int secure, int local ); void configure_ns_socket( int * ns ); diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c index beec7d5c..0439007b 100644 --- a/ldap/servers/slapd/fedse.c +++ b/ldap/servers/slapd/fedse.c @@ -1728,7 +1728,11 @@ search_easter_egg( Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *entr { static int twiddle= -1; char *type, *value, *copy; +#if defined(USE_OPENLDAP) + ber_len_t vlen; +#else int vlen; +#endif struct berval bv; struct berval *bvals[2]; if (twiddle < 0) { diff --git a/ldap/servers/slapd/filter.c b/ldap/servers/slapd/filter.c index a3ec29c9..b3e96b4a 100644 --- a/ldap/servers/slapd/filter.c +++ b/ldap/servers/slapd/filter.c @@ -418,7 +418,7 @@ get_filter_list( Connection *conn, BerElement *ber, struct slapi_filter **new; int err; ber_tag_t tag; - ber_len_t len; + ber_len_t len = -1; char *last; LDAPDebug( LDAP_DEBUG_FILTER, "=> get_filter_list\n", 0, 0, 0 ); @@ -447,10 +447,16 @@ get_filter_list( Connection *conn, BerElement *ber, slapi_ch_free((void**)&ftmp ); } new = &(*new)->f_next; + len = -1; } *new = NULL; - if ( tag == LBER_ERROR && *fstr != NULL ) { + /* openldap does not return LBER_END_OF_SEQORSET - + so check for len == -1 - openldap ber_next_element will not set + len if it has reached the end, and -1 is not a valid value + for a real len */ + if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) && (*fstr != NULL) ) { + LDAPDebug( LDAP_DEBUG_ANY, " error parsing filter list\n", 0, 0, 0 ); slapi_ch_free((void**)fstr ); } @@ -467,7 +473,7 @@ get_substring_filter( ) { ber_tag_t tag, rc; - ber_len_t len; + ber_len_t len = -1; char *val, *last, *type = NULL; char ebuf[BUFSIZ]; @@ -489,6 +495,7 @@ get_substring_filter( tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( ber, &len, last ) ) { + len = -1; /* reset - not used in loop */ val = NULL; rc = ber_scanf( ber, "a", &val ); if ( rc == LBER_ERROR ) { @@ -547,7 +554,8 @@ get_substring_filter( } } - if ( tag == LBER_ERROR ) { + if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { + LDAPDebug( LDAP_DEBUG_ANY, " error reading substring filter\n", 0, 0, 0 ); return( LDAP_PROTOCOL_ERROR ); } if ( f->f_sub_initial == NULL && f->f_sub_any == NULL && @@ -571,7 +579,7 @@ get_extensible_filter( BerElement *ber, mr_filter_t* mrf ) { int gotelem, gotoid, gotvalue; ber_tag_t tag; - ber_len_t len; + ber_len_t len = -1; char *last; int rc = LDAP_SUCCESS; @@ -589,6 +597,7 @@ get_extensible_filter( BerElement *ber, mr_filter_t* mrf ) * * where either oid or type is required. */ + len = -1; /* reset - not used in loop */ switch ( tag ) { case LDAP_TAG_MRA_OID: if ( gotelem != 0 ) { @@ -645,7 +654,7 @@ get_extensible_filter( BerElement *ber, mr_filter_t* mrf ) } } - if ( tag == LBER_ERROR ) { + if ( (tag != LBER_ERROR) && (len != -1) ) { goto parsing_error; } diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c index e9df0949..f5666763 100644 --- a/ldap/servers/slapd/filterentry.c +++ b/ldap/servers/slapd/filterentry.c @@ -444,10 +444,10 @@ dn2attrs(const char *dn) slapi_ch_free_string( &type ); } } - ldap_value_free (avas); + slapi_ldap_value_free (avas); } } - ldap_value_free (rdns); + slapi_ldap_value_free (rdns); } return dnAttrs; } diff --git a/ldap/servers/slapd/getfilelist.c b/ldap/servers/slapd/getfilelist.c index b2ef6e21..ac79430f 100644 --- a/ldap/servers/slapd/getfilelist.c +++ b/ldap/servers/slapd/getfilelist.c @@ -130,7 +130,7 @@ matches(const char *filename, const char *pattern) return 1; /* null pattern matches everything */ /* Compile the pattern */ - re = slapi_re_comp( (char *)pattern, &error ); + re = slapi_re_comp( pattern, &error ); if (re) { /* Matches the compiled pattern against the filename */ match = slapi_re_exec( re, filename, -1 /* no time limit */ ); diff --git a/ldap/servers/slapd/globals.c b/ldap/servers/slapd/globals.c index e49aa889..91c21ed6 100644 --- a/ldap/servers/slapd/globals.c +++ b/ldap/servers/slapd/globals.c @@ -49,7 +49,6 @@ #include "ldap.h" #include <sslproto.h> /* cipher suite names */ -#include <ldap_ssl.h> #undef OFF #undef LITTLE_ENDIAN diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c new file mode 100644 index 00000000..4ea56143 --- /dev/null +++ b/ldap/servers/slapd/ldaputil.c @@ -0,0 +1,1529 @@ +/** BEGIN COPYRIGHT BLOCK + * This Program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA. + * + * In addition, as a special exception, Red Hat, Inc. gives You the additional + * right to link the code of this Program with code not covered under the GNU + * General Public License ("Non-GPL Code") and to distribute linked combinations + * including the two, subject to the limitations in this paragraph. Non-GPL Code + * permitted under this exception must only link to the code of this Program + * through those well defined interfaces identified in the file named EXCEPTION + * found in the source code files (the "Approved Interfaces"). The files of + * Non-GPL Code may instantiate templates or use macros or inline functions from + * the Approved Interfaces without causing the resulting work to be covered by + * the GNU General Public License. Only Red Hat, Inc. may make changes or + * additions to the list of Approved Interfaces. You must obey the GNU General + * Public License in all respects for all of the Program code and other code used + * in conjunction with the Program except the Non-GPL Code covered by this + * exception. If you modify this file, you may extend this exception to your + * version of the file, but you are not obligated to do so. If you do not wish to + * provide this exception without modification, you must delete this exception + * statement from your version and license this file solely under the GPL without + * exception. + * + * + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. + * Copyright (C) 2005 Red Hat, Inc. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* ldaputil.c -- LDAP utility functions and wrappers */ +#ifdef _WIN32 +#include <direct.h> /* for getcwd */ +#else +#include <sys/socket.h> +#include <sys/param.h> +#include <unistd.h> +#include <pwd.h> +#endif +#include <libgen.h> +#include <pk11func.h> +#include "slap.h" +#include "prtime.h" +#include "prinrval.h" +#include "snmp_collator.h" +#if !defined(USE_OPENLDAP) +#include <ldap_ssl.h> +#include <ldappr.h> +#endif + +#ifdef MEMPOOL_EXPERIMENTAL +void _free_wrapper(void *ptr) +{ + slapi_ch_free(&ptr); +} +#endif + +/* + * Function: slapi_ldap_unbind() + * Purpose: release an LDAP session obtained from a call to slapi_ldap_init(). + */ +void +slapi_ldap_unbind( LDAP *ld ) +{ + if ( ld != NULL ) { + ldap_unbind_ext( ld, NULL, NULL ); + } +} + +const char * +slapi_urlparse_err2string( int err ) +{ + const char *s="internal error"; + + switch( err ) { + case 0: + s = "no error"; + break; + case LDAP_URL_ERR_BADSCOPE: + s = "invalid search scope"; + break; + case LDAP_URL_ERR_MEM: + s = "unable to allocate memory"; + break; + case LDAP_URL_ERR_PARAM: + s = "bad parameter to an LDAP URL function"; + break; +#if defined(USE_OPENLDAP) + case LDAP_URL_ERR_BADSCHEME: + s = "does not begin with ldap://, ldaps://, or ldapi://"; + break; + case LDAP_URL_ERR_BADENCLOSURE: + s = "missing trailing '>' in enclosure"; + break; + case LDAP_URL_ERR_BADURL: + s = "not a valid LDAP URL"; + break; + case LDAP_URL_ERR_BADHOST: + s = "hostname part of url is not valid or not given"; + break; + case LDAP_URL_ERR_BADATTRS: + s = "attribute list not formatted correctly or missing"; + break; + case LDAP_URL_ERR_BADFILTER: + s = "search filter not correct"; + break; + case LDAP_URL_ERR_BADEXTS: + s = "extensions not specified correctly"; + break; +#else /* !USE_OPENLDAP */ + case LDAP_URL_ERR_NOTLDAP: + s = "missing ldap:// or ldaps:// or ldapi://"; + break; + case LDAP_URL_ERR_NODN: + s = "missing suffix"; + break; +#endif + } + + return( s ); +} + +/* there are various differences among url parsers - directory server + needs the ability to parse partial URLs - those with no dn - and + needs to be able to tell if it is a secure url (ldaps) or not */ +int +slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *secure) +{ + PR_ASSERT(url); + PR_ASSERT(ludpp); + int rc; + + if (secure) { + *secure = 0; + } +#if defined(HAVE_LDAP_URL_PARSE_NO_DEFAULTS) + rc = ldap_url_parse_no_defaults(url, ludpp, require_dn); + if (!rc && *ludpp && secure) { + *secure = (*ludpp)->lud_options & LDAP_URL_OPT_SECURE; + } +#else /* openldap */ +#if defined(HAVE_LDAP_URL_PARSE_EXT) + rc = ldap_url_parse_ext(url, ludpp, require_dn ? LDAP_PVT_URL_PARSE_NONE : LDAP_PVT_URL_PARSE_NOEMPTY_DN); +#else + rc = ldap_url_parse(url, ludpp); + if (rc || !*ludpp || !require_dn) { /* failed - see if failure was due to missing dn */ + size_t len = strlen(url); + /* assume the url is just scheme://host:port[/] - add the empty string + as the DN (adding a trailing / first if needed) and try to parse + again + */ + char *urlcopy = slapi_ch_smprintf("%s%s%s", url, (url[len-1] == '/' ? "" : "/"), ""); + rc = ldap_url_parse(urlcopy, ludpp); + slapi_ch_free_string(&urlcopy); + if (0 == rc) { /* only problem was the DN - free it */ + slapi_ch_free_string(&((*ludpp)->lud_dn)); + } + } +#endif + if (!rc && *ludpp && secure) { + *secure = (*ludpp)->lud_scheme && !strcmp((*ludpp)->lud_scheme, "ldaps"); + } +#endif /* openldap */ + + return rc; +} + +#include <sasl.h> + +int +slapi_ldap_get_lderrno(LDAP *ld, char **m, char **s) +{ + int rc = LDAP_SUCCESS; + +#if defined(USE_OPENLDAP) + ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &rc); + if (m) { + ldap_get_option(ld, LDAP_OPT_MATCHED_DN, m); + } + if (s) { +#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE + ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, s); +#else + ldap_get_option(ld, LDAP_OPT_ERROR_STRING, s); +#endif + } +#else /* !USE_OPENLDAP */ + rc = ldap_get_lderrno( ld, m, s ); +#endif + return rc; +} + +void +slapi_ldif_put_type_and_value_with_options( char **out, const char *t, const char *val, int vlen, unsigned long options ) +{ +#if defined(USE_OPENLDAP) + /* openldap always wraps and always does conservative base64 encoding + we unwrap here, but clients will have to do their own base64 decode */ + int type = LDIF_PUT_VALUE; + char *save = *out; + + if (options & LDIF_OPT_VALUE_IS_URL) { + type = LDIF_PUT_URL; + } + ldif_sput( out, type, t, val, vlen ); + if (options & LDIF_OPT_NOWRAP) { + /* modify out in place, stripping out continuation lines */ + char *src = save; + char *dest = save; + for (; src && *src && (src != *out); ++src) { + if (!strncmp(src, "\n ", 2)) { + src += 2; /* skip continuation */ + } + *dest++ = *src; + } + *dest = '\n'; + } +#else + ldif_put_type_and_value_with_options( out, (char *)t, (char *)val, vlen, options ); +#endif +} + +void +slapi_ldap_value_free( char **vals ) +{ +#if defined(USE_OPENLDAP) + slapi_ch_array_free(vals); +#else + ldap_value_free(vals); +#endif +} + +int +slapi_ldap_count_values( char **vals ) +{ +#if defined(USE_OPENLDAP) + return ldap_count_values_len((struct berval **)vals); +#else + return ldap_count_values(vals); +#endif +} + +/* + Perform LDAP init and return an LDAP* handle. If ldapurl is given, + that is used as the basis for the protocol, host, port, and whether + to use starttls (given on the end as ldap://..../?????starttlsOID + If hostname is given, LDAP or LDAPS is assumed, and this will override + the hostname from the ldapurl, if any. If port is > 0, this is the + port number to use. It will override the port in the ldapurl, if any. + If no port is given in port or ldapurl, the default will be used based + on the secure setting (389 for ldap, 636 for ldaps, 389 for starttls) + secure takes 1 of 3 values - 0 means regular ldap, 1 means ldaps, 2 + means regular ldap with starttls. + filename is the ldapi file name - if this is given, and no other options + are given, ldapi is assumed. + */ +/* util_sasl_path: the string argument for putenv. + It must be a global or a static */ +char util_sasl_path[MAXPATHLEN]; + +LDAP * +slapi_ldap_init_ext( + const char *ldapurl, /* full ldap url */ + const char *hostname, /* can also use this to override + host in url */ + int port, /* can also use this to override port in url */ + int secure, /* 0 for ldap, 1 for ldaps, 2 for starttls - + override proto in url */ + int shared, /* if true, LDAP* will be shared among multiple threads */ + const char *filename /* for ldapi */ +) +{ + LDAPURLDesc *ludp = NULL; + LDAP *ld = NULL; + int rc = 0; + int secureurl = 0; + + /* We need to provide a sasl path used for client connections, especially + if the server is not set up to be a sasl server - since mozldap provides + no way to override the default path programatically, we set the sasl + path to the environment variable SASL_PATH. */ + char *configpluginpath = config_get_saslpath(); + char *pluginpath = configpluginpath; + char *pp = NULL; + + if (NULL == pluginpath || (*pluginpath == '\0')) { + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", + "configpluginpath == NULL\n"); + if (!(pluginpath = getenv("SASL_PATH"))) { +#if defined(LINUX) && defined(__LP64__) + pluginpath = "/usr/lib64/sasl2"; +#else + pluginpath = "/usr/lib/sasl2"; +#endif + } + } + if ('\0' == util_sasl_path[0] || /* first time */ + NULL == (pp = strchr(util_sasl_path, '=')) || /* invalid arg for putenv */ + (0 != strcmp(++pp, pluginpath)) /* sasl_path has been updated */ ) { + PR_snprintf(util_sasl_path, sizeof(util_sasl_path), + "SASL_PATH=%s", pluginpath); + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", + "putenv(%s)\n", util_sasl_path); + putenv(util_sasl_path); + } + slapi_ch_free_string(&configpluginpath); + + /* if ldapurl is given, parse it */ + if (ldapurl && ((rc = slapi_ldap_url_parse(ldapurl, &ludp, 0, &secureurl)) || + !ludp)) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "Could not parse given LDAP URL [%s] : error [%s]\n", + ldapurl ? ldapurl : "NULL", + slapi_urlparse_err2string(rc)); + goto done; + } + + /* use url host if no host given */ + if (!hostname && ludp && ludp->lud_host) { + hostname = ludp->lud_host; + } + + /* use url port if no port given */ + if (!port && ludp && ludp->lud_port) { + port = ludp->lud_port; + } + + /* use secure setting from url if none given */ + if (!secure && ludp) { + if (secureurl) { + secure = 1; + } else if (0/* starttls option - not supported yet in LDAP URLs */) { + secure = 2; + } + } + + /* ldap_url_parse doesn't yet handle ldapi */ + /* + if (!filename && ludp && ludp->lud_file) { + filename = ludp->lud_file; + } + */ + +#ifdef MEMPOOL_EXPERIMENTAL + { + /* + * slapi_ch_malloc functions need to be set to LDAP C SDK + */ + struct ldap_memalloc_fns memalloc_fns; + memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc; + memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc; + memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc; + memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper; + } + /* + * MEMPOOL_EXPERIMENTAL: + * These LDAP C SDK init function needs to be revisited. + * In ldap_init called via ldapssl_init and prldap_init initializes + * options and set default values including memalloc_fns, then it + * initializes as sasl client by calling sasl_client_init. In + * sasl_client_init, it creates mechlist using the malloc function + * available at the moment which could mismatch the malloc/free functions + * set later. + */ +#endif + +#if defined(USE_OPENLDAP) + if (ldapurl) { + rc = ldap_initialize(&ld, ldapurl); + if (rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "Could not initialize LDAP connection to [%s]: %d:%s\n", + ldapurl, rc, ldap_err2string(rc)); + goto done; + } + } else { + char *makeurl = NULL; + if (filename) { + makeurl = slapi_ch_smprintf("ldapi://%s/", filename); + } else { /* host port */ + makeurl = slapi_ch_smprintf("ldap%s://%s:%d/", (secure == 1 ? "s" : ""), hostname, port); + } + rc = ldap_initialize(&ld, makeurl); + if (rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "Could not initialize LDAP connection to [%s]: %d:%s\n", + makeurl, rc, ldap_err2string(rc)); + slapi_ch_free_string(&makeurl); + goto done; + } + slapi_ch_free_string(&makeurl); + } +#else /* !USE_OPENLDAP */ + if (filename) { + /* ldapi in mozldap client is not yet supported */ + } else if (secure == 1) { + ld = ldapssl_init(hostname, port, secure); + } else { /* regular ldap and/or starttls */ + /* + * Leverage the libprldap layer to take care of all the NSPR + * integration. + * Note that ldapssl_init() uses libprldap implicitly. + */ + ld = prldap_init(hostname, port, shared); + } +#endif /* !USE_OPENLDAP */ + /* Update snmp interaction table */ + if (hostname) { + if (ld == NULL) { + set_snmp_interaction_row((char *)hostname, port, -1); + } else { + set_snmp_interaction_row((char *)hostname, port, 0); + } + } + + if ((ld != NULL) && !filename) { + /* + * Set the outbound LDAP I/O timeout based on the server config. + */ + int io_timeout_ms = config_get_outbound_ldap_io_timeout(); + if (io_timeout_ms > 0) { +#if defined(USE_OPENLDAP) + struct timeval tv; + tv.tv_sec = io_timeout_ms / 1000; + tv.tv_usec = (io_timeout_ms % 1000) * 1000; + if (LDAP_OPT_SUCCESS != ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv)) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set outbound I/O " + "timeout to %dms\n", + io_timeout_ms); + slapi_ldap_unbind(ld); + ld = NULL; + goto done; + } +#else /* !USE_OPENLDAP */ + if (prldap_set_session_option(ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT, + io_timeout_ms) != LDAP_SUCCESS) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set outbound I/O " + "timeout to %dms\n", + io_timeout_ms); + slapi_ldap_unbind(ld); + ld = NULL; + goto done; + } +#endif /* !USE_OPENLDAP */ + } + + /* + * Set SSL strength (server certificate validity checking). + */ + if (secure > 0) { +#if !defined(USE_OPENLDAP) + int ssl_strength = 0; +#endif + LDAP *myld = NULL; + + /* we can only use the set functions below with a real + LDAP* if it has already gone through ldapssl_init - + so, use NULL if using starttls */ + if (secure == 1) { + myld = ld; + } + + if (config_get_ssl_check_hostname()) { + /* check hostname against name in certificate */ +#if defined(USE_OPENLDAP) + if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, "hard"))) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set REQUIRE_CERT option to hard\n"); + } +#else /* !USE_OPENLDAP */ + ssl_strength = LDAPSSL_AUTH_CNCHECK; +#endif /* !USE_OPENLDAP */ + } else { + /* verify certificate only */ +#if defined(USE_OPENLDAP) + if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT, "allow"))) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set REQUIRE_CERT option to allow\n"); + } +#else /* !USE_OPENLDAP */ + ssl_strength = LDAPSSL_AUTH_CERT; +#endif /* !USE_OPENLDAP */ + } + +#if defined(USE_OPENLDAP) +#if defined(LDAP_OPT_X_TLS_PROTOCOL_MIN) + if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, LDAP_OPT_X_TLS_PROTOCOL_SSL3))) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set minimum TLS protocol level to SSL3n"); + } +#endif /* LDAP_OPT_X_TLS_PROTOCOL_MIN */ +#else /* !USE_OPENLDAP */ + if ((rc = ldapssl_set_strength(myld, ssl_strength)) || + (rc = ldapssl_set_option(myld, SSL_ENABLE_SSL2, PR_FALSE)) || + (rc = ldapssl_set_option(myld, SSL_ENABLE_SSL3, PR_TRUE)) || + (rc = ldapssl_set_option(myld, SSL_ENABLE_TLS, PR_TRUE))) { + int prerr = PR_GetError(); + + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", + "failed: unable to set SSL options (" + SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + prerr, slapd_pr_strerror(prerr)); + + } + if (secure == 1) { + /* tell bind code we are using SSL */ + ldap_set_option(ld, LDAP_OPT_SSL, LDAP_OPT_ON); + } +#endif /* !USE_OPENLDAP */ + } + } + + if (ld && (secure == 2)) { + /* We don't have a way to stash context data with the LDAP*, so we + stash the information in the client controls (currently unused). + We don't want to open the connection in ldap_init, since that's + not the semantic - the connection is not usually opened until + the first operation is sent, which is usually the bind - or + in this case, the start_tls - so we stash the start_tls so + we can do it in slapi_ldap_bind - note that this will get + cleaned up when the LDAP* is disposed of + */ + LDAPControl start_tls_dummy_ctrl; + LDAPControl **clientctrls = NULL; + + /* returns copy of controls */ + ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls); + + start_tls_dummy_ctrl.ldctl_oid = START_TLS_OID; + start_tls_dummy_ctrl.ldctl_value.bv_val = NULL; + start_tls_dummy_ctrl.ldctl_value.bv_len = 0; + start_tls_dummy_ctrl.ldctl_iscritical = 0; + slapi_add_control_ext(&clientctrls, &start_tls_dummy_ctrl, 1); + /* set option frees old list and copies the new list */ + ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, clientctrls); + ldap_controls_free(clientctrls); /* free the copy */ + } + + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", + "Success: set up conn to [%s:%d]%s\n", + hostname, port, + (secure == 2) ? " using startTLS" : + ((secure == 1) ? " using SSL" : "")); +done: + ldap_free_urldesc(ludp); + + return( ld ); +} + +/* + * Function: slapi_ldap_init() + * Description: just like ldap_ssl_init() but also arranges for the LDAP + * session handle returned to be safely shareable by multiple threads + * if "shared" is non-zero. + * Returns: + * an LDAP session handle (NULL if some local error occurs). + */ +LDAP * +slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared ) +{ + return slapi_ldap_init_ext(NULL, ldaphost, ldapport, secure, shared, NULL); +} + +/* + * Does the correct bind operation simple/sasl/cert depending + * on the arguments passed in. If the user specified to use + * starttls in init, this will do the starttls first. If using + * ssl or client cert auth, this will initialize the client side + * of that. + */ +int +slapi_ldap_bind( + LDAP *ld, /* ldap connection */ + const char *bindid, /* usually a bind DN for simple bind */ + const char *creds, /* usually a password for simple bind */ + const char *mech, /* name of mechanism */ + LDAPControl **serverctrls, /* additional controls to send */ + LDAPControl ***returnedctrls, /* returned controls */ + struct timeval *timeout, /* timeout */ + int *msgidp /* pass in non-NULL for async handling */ +) +{ + int rc = LDAP_SUCCESS; + LDAPControl **clientctrls = NULL; + int secure = 0; + struct berval bvcreds = {0, NULL}; + LDAPMessage *result = NULL; + struct berval *servercredp = NULL; + + /* do starttls if requested + NOTE - starttls is an extop, not a control, but we don't have + a place we can stash this information in the LDAP*, other + than the currently unused clientctrls */ + ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls); + if (clientctrls && clientctrls[0] && + slapi_control_present(clientctrls, START_TLS_OID, NULL, NULL)) { + secure = 2; + } else { +#if defined(USE_OPENLDAP) + /* openldap doesn't have a SSL/TLS yes/no flag - so grab the + ldapurl, parse it, and see if it is a secure one */ + char *ldapurl = NULL; + LDAPURLDesc *ludp = NULL; + + ldap_get_option(ld, LDAP_OPT_URI, &ldapurl); + slapi_ldap_url_parse(ldapurl, &ludp, 0, &secure); + ldap_free_urldesc(ludp); + slapi_ch_free_string(&ldapurl); +#else /* !USE_OPENLDAP */ + ldap_get_option(ld, LDAP_OPT_SSL, &secure); +#endif + } + ldap_controls_free(clientctrls); + ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL); + + if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) { + /* SSL connections will use the server's security context + and cert for client auth */ + rc = slapd_SSL_client_auth(ld); + + if (rc != 0) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not configure the server for cert " + "auth - error %d - make sure the server is " + "correctly configured for SSL/TLS\n", rc); + goto done; + } else { + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", + "Set up conn to use client auth\n"); + } + bvcreds.bv_val = NULL; /* ignore username and passed in creds */ + bvcreds.bv_len = 0; /* for external auth */ + bindid = NULL; + } else { /* other type of auth */ + bvcreds.bv_val = (char *)creds; + bvcreds.bv_len = creds ? strlen(creds) : 0; + } + + if (secure == 2) { /* send start tls */ + rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL); + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send startTLS request: " + "error %d (%s)\n", + rc, ldap_err2string(rc)); + goto done; + } + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", + "startTLS started on connection\n"); + } + + /* The connection has been set up - now do the actual bind, depending on + the mechanism and arguments */ + if (!mech || (mech == LDAP_SASL_SIMPLE) || + !strcmp(mech, LDAP_SASL_EXTERNAL)) { + int mymsgid = 0; + + slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", + "attempting %s bind with id [%s] creds [%s]\n", + mech ? mech : "SIMPLE", + bindid, creds); + if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, + NULL /* clientctrls */, &mymsgid))) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send bind request for id " + "[%s] mech [%s]: error %d (%s) %d (%s) %d (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc), + PR_GetError(), slapd_pr_strerror(PR_GetError()), + errno, slapd_system_strerror(errno)); + goto done; + } + + if (msgidp) { /* let caller process result */ + *msgidp = mymsgid; + } else { /* process results */ + rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result); + if (-1 == rc) { /* error */ + rc = slapi_ldap_get_lderrno(ld, NULL, NULL); + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error reading bind response for id " + "[%s] mech [%s]: error %d (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc)); + goto done; + } else if (rc == 0) { /* timeout */ + rc = LDAP_TIMEOUT; + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: timeout after [%ld.%ld] seconds reading " + "bind response for [%s] mech [%s]\n", + timeout ? timeout->tv_sec : 0, + timeout ? timeout->tv_usec : 0, + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE"); + goto done; + } + /* if we got here, we were able to read success result */ + /* Get the controls sent by the server if requested */ + if (returnedctrls) { + if ((rc = ldap_parse_result(ld, result, &rc, NULL, NULL, + NULL, returnedctrls, + 0)) != LDAP_SUCCESS) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not bind id " + "[%s] mech [%s]: error %d (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc)); + goto done; + } + } + + /* parse the bind result and get the ldap error code */ + if ((rc = ldap_parse_sasl_bind_result(ld, result, &servercredp, + 0))) { + rc = slapi_ldap_get_lderrno(ld, NULL, NULL); + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not read bind results for id " + "[%s] mech [%s]: error %d (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc)); + goto done; + } + } + } else { + /* a SASL mech - set the sasl ssf to 0 if using TLS/SSL */ + /* openldap supports tls + sasl security */ +#if !defined(USE_OPENLDAP) + if (secure) { + sasl_ssf_t max_ssf = 0; + ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf); + } +#endif + rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech, + serverctrls, returnedctrls, + msgidp); + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not perform interactive bind for id " + "[%s] mech [%s]: error %d (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc)); + } + } + +done: + slapi_ch_bvfree(&servercredp); + ldap_msgfree(result); + + return rc; +} + +/* the following implements the client side of sasl bind, for LDAP server + -> LDAP server SASL */ + +typedef struct { + char *mech; + char *authid; + char *username; + char *passwd; + char *realm; +} ldapSaslInteractVals; + +#ifdef HAVE_KRB5 +static void set_krb5_creds( + const char *authid, + const char *username, + const char *passwd, + const char *realm, + ldapSaslInteractVals *vals +); +#endif + +static void * +ldap_sasl_set_interact_vals(LDAP *ld, const char *mech, const char *authid, + const char *username, const char *passwd, + const char *realm) +{ + ldapSaslInteractVals *vals = NULL; + char *idprefix = ""; + + vals = (ldapSaslInteractVals *) + slapi_ch_calloc(1, sizeof(ldapSaslInteractVals)); + + if (!vals) { + return NULL; + } + + if (mech) { + vals->mech = slapi_ch_strdup(mech); + } else { + ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &vals->mech); + } + + if (vals->mech && !strcasecmp(vals->mech, "DIGEST-MD5")) { + idprefix = "dn:"; /* prefix name and id with this string */ + } + + if (authid) { /* use explicit passed in value */ + vals->authid = slapi_ch_smprintf("%s%s", idprefix, authid); + } else { /* use option value if any */ + ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &vals->authid); + if (!vals->authid) { +/* get server user id? */ + vals->authid = slapi_ch_strdup(""); + } + } + + if (username) { /* use explicit passed in value */ + vals->username = slapi_ch_smprintf("%s%s", idprefix, username); + } else { /* use option value if any */ + ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &vals->username); + if (!vals->username) { /* use default sasl value */ + vals->username = slapi_ch_strdup(""); + } + } + + if (passwd) { + vals->passwd = slapi_ch_strdup(passwd); + } else { + vals->passwd = slapi_ch_strdup(""); + } + + if (realm) { + vals->realm = slapi_ch_strdup(realm); + } else { + ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &vals->realm); + if (!vals->realm) { /* use default sasl value */ + vals->realm = slapi_ch_strdup(""); + } + } + +#ifdef HAVE_KRB5 + if (mech && !strcmp(mech, "GSSAPI")) { + set_krb5_creds(authid, username, passwd, realm, vals); + } +#endif /* HAVE_KRB5 */ + + return vals; +} + +static void +ldap_sasl_free_interact_vals(void *defaults) +{ + ldapSaslInteractVals *vals = defaults; + + if (vals) { + slapi_ch_free_string(&vals->mech); + slapi_ch_free_string(&vals->authid); + slapi_ch_free_string(&vals->username); + slapi_ch_free_string(&vals->passwd); + slapi_ch_free_string(&vals->realm); + slapi_ch_free(&defaults); + } +} + +static int +ldap_sasl_get_val(ldapSaslInteractVals *vals, sasl_interact_t *interact, unsigned flags) +{ + const char *defvalue = interact->defresult; + int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing */ + + if (vals != NULL) { + switch(interact->id) { + case SASL_CB_AUTHNAME: + defvalue = vals->authid; + slapi_log_error(authtracelevel, "ldap_sasl_get_val", + "Using value [%s] for SASL_CB_AUTHNAME\n", + defvalue ? defvalue : "(null)"); + break; + case SASL_CB_USER: + defvalue = vals->username; + slapi_log_error(authtracelevel, "ldap_sasl_get_val", + "Using value [%s] for SASL_CB_USER\n", + defvalue ? defvalue : "(null)"); + break; + case SASL_CB_PASS: + defvalue = vals->passwd; + slapi_log_error(authtracelevel, "ldap_sasl_get_val", + "Using value [%s] for SASL_CB_PASS\n", + defvalue ? defvalue : "(null)"); + break; + case SASL_CB_GETREALM: + defvalue = vals->realm; + slapi_log_error(authtracelevel, "ldap_sasl_get_val", + "Using value [%s] for SASL_CB_GETREALM\n", + defvalue ? defvalue : "(null)"); + break; + } + } + + if (defvalue != NULL) { + interact->result = defvalue; + if ((char *)interact->result == NULL) + return (LDAP_NO_MEMORY); + interact->len = strlen((char *)(interact->result)); + } + return (LDAP_SUCCESS); +} + +static int +ldap_sasl_interact_cb(LDAP *ld, unsigned flags, void *defaults, void *prompts) +{ + sasl_interact_t *interact = NULL; + ldapSaslInteractVals *sasldefaults = defaults; + int rc; + + if (prompts == NULL) { + return (LDAP_PARAM_ERROR); + } + + for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) { + /* Obtain the default value */ + if ((rc = ldap_sasl_get_val(sasldefaults, interact, flags)) != LDAP_SUCCESS) { + return (rc); + } + } + + return (LDAP_SUCCESS); +} + +/* figure out from the context and this error if we should + attempt to retry the bind */ +static int +can_retry_bind(LDAP *ld, const char *mech, const char *bindid, + const char *creds, int rc, const char *errmsg) +{ + int localrc = 0; + if (errmsg && strstr(errmsg, "Ticket expired")) { + localrc = 1; + } + + return localrc; +} + +int +slapd_ldap_sasl_interactive_bind( + LDAP *ld, /* ldap connection */ + const char *bindid, /* usually a bind DN for simple bind */ + const char *creds, /* usually a password for simple bind */ + const char *mech, /* name of mechanism */ + LDAPControl **serverctrls, /* additional controls to send */ + LDAPControl ***returnedctrls, /* returned controls */ + int *msgidp /* pass in non-NULL for async handling */ +) +{ + int rc = LDAP_SUCCESS; + int tries = 0; + + while (tries < 2) { + void *defaults = ldap_sasl_set_interact_vals(ld, mech, bindid, bindid, + creds, NULL); + /* have to first set the defaults used by the callback function */ + /* call the bind function */ + /* openldap does not have the ext version - not sure how to get the + returned controls */ +#if defined(USE_OPENLDAP) + rc = ldap_sasl_interactive_bind_s(ld, bindid, mech, serverctrls, + NULL, LDAP_SASL_QUIET, + ldap_sasl_interact_cb, defaults); +#else + rc = ldap_sasl_interactive_bind_ext_s(ld, bindid, mech, serverctrls, + NULL, LDAP_SASL_QUIET, + ldap_sasl_interact_cb, defaults, + returnedctrls); +#endif + ldap_sasl_free_interact_vals(defaults); + if (LDAP_SUCCESS != rc) { + char *errmsg = NULL; + rc = slapi_ldap_get_lderrno(ld, NULL, &errmsg); + slapi_log_error(SLAPI_LOG_FATAL, "slapd_ldap_sasl_interactive_bind", + "Error: could not perform interactive bind for id " + "[%s] mech [%s]: error %d (%s) (%s)\n", + bindid ? bindid : "(anon)", + mech ? mech : "SIMPLE", + rc, ldap_err2string(rc), errmsg); + if (can_retry_bind(ld, mech, bindid, creds, rc, errmsg)) { + ; /* pass through to retry one time */ + } else { + break; /* done - fail - cannot retry */ + } + } else { + break; /* done - success */ + } + tries++; + } + + return rc; +} + +#ifdef HAVE_KRB5 +#include <krb5.h> + +/* for some reason this is not in the public API? + but it is documented e.g. man kinit */ +#ifndef KRB5_ENV_CCNAME +#define KRB5_ENV_CCNAME "KRB5CCNAME" +#endif + +static void +show_one_credential(int authtracelevel, + krb5_context ctx, krb5_creds *cred) +{ + char *logname = "show_one_credential"; + krb5_error_code rc; + char *name = NULL, *sname = NULL; + char startts[BUFSIZ], endts[BUFSIZ], renewts[BUFSIZ]; + + if ((rc = krb5_unparse_name(ctx, cred->client, &name))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get client name from credential: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + if ((rc = krb5_unparse_name(ctx, cred->server, &sname))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get server name from credential: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + if (!cred->times.starttime) { + cred->times.starttime = cred->times.authtime; + } + krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.starttime, + startts, sizeof(startts), NULL); + krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.endtime, + endts, sizeof(endts), NULL); + krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.renew_till, + renewts, sizeof(renewts), NULL); + + slapi_log_error(authtracelevel, logname, + "\tKerberos credential: client [%s] server [%s] " + "start time [%s] end time [%s] renew time [%s] " + "flags [0x%x]\n", name, sname, startts, endts, + renewts, (uint32_t)cred->ticket_flags); + +cleanup: + krb5_free_unparsed_name(ctx, name); + krb5_free_unparsed_name(ctx, sname); + + return; +} + +/* + * Call this after storing the credentials in the cache + */ +static void +show_cached_credentials(int authtracelevel, + krb5_context ctx, krb5_ccache cc, + krb5_principal princ) +{ + char *logname = "show_cached_credentials"; + krb5_error_code rc = 0; + krb5_creds creds; + krb5_cc_cursor cur; + char *princ_name = NULL; + + if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get principal name from principal: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + + slapi_log_error(authtracelevel, logname, + "Ticket cache: %s:%s\nDefault principal: %s\n\n", + krb5_cc_get_type(ctx, cc), + krb5_cc_get_name(ctx, cc), princ_name); + + if ((rc = krb5_cc_start_seq_get(ctx, cc, &cur))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get cursor to iterate cached credentials: " + "%d (%s)\n", rc, error_message(rc)); + goto cleanup; + } + + while (!(rc = krb5_cc_next_cred(ctx, cc, &cur, &creds))) { + show_one_credential(authtracelevel, ctx, &creds); + krb5_free_cred_contents(ctx, &creds); + } + if (rc == KRB5_CC_END) { + if ((rc = krb5_cc_end_seq_get(ctx, cc, &cur))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not close cached credentials cursor: " + "%d (%s)\n", rc, error_message(rc)); + goto cleanup; + } + } + +cleanup: + krb5_free_unparsed_name(ctx, princ_name); + + return; +} + +static int +looks_like_a_dn(const char *username) +{ + return (username && strchr(username, '=')); +} + +static int +credentials_are_valid( + krb5_context ctx, + krb5_ccache cc, + krb5_principal princ, + const char *princ_name, + int *rc +) +{ + char *logname = "credentials_are_valid"; + int myrc = 0; + krb5_creds mcreds; /* match these values */ + krb5_creds creds; /* returned creds */ + char *tgs_princ_name = NULL; + krb5_timestamp currenttime; + int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing */ + int realm_len; + char *realm_str; + int time_buffer = 30; /* seconds - go ahead and renew if creds are + about to expire */ + + memset(&mcreds, 0, sizeof(mcreds)); + memset(&creds, 0, sizeof(creds)); + *rc = 0; + if (!cc) { + /* ok - no error */ + goto cleanup; + } + + /* have to construct the tgs server principal in + order to set mcreds.server required in order + to use krb5_cc_retrieve_creds() */ + /* get default realm first */ + realm_len = krb5_princ_realm(ctx, princ)->length; + realm_str = krb5_princ_realm(ctx, princ)->data; + tgs_princ_name = slapi_ch_smprintf("%s/%*s@%*s", KRB5_TGS_NAME, + realm_len, realm_str, + realm_len, realm_str); + + if ((*rc = krb5_parse_name(ctx, tgs_princ_name, &mcreds.server))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could parse principal [%s]: %d (%s)\n", + tgs_princ_name, *rc, error_message(*rc)); + goto cleanup; + } + + mcreds.client = princ; + if ((*rc = krb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds))) { + if (*rc == KRB5_CC_NOTFOUND) { + /* ok - no creds for this princ in the cache */ + *rc = 0; + } + goto cleanup; + } + + /* have the creds - now look at the timestamp */ + if ((*rc = krb5_timeofday(ctx, ¤ttime))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get current time: %d (%s)\n", + *rc, error_message(*rc)); + goto cleanup; + } + + if (currenttime > (creds.times.endtime + time_buffer)) { + slapi_log_error(authtracelevel, logname, + "Credentials for [%s] have expired or will soon " + "expire - now [%d] endtime [%d]\n", princ_name, + currenttime, creds.times.endtime); + goto cleanup; + } + + myrc = 1; /* credentials are valid */ +cleanup: + krb5_free_cred_contents(ctx, &creds); + slapi_ch_free_string(&tgs_princ_name); + if (mcreds.server) { + krb5_free_principal(ctx, mcreds.server); + } + + return myrc; +} + +/* + * This implementation assumes that we want to use the + * keytab from the default keytab env. var KRB5_KTNAME + * as. This code is very similar to kinit -k -t. We + * get a krb context, get the default keytab, get + * the credentials from the keytab, authenticate with + * those credentials, create a ccache, store the + * credentials in the ccache, and set the ccache + * env var to point to those credentials. + */ +static void +set_krb5_creds( + const char *authid, + const char *username, + const char *passwd, + const char *realm, + ldapSaslInteractVals *vals +) +{ + char *logname = "set_krb5_creds"; + const char *cc_type = "MEMORY"; /* keep cred cache in memory */ + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal princ = NULL; + char *princ_name = NULL; + krb5_error_code rc = 0; + krb5_creds creds; + krb5_keytab kt = NULL; + char *cc_name = NULL; + char ktname[MAX_KEYTAB_NAME_LEN]; + static char cc_env_name[1024+32]; /* size from ccdefname.c */ + int new_ccache = 0; + int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing + not sure what shell was + used for, does not + appear to be used + currently */ + + /* probably have to put a mutex around this whole thing, to avoid + problems with reentrancy, since we are setting a "global" + variable via an environment variable */ + + /* wipe this out so we can safely free it later if we + short circuit */ + memset(&creds, 0, sizeof(creds)); + + /* initialize the kerberos context */ + if ((rc = krb5_init_context(&ctx))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not init Kerberos context: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + + /* see if there is already a ccache, and see if there are + creds in the ccache */ + /* grab the default ccache - note: this does not open the cache */ + if ((rc = krb5_cc_default(ctx, &cc))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get default Kerberos ccache: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + + /* use this cache - construct the full cache name */ + cc_name = slapi_ch_smprintf("%s:%s", krb5_cc_get_type(ctx, cc), + krb5_cc_get_name(ctx, cc)); + + /* grab the principal from the ccache - will fail if there + is no ccache */ + if ((rc = krb5_cc_get_principal(ctx, cc, &princ))) { + if (KRB5_FCC_NOFILE == rc) { /* no cache - ok */ + slapi_log_error(authtracelevel, logname, + "The default credentials cache [%s] not found: " + "will create a new one.\n", cc_name); + /* close the cache - we will create a new one below */ + krb5_cc_close(ctx, cc); + cc = NULL; + slapi_ch_free_string(&cc_name); + /* fall through to the keytab auth code below */ + } else { /* fatal */ + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not open default Kerberos ccache [%s]: " + "%d (%s)\n", cc_name, rc, error_message(rc)); + goto cleanup; + } + } else { /* have a valid ccache && found principal */ + if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to get name of principal from ccache [%s]: " + "%d (%s)\n", cc_name, rc, error_message(rc)); + goto cleanup; + } + slapi_log_error(authtracelevel, logname, + "Using principal [%s] from ccache [%s]\n", + princ_name, cc_name); + } + + /* if this is not our type of ccache, there is nothing more we can + do - just punt and let sasl/gssapi take it's course - this + usually means there has been an external kinit e.g. in the + start up script, and it is the responsibility of the script to + renew those credentials or face lots of sasl/gssapi failures + This means, however, that the caller MUST MAKE SURE THERE IS NO + DEFAULT CCACHE FILE or the server will attempt to use it (and + likely fail) - THERE MUST BE NO DEFAULT CCACHE FILE IF YOU WANT + THE SERVER TO AUTHENTICATE WITH THE KEYTAB + NOTE: cc types are case sensitive and always upper case */ + if (cc && strcmp(cc_type, krb5_cc_get_type(ctx, cc))) { + static int errmsgcounter = 0; + int loglevel = SLAPI_LOG_FATAL; + if (errmsgcounter) { + loglevel = authtracelevel; + } + /* make sure we log this message once, in case the user has + done something unintended, we want to make sure they know + about it. However, if the user knows what he/she is doing, + by using an external ccache file, they probably don't want + to be notified with an error every time. */ + slapi_log_error(loglevel, logname, + "The server will use the external SASL/GSSAPI " + "credentials cache [%s:%s]. If you want the " + "server to automatically authenticate with its " + "keytab, you must remove this cache. If you " + "did not intend to use this cache, you will likely " + "see many SASL/GSSAPI authentication failures.\n", + krb5_cc_get_type(ctx, cc), krb5_cc_get_name(ctx, cc)); + errmsgcounter++; + goto cleanup; + } + + /* need to figure out which principal to use + 1) use the one from the ccache + 2) use username + 3) construct one in the form ldap/fqdn@REALM + */ + if (!princ && username && !looks_like_a_dn(username) && + (rc = krb5_parse_name(ctx, username, &princ))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Error: could not convert [%s] into a kerberos " + "principal: %d (%s)\n", username, + rc, error_message(rc)); + goto cleanup; + } + + /* if still no principal, construct one */ + if (!princ && + (rc = krb5_sname_to_principal(ctx, NULL, "ldap", + KRB5_NT_SRV_HST, &princ))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Error: could not construct ldap service " + "principal: %d (%s)\n", rc, error_message(rc)); + goto cleanup; + } + + if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to get name of principal: " + "%d (%s)\n", rc, error_message(rc)); + goto cleanup; + } + + slapi_log_error(authtracelevel, logname, + "Using principal named [%s]\n", princ_name); + + /* grab the credentials from the ccache, if any - + if the credentials are still valid, we do not have + to authenticate again */ + if (credentials_are_valid(ctx, cc, princ, princ_name, &rc)) { + slapi_log_error(authtracelevel, logname, + "Credentials for principal [%s] are still " + "valid - no auth is necessary.\n", + princ_name); + goto cleanup; + } else if (rc) { /* some error other than "there are no credentials" */ + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to verify cached credentials for " + "principal [%s]: %d (%s)\n", princ_name, + rc, error_message(rc)); + goto cleanup; + } + + /* find our default keytab */ + if ((rc = krb5_kt_default(ctx, &kt))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to get default keytab: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + + /* get name of keytab for debugging purposes */ + if ((rc = krb5_kt_get_name(ctx, kt, ktname, sizeof(ktname)))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to get name of default keytab: %d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + + slapi_log_error(authtracelevel, logname, + "Using keytab named [%s]\n", ktname); + + /* now do the actual kerberos authentication using + the keytab, and get the creds */ + rc = krb5_get_init_creds_keytab(ctx, &creds, princ, kt, + 0, NULL, NULL); + if (rc) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not get initial credentials for principal [%s] " + "in keytab [%s]: %d (%s)\n", + princ_name, ktname, rc, error_message(rc)); + goto cleanup; + } + + /* completely done with the keytab now, close it */ + krb5_kt_close(ctx, kt); + kt = NULL; /* no double free */ + + /* we now have the creds and the principal to which the + creds belong - use or allocate a new memory based + cache to hold the creds */ + if (!cc_name) { +#if HAVE_KRB5_CC_NEW_UNIQUE + /* krb5_cc_new_unique is a new convenience function which + generates a new unique name and returns a memory + cache with that name */ + if ((rc = krb5_cc_new_unique(ctx, cc_type, NULL, &cc))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not create new unique memory ccache: " + "%d (%s)\n", + rc, error_message(rc)); + goto cleanup; + } + cc_name = slapi_ch_smprintf("%s:%s", cc_type, + krb5_cc_get_name(ctx, cc)); +#else + /* store the cache in memory - krb5_init_context uses malloc + to create the ctx, so the address should be unique enough + for our purposes */ + if (!(cc_name = slapi_ch_smprintf("%s:%p", cc_type, ctx))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could create Kerberos memory ccache: " + "out of memory\n"); + rc = 1; + goto cleanup; + } +#endif + slapi_log_error(authtracelevel, logname, + "Generated new memory ccache [%s]\n", cc_name); + new_ccache = 1; /* need to set this in env. */ + } else { + slapi_log_error(authtracelevel, logname, + "Using existing ccache [%s]\n", cc_name); + } + + /* krb5_cc_resolve is basically like an init - + this creates the cache structure, and creates a slot + for the cache in the static linked list in memory, if + there is not already a slot - + see cc_memory.c for details + cc could already have been created by new_unique above + */ + if (!cc && (rc = krb5_cc_resolve(ctx, cc_name, &cc))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not create ccache [%s]: %d (%s)\n", + cc_name, rc, error_message(rc)); + goto cleanup; + } + + /* wipe out previous contents of cache for this principal, if any */ + if ((rc = krb5_cc_initialize(ctx, cc, princ))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not initialize ccache [%s] for the new " + "credentials for principal [%s]: %d (%s)\n", + cc_name, princ_name, rc, error_message(rc)); + goto cleanup; + } + + /* store the credentials in the cache */ + if ((rc = krb5_cc_store_cred(ctx, cc, &creds))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Could not store the credentials in the " + "ccache [%s] for principal [%s]: %d (%s)\n", + cc_name, princ_name, rc, error_message(rc)); + goto cleanup; + } + + /* now, do a "klist" to show the credential information, and log it */ + show_cached_credentials(authtracelevel, ctx, cc, princ); + + /* set the CC env var to the value of the cc cache name */ + /* since we can't pass krb5 context up and out of here + and down through the ldap sasl layer, we set this + env var so that calls to krb5_cc_default_name will + use this */ + if (new_ccache) { + PR_snprintf(cc_env_name, sizeof(cc_env_name), + "%s=%s", KRB5_ENV_CCNAME, cc_name); + PR_SetEnv(cc_env_name); + slapi_log_error(authtracelevel, logname, + "Set new env for ccache: [%s]\n", + cc_env_name); + } + +cleanup: + /* use NULL as username and authid */ + slapi_ch_free_string(&vals->username); + slapi_ch_free_string(&vals->authid); + + krb5_free_unparsed_name(ctx, princ_name); + if (kt) { /* NULL not allowed */ + krb5_kt_close(ctx, kt); + } + if (creds.client == princ) { + creds.client = NULL; + } + krb5_free_cred_contents(ctx, &creds); + slapi_ch_free_string(&cc_name); + krb5_free_principal(ctx, princ); + if (cc) { + krb5_cc_close(ctx, cc); + } + if (ctx) { /* cannot pass NULL to free context */ + krb5_free_context(ctx); + } + return; +} + +#endif /* HAVE_KRB5 */ diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 358a745a..d806809e 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -52,7 +52,6 @@ #include "ldap.h" #include <sslproto.h> -#include <ldap_ssl.h> #undef OFF #undef LITTLE_ENDIAN diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index d90d2b49..1eac8489 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -179,6 +179,7 @@ do_modify( Slapi_PBlock *pb ) /* collect modifications & save for later */ slapi_mods_init(&smods, 0); + len = -1; for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( ber, &len, last ) ) @@ -186,6 +187,7 @@ do_modify( Slapi_PBlock *pb ) ber_int_t mod_op; mod = (LDAPMod *) slapi_ch_malloc( sizeof(LDAPMod) ); mod->mod_bvalues = NULL; + len = -1; /* reset - len is not used */ if ( ber_scanf( ber, "{i{a[V]}}", &mod_op, &type, &mod->mod_bvalues ) == LBER_ERROR ) @@ -264,7 +266,7 @@ do_modify( Slapi_PBlock *pb ) } /* check for decoding error */ - if ( tag == LBER_ERROR ) + if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { op_shared_log_error_access (pb, "MOD", dn, "decoding error"); send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL ); diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c index b8ca7fe7..e27b96e9 100644 --- a/ldap/servers/slapd/modrdn.c +++ b/ldap/servers/slapd/modrdn.c @@ -385,7 +385,7 @@ op_shared_rename(Slapi_PBlock *pb, int passin_args) } else { - ldap_value_free(rdns); + slapi_ldap_value_free(rdns); } /* check if created attributes are used in the new RDN */ @@ -409,7 +409,7 @@ op_shared_rename(Slapi_PBlock *pb, int passin_args) } else { - ldap_value_free(rdns); + slapi_ldap_value_free(rdns); } if (newsuperior != NULL) diff --git a/ldap/servers/slapd/modutil.c b/ldap/servers/slapd/modutil.c index eec7b33b..deed1ccb 100644 --- a/ldap/servers/slapd/modutil.c +++ b/ldap/servers/slapd/modutil.c @@ -816,7 +816,7 @@ slapi_mod_dump(LDAPMod *mod, int n) len = LDIF_SIZE_NEEDED( len, mod->mod_bvalues[i]->bv_len ) + 1; buf = slapi_ch_malloc( len ); bufp = buf; - ldif_put_type_and_value( &bufp, mod->mod_type, mod->mod_bvalues[i]->bv_val, mod->mod_bvalues[i]->bv_len ); + slapi_ldif_put_type_and_value_with_options( &bufp, mod->mod_type, mod->mod_bvalues[i]->bv_val, mod->mod_bvalues[i]->bv_len, 0 ); *bufp = '\0'; LDAPDebug( LDAP_DEBUG_ANY, "smod %d - value: %s", n, buf, 0); slapi_ch_free( (void**)&buf ); diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c index 85a19a45..510b257c 100644 --- a/ldap/servers/slapd/operation.c +++ b/ldap/servers/slapd/operation.c @@ -115,6 +115,43 @@ get_operation_object_type() return operation_type; } +#if defined(USE_OPENLDAP) +/* openldap doesn't have anything like this, nor does it have + a way to portably and without cheating discover the + sizeof BerElement - see lber_pvt.h for the trick used + for BerElementBuffer + so we just allocate everything separately + If we wanted to get fancy, we could use LBER_OPT_MEMORY_FNS + to override the ber malloc, realloc, etc. and use + LBER_OPT_BER_MEMCTX to provide callback data for use + with those functions +*/ +static void* +ber_special_alloc(size_t size, BerElement **ppBer) +{ + void *mem = NULL; + + /* starts out with a null buffer - will grow as needed */ + *ppBer = ber_alloc_t(0); + + /* Make sure mem size requested is aligned */ + if (0 != ( size & 0x03 )) { + size += (sizeof(ber_int_t) - (size & 0x03)); + } + + mem = slapi_ch_malloc(size); + + return mem; +} + +static void +ber_special_free(void* buf, BerElement *ber) +{ + ber_free(ber, 1); + slapi_ch_free(&buf); +} +#endif + /* * Allocate a new Slapi_Operation. * The flag parameter indicates whether the the operation is diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c index 2953b1b8..5c87303a 100644 --- a/ldap/servers/slapd/passwd_extop.c +++ b/ldap/servers/slapd/passwd_extop.c @@ -57,6 +57,8 @@ #include <prio.h> +#include <plbase64.h> + #include <ssl.h> #include "slap.h" #include "slapi-plugin.h" @@ -233,7 +235,7 @@ static int passwd_modify_userpassword(Slapi_PBlock *pb_orig, Slapi_Entry *target /* Generate a new, basic random password */ static int passwd_modify_generate_basic_passwd( int passlen, char **genpasswd ) { - unsigned char *data = NULL; + char *data = NULL; char *enc = NULL; int datalen = LDAP_EXTOP_PASSMOD_RANDOM_BYTES; int enclen = LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN + 1; @@ -247,16 +249,14 @@ static int passwd_modify_generate_basic_passwd( int passlen, char **genpasswd ) enclen = datalen * 4; /* allocate the large enough space */ } - data = (unsigned char *)slapi_ch_calloc( datalen, 1 ); - enc = (char *)slapi_ch_calloc( enclen, 1 ); + data = slapi_ch_calloc( datalen, 1 ); /* get random bytes from NSS */ - PK11_GenerateRandom( data, datalen ); + PK11_GenerateRandom( (unsigned char *)data, datalen ); /* b64 encode the random bytes to get a password made up - * of printable characters. ldif_base64_encode() will - * zero-terminate the string */ - (void)ldif_base64_encode( data, enc, passlen, -1 ); + * of printable characters. */ + enc = PL_Base64Encode( data, datalen, NULL ); /* This will get freed by the caller */ *genpasswd = slapi_ch_malloc( 1 + passlen ); @@ -264,7 +264,7 @@ static int passwd_modify_generate_basic_passwd( int passlen, char **genpasswd ) /* trim the password to the proper length */ PL_strncpyz( *genpasswd, enc, passlen + 1 ); - slapi_ch_free( (void **)&data ); + slapi_ch_free_string( &data ); slapi_ch_free_string( &enc ); return LDAP_SUCCESS; diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 7955e86a..afcdb0b2 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -1280,6 +1280,9 @@ int connection_acquire_nolock (Connection *conn); int connection_release_nolock (Connection *conn); int connection_is_free (Connection *conn); int connection_is_active_nolock (Connection *conn); +#if defined(USE_OPENLDAP) +ber_slen_t openldap_read_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len); +#endif /* * saslbind.c diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c index 026c80c7..97b0719f 100644 --- a/ldap/servers/slapd/rdn.c +++ b/ldap/servers/slapd/rdn.c @@ -96,7 +96,7 @@ slapi_rdn_init_dn(Slapi_RDN *rdn,const char *dn) if(dns!=NULL) { rdn->rdn= slapi_ch_strdup(dns[0]); - ldap_value_free(dns); + slapi_ldap_value_free(dns); } } } @@ -151,7 +151,7 @@ slapi_rdn_get_rdns(Slapi_RDN *rdn) { if(rdn->rdns!=NULL) { - ldap_value_free(rdn->rdns); + slapi_ldap_value_free(rdn->rdns); rdn->rdns= NULL; } if(rdn->rdn!=NULL) @@ -182,7 +182,7 @@ slapi_rdn_done(Slapi_RDN *rdn) if(rdn!=NULL) { slapi_ch_free((void**)&(rdn->rdn)); - ldap_value_free(rdn->rdns); + slapi_ldap_value_free(rdn->rdns); slapi_rdn_init(rdn); } } diff --git a/ldap/servers/slapd/referral.c b/ldap/servers/slapd/referral.c index 81adccd4..458da813 100644 --- a/ldap/servers/slapd/referral.c +++ b/ldap/servers/slapd/referral.c @@ -315,6 +315,7 @@ adjust_referral_basedn( char **urlp, const Slapi_DN *refsdn, LDAPURLDesc *ludp = NULL; char *p, *refdn_norm; int rc = 0; + int secure = 0; PR_ASSERT( urlp != NULL ); PR_ASSERT( *urlp != NULL ); @@ -326,22 +327,16 @@ adjust_referral_basedn( char **urlp, const Slapi_DN *refsdn, return; } - rc = ldap_url_parse( *urlp, &ludp ); - - if ((rc != 0) && - (rc != LDAP_URL_ERR_NODN)) - /* - * rc != LDAP_URL_ERR_NODN is to circumvent a pb in the C-SDK - * in ldap_url_parse. The function will return an error if the - * URL contains no DN (though it is a valid URL according to - * RFC 2255. - */ + rc = slapi_ldap_url_parse( *urlp, &ludp, 0, &secure ); + + if (rc != 0) { /* Nothing to do, just return */ + /* log bogus url? */ return; } - if (ludp && (ludp->lud_dn != NULL)) { + if (ludp && (ludp->lud_dn != NULL) && (ludp->lud_dn[0])) { refdn_norm = slapi_dn_normalize( slapi_ch_strdup( ludp->lud_dn )); diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c index 3bee6f8c..ce08c5a6 100644 --- a/ldap/servers/slapd/saslbind.c +++ b/ldap/servers/slapd/saslbind.c @@ -682,7 +682,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb) LDAPDebug(LDAP_DEBUG_TRACE, "sasl library mechs: %s\n", str, 0, 0); /* merge into result set */ dupstr = slapi_ch_strdup(str); - others = str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */); + others = slapi_str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */); charray_merge(&ret, others, 1); charray_free(others); slapi_ch_free((void**)&dupstr); @@ -722,7 +722,7 @@ ids_sasl_mech_supported(Slapi_PBlock *pb, sasl_conn_t *sasl_conn, const char *me } dupstr = slapi_ch_strdup(str); - mechs = str2charray(dupstr, ","); + mechs = slapi_str2charray(dupstr, ","); for (i = 0; mechs[i] != NULL; i++) { if (strcasecmp(mech, mechs[i]) == 0) { diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c index c2600f41..3eb3ab82 100644 --- a/ldap/servers/slapd/schema.c +++ b/ldap/servers/slapd/schema.c @@ -1997,7 +1997,7 @@ static char **read_dollar_values ( char *vals) { } } vals[k] = '\0'; - retVal = str2charray (vals, "$"); + retVal = slapi_str2charray (vals, "$"); return retVal; } diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index fd2c7d73..7fd67613 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -188,9 +188,6 @@ typedef struct symbol_t { * XXXmcs: these are defined by ldap.h or ldap-extension.h, * but only in a newer release than we use with DS today. */ -#ifndef LDAP_CONTROL_AUTH_REQUEST -#define LDAP_CONTROL_AUTH_REQUEST "2.16.840.1.113730.3.4.16" -#endif #ifndef LDAP_CONTROL_AUTH_RESPONSE #define LDAP_CONTROL_AUTH_RESPONSE "2.16.840.1.113730.3.4.15" #endif @@ -2047,8 +2044,12 @@ extern char *attr_dataversion; #define SLAPD_SNMP_UPDATE_INTERVAL (10 * 1000) /* 10 seconds */ +#ifndef LDAP_AUTH_KRBV41 #define LDAP_AUTH_KRBV41 0x81L +#endif +#ifndef LDAP_AUTH_KRBV42 #define LDAP_AUTH_KRBV42 0x82L +#endif /* for timing certain operations */ #ifdef USE_TIMERS diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 135f49b7..e04fad9b 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -129,18 +129,143 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...) /* * filter types + * openldap defines these, but not mozldap */ +#ifndef LDAP_FILTER_AND #define LDAP_FILTER_AND 0xa0L +#endif +#ifndef LDAP_FILTER_OR #define LDAP_FILTER_OR 0xa1L +#endif +#ifndef LDAP_FILTER_NOT #define LDAP_FILTER_NOT 0xa2L +#endif +#ifndef LDAP_FILTER_EQUALITY #define LDAP_FILTER_EQUALITY 0xa3L +#endif +#ifndef LDAP_FILTER_SUBSTRINGS #define LDAP_FILTER_SUBSTRINGS 0xa4L +#endif +#ifndef LDAP_FILTER_GE #define LDAP_FILTER_GE 0xa5L +#endif +#ifndef LDAP_FILTER_LE #define LDAP_FILTER_LE 0xa6L +#endif +#ifndef LDAP_FILTER_PRESENT #define LDAP_FILTER_PRESENT 0x87L +#endif +#ifndef LDAP_FILTER_APPROX #define LDAP_FILTER_APPROX 0xa8L -#define LDAP_FILTER_EXTENDED 0xa9L +#endif + +#ifndef LDAP_FILTER_EXTENDED +#ifdef LDAP_FILTER_EXT +#define LDAP_FILTER_EXTENDED LDAP_FILTER_EXT +#else +#define LDAP_FILTER_EXTENDED 0xa9L +#endif +#endif + +#ifndef LBER_END_OF_SEQORSET +#define LBER_END_OF_SEQORSET ((ber_tag_t) -2) /* 0xfffffffeU */ +#endif + +#ifndef LDAP_CHANGETYPE_ADD +#ifdef LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_ADD +#define LDAP_CHANGETYPE_ADD LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_ADD +#else +#define LDAP_CHANGETYPE_ADD 1 +#endif +#endif +#ifndef LDAP_CHANGETYPE_DELETE +#ifdef LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_DELETE +#define LDAP_CHANGETYPE_DELETE LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_DELETE +#else +#define LDAP_CHANGETYPE_DELETE 2 +#endif +#endif +#ifndef LDAP_CHANGETYPE_MODIFY +#ifdef LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_MODIFY +#define LDAP_CHANGETYPE_MODIFY LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_MODIFY +#else +#define LDAP_CHANGETYPE_MODIFY 4 +#endif +#endif +#ifndef LDAP_CHANGETYPE_MODDN +#ifdef LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_RENAME +#define LDAP_CHANGETYPE_MODDN LDAP_CONTROL_PERSSIT_ENTRY_CHANGE_RENAME +#else +#define LDAP_CHANGETYPE_MODDN 8 +#endif +#endif +#ifndef LDAP_CHANGETYPE_ANY +#define LDAP_CHANGETYPE_ANY (1|2|4|8) +#endif + +#ifndef LDAP_CONTROL_PERSISTENTSEARCH +#ifdef LDAP_CONTROL_PERSIST_REQUEST +#define LDAP_CONTROL_PERSISTENTSEARCH LDAP_CONTROL_PERSIST_REQUEST +#else +#define LDAP_CONTROL_PERSISTENTSEARCH "2.16.840.1.113730.3.4.3" +#endif +#endif +#ifndef LDAP_CONTROL_ENTRYCHANGE +#ifdef LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE +#define LDAP_CONTROL_ENTRYCHANGE LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE +#else +#define LDAP_CONTROL_ENTRYCHANGE "2.16.840.1.113730.3.4.7" +#endif +#endif + +#ifndef LDAP_CONTROL_PWEXPIRED +#define LDAP_CONTROL_PWEXPIRED "2.16.840.1.113730.3.4.4" +#endif +#ifndef LDAP_CONTROL_PWEXPIRING +#define LDAP_CONTROL_PWEXPIRING "2.16.840.1.113730.3.4.5" +#endif +#ifndef LDAP_X_CONTROL_PWPOLICY_REQUEST +#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST +#define LDAP_X_CONTROL_PWPOLICY_REQUEST LDAP_CONTROL_PASSWORDPOLICYREQUEST +#else +#define LDAP_X_CONTROL_PWPOLICY_REQUEST "1.3.6.1.4.1.42.2.27.8.5.1" +#endif +#endif +#ifndef LDAP_X_CONTROL_PWPOLICY_RESPONSE +#ifdef LDAP_CONTROL_PASSWORDPOLICYRESPONSE +#define LDAP_X_CONTROL_PWPOLICY_RESPONSE LDAP_CONTROL_PASSWORDPOLICYRESPONSE +#else +#define LDAP_X_CONTROL_PWPOLICY_RESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" +#endif +#endif + +#ifndef LDAP_CONTROL_PROXYAUTH +#define LDAP_CONTROL_PROXYAUTH "2.16.840.1.113730.3.4.12" /* version 1 */ +#endif +#ifndef LDAP_CONTROL_PROXIEDAUTH +#ifdef LDAP_CONTROL_PROXY_AUTHZ +#define LDAP_CONTROL_PROXIEDAUTH LDAP_CONTROL_PROXY_AUTHZ +#else +#define LDAP_CONTROL_PROXIEDAUTH "2.16.840.1.113730.3.4.18" /* version 2 */ +#endif +#endif + +#ifndef LDAP_CONTROL_AUTH_REQUEST +#define LDAP_CONTROL_AUTH_REQUEST "2.16.840.1.113730.3.4.16" +#endif + +#ifndef LDAP_SORT_CONTROL_MISSING +#define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 (server side sort extn) */ +#endif +#ifndef LDAP_INDEX_RANGE_ERROR +#define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 (VLV extn) */ +#endif + +/* openldap does not use this */ +#ifndef LBER_OVERFLOW +#define LBER_OVERFLOW ((ber_tag_t) -3) /* 0xfffffffdU */ +#endif /* * Sequential access types @@ -3400,6 +3525,98 @@ int slapi_re_subs( Slapi_Regex *re_handle, const char *subject, const char *src, */ void slapi_re_free(Slapi_Regex *re_handle); +/* wrap non-portable LDAP API functions */ +void slapi_ldap_value_free(char **vals); +int slapi_ldap_count_values(char **vals); +int slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *secure); +const char *slapi_urlparse_err2string(int err); +int slapi_ldap_get_lderrno(LDAP *ld, char **m, char **s); +#ifndef LDIF_OPT_NOWRAP +#define LDIF_OPT_NOWRAP 0x01UL +#endif +#ifndef LDIF_OPT_VALUE_IS_URL +#define LDIF_OPT_VALUE_IS_URL 0x02UL +#endif +#ifndef LDIF_OPT_MINIMAL_ENCODING +#define LDIF_OPT_MINIMAL_ENCODING 0x04UL +#endif +void slapi_ldif_put_type_and_value_with_options( char **out, const char *t, const char *val, int vlen, unsigned long options ); + +#if defined(USE_OPENLDAP) +/* + * UTF-8 routines (should these move into libnls?) + */ +/* number of bytes in character */ +int ldap_utf8len( const char* ); +/* find next character */ +char *ldap_utf8next( char* ); +/* find previous character */ +char *ldap_utf8prev( char* ); +/* copy one character */ +int ldap_utf8copy( char* dst, const char* src ); +/* total number of characters */ +size_t ldap_utf8characters( const char* ); +/* get one UCS-4 character, and move *src to the next character */ +unsigned long ldap_utf8getcc( const char** src ); +/* UTF-8 aware strtok_r() */ +char *ldap_utf8strtok_r( char* src, const char* brk, char** next); + +/* like isalnum(*s) in the C locale */ +int ldap_utf8isalnum( char* s ); +/* like isalpha(*s) in the C locale */ +int ldap_utf8isalpha( char* s ); +/* like isdigit(*s) in the C locale */ +int ldap_utf8isdigit( char* s ); +/* like isxdigit(*s) in the C locale */ +int ldap_utf8isxdigit(char* s ); +/* like isspace(*s) in the C locale */ +int ldap_utf8isspace( char* s ); + +#define LDAP_UTF8LEN(s) ((0x80 & *(unsigned char*)(s)) ? ldap_utf8len (s) : 1) +#define LDAP_UTF8NEXT(s) ((0x80 & *(unsigned char*)(s)) ? ldap_utf8next(s) : ( s)+1) +#define LDAP_UTF8INC(s) ((0x80 & *(unsigned char*)(s)) ? s=ldap_utf8next(s) : ++s) + +#define LDAP_UTF8PREV(s) ldap_utf8prev(s) +#define LDAP_UTF8DEC(s) (s=ldap_utf8prev(s)) + +#define LDAP_UTF8COPY(d,s) ((0x80 & *(unsigned char*)(s)) ? ldap_utf8copy(d,s) : ((*(d) = *(s)), 1)) +#define LDAP_UTF8GETCC(s) ((0x80 & *(unsigned char*)(s)) ? ldap_utf8getcc (&s) : *s++) +#define LDAP_UTF8GETC(s) ((0x80 & *(unsigned char*)(s)) ? ldap_utf8getcc ((const char**)&s) : *s++) +#endif /* USE_OPENLDAP */ + +/* by default will allow dups */ +char **slapi_str2charray( char *str, char *brkstr ); +/* + * extended version of str2charray lets you disallow + * duplicate values into the array. + */ +char **slapi_str2charray_ext( char *str, char *brkstr, int allow_dups ); + +#ifndef LDAP_PORT_MAX +#define LDAP_PORT_MAX 65535 /* API extension */ +#endif + +#ifndef LDAP_ALL_USER_ATTRS +#ifdef LDAP_ALL_USER_ATTRIBUTES +#define LDAP_ALL_USER_ATTRS LDAP_ALL_USER_ATTRIBUTES +#else +#define LDAP_ALL_USER_ATTRS "*" +#endif +#endif + +#ifndef LDAP_SASL_EXTERNAL +#define LDAP_SASL_EXTERNAL "EXTERNAL" /* TLS/SSL extension */ +#endif + +#ifndef LBER_SOCKET +#ifdef LBER_SOCKET_T +#define LBER_SOCKET LBER_SOCKET_T +#else +#define LBER_SOCKET int +#endif +#endif + + #ifdef __cplusplus } #endif diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index ab3430a4..85c45896 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -800,8 +800,6 @@ void charray_free( char **array ); int charray_inlist( char **a, char *s ); int charray_utf8_inlist( char **a, char *s ); char ** charray_dup( char **a ); -char ** str2charray( char *str, char *brkstr ); -char ** str2charray_ext( char *str, char *brkstr, int allow_dups ); int charray_remove(char **a, const char *s, int freeit); char ** cool_charray_dup( char **a ); void cool_charray_free( char **array ); diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c index 6da15a02..5b107990 100644 --- a/ldap/servers/slapd/ssl.c +++ b/ldap/servers/slapd/ssl.c @@ -68,9 +68,12 @@ #include "svrcore.h" #include "fe.h" -#include <ldap_ssl.h> /* ldapssl_client_init */ #include "certdb.h" +#if !defined(USE_OPENLDAP) +#include "ldap_ssl.h" +#endif + /* For IRIX... */ #ifndef MAXPATHLEN #define MAXPATHLEN 1024 @@ -1241,6 +1244,21 @@ slapd_SSL_client_auth (LDAP* ld) "(no password). (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", errorCode, slapd_pr_strerror(errorCode)); } else { +#if defined(USE_OPENLDAP) + rc = ldap_set_option(ld, LDAP_OPT_X_TLS_KEYFILE, SERVER_KEY_NAME); + if (rc) { + slapd_SSL_warn("SSL client authentication cannot be used " + "unable to set the key to use to %s", SERVER_KEY_NAME); + } + rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CERTFILE, cert_name); + if (rc) { + slapd_SSL_warn("SSL client authentication cannot be used " + "unable to set the cert to use to %s", cert_name); + } + /* not sure what else needs to be done for client auth - don't + currently have a way to pass in the password to use to unlock + the keydb - nor a way to disable caching */ +#else /* !USE_OPENLDAP */ rc = ldapssl_enable_clientauth (ld, SERVER_KEY_NAME, pw, cert_name); if (rc != 0) { errorCode = PR_GetError(); @@ -1258,6 +1276,7 @@ slapd_SSL_client_auth (LDAP* ld) ldapssl_set_option(ld, SSL_NO_CACHE, PR_TRUE); } +#endif } } diff --git a/ldap/servers/slapd/time.c b/ldap/servers/slapd/time.c index c5a83330..12e02ce6 100644 --- a/ldap/servers/slapd/time.c +++ b/ldap/servers/slapd/time.c @@ -55,7 +55,7 @@ #include "slap.h" #include "fe.h" -LDAP_API(unsigned long) strntoul( char *from, size_t len, int base ); +unsigned long strntoul( char *from, size_t len, int base ); #define mktime_r(from) mktime (from) /* possible bug: is this thread-safe? */ static time_t currenttime; @@ -265,7 +265,7 @@ write_localTime (time_t from, struct berval* into) * * Returns: See strtoul(3). */ -LDAP_API(unsigned long) strntoul( char *from, size_t len, int base ) +unsigned long strntoul( char *from, size_t len, int base ) { unsigned long result; char c = from[ len ]; diff --git a/ldap/servers/slapd/tools/ldaptool.h b/ldap/servers/slapd/tools/ldaptool.h index e85c4d0f..1aaf0edc 100644 --- a/ldap/servers/slapd/tools/ldaptool.h +++ b/ldap/servers/slapd/tools/ldaptool.h @@ -100,12 +100,6 @@ extern int getopt (int argc, char *const *argv, const char *optstring); #include <ldaplog.h> #include <ldif.h> -#if defined(NET_SSL) -#include <ldap_ssl.h> -#endif - -#include <ldappr.h> - #ifdef __cplusplus extern "C" { #endif @@ -119,7 +113,6 @@ extern "C" { #define LDAPTOOL_DEFSEP "=" /* used by ldapcmp and ldapsearch */ #define LDAPTOOL_DEFHOST "localhost" -#define LDAPTOOL_DEFSSLSTRENGTH LDAPSSL_AUTH_CERT #define LDAPTOOL_DEFCERTDBPATH "." #define LDAPTOOL_DEFKEYDBPATH "." #define LDAPTOOL_DEFREFHOPLIMIT 5 diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c b/ldap/servers/slapd/tools/ldclt/ldapfct.c index e58a41e1..a2382b7f 100644 --- a/ldap/servers/slapd/tools/ldclt/ldapfct.c +++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c @@ -256,10 +256,11 @@ dd/mm/yy | Author | Comments #include <sasl.h> #include "ldaptool-sasl.h" +#if !defined(USE_OPENLDAP) #include <ldap_ssl.h> /* ldapssl_init(), etc... */ +#endif - - +#include <prprf.h> @@ -463,7 +464,27 @@ buildNewBindDN ( +#if defined(USE_OPENLDAP) +int +refRebindProc( + LDAP *ldapCtx, + const char *url, + ber_tag_t request, + ber_int_t msgid, + void *arg +) +{ + thread_context *tttctx; + struct berval cred; + + tttctx = (thread_context *)arg; + cred.bv_val = tttctx->bufPasswd; + cred.bv_len = strlen(tttctx->bufPasswd); + return ldap_sasl_bind_s(ldapCtx, tttctx->bufBindDN, LDAP_SASL_SIMPLE, + &cred, NULL, NULL, NULL); +} +#else /* !USE_OPENLDAP */ /* New function */ /*JLS 08-03-01*/ /* **************************************************************************** FUNCTION : refRebindProc @@ -503,6 +524,7 @@ refRebindProc ( return (LDAP_SUCCESS); } +#endif /* !USE_OPENLDAP */ @@ -589,6 +611,7 @@ connectToServer ( int ret; /* Return value */ LBER_SOCKET fd; /* LDAP cnx's fd */ int v2v3; /* LDAP version used */ + struct berval cred = {0, NULL}; /* * Maybe close the connection ? @@ -629,8 +652,8 @@ connectToServer ( if (close ((int)fd) < 0) { perror ("ldctx"); - printf ("ldclt[%d]: T%03d: cannot close(fd=%ld), error=%d (%s)\n", - mctx.pid, tttctx->thrdNum, fd, errno, strerror (errno)); + printf ("ldclt[%d]: T%03d: cannot close(fd=%d), error=%d (%s)\n", + mctx.pid, tttctx->thrdNum, (int)fd, errno, strerror (errno)); return (-1); } } @@ -642,7 +665,7 @@ connectToServer ( * But don't be afraid, the UNBIND operation never reach the * server that will only see a suddent socket disconnection. */ - ret = ldap_unbind (tttctx->ldapCtx); + ret = ldap_unbind_ext (tttctx->ldapCtx, NULL, NULL); if (ret != LDAP_SUCCESS) { fprintf (stderr, "ldclt[%d]: T%03d: cannot ldap_unbind(), error=%d (%s)\n", @@ -660,6 +683,27 @@ connectToServer ( */ if (tttctx->ldapCtx == NULL) { + const char *mech = LDAP_SASL_SIMPLE; + const char *binddn = NULL; + const char *passwd = NULL; +#if defined(USE_OPENLDAP) + char *ldapurl = NULL; +#endif + +#if defined(USE_OPENLDAP) + ldapurl = PR_smprintf("ldap%s://%s:%d/", + (mctx.mode & SSL) ? "s" : "", + mctx.hostname, mctx.port); + if ((ret = ldap_initialize(&tttctx->ldapCtx, ldapurl))) { + printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n", + mctx.pid, tttctx->thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret)); + fflush (stdout); + PR_smprintf_free(ldapurl); + return (-1); + } + PR_smprintf_free(ldapurl); + ldapurl = NULL; +#else /* !USE_OPENLDAP */ /* * SSL is enabled ? */ @@ -720,6 +764,18 @@ connectToServer ( return (-1); } } +#endif /* !USE_OPENLDAP */ + + if (mctx.mode & CLTAUTH) { + mech = "EXTERNAL"; + binddn = ""; + passwd = NULL; + } else { + binddn = tttctx->bufBindDN; + passwd = tttctx->bufPasswd; + cred.bv_val = (char *)passwd; + cred.bv_len = strlen(passwd); + } if (mctx.mode & LDAP_V2) v2v3 = LDAP_VERSION2; @@ -849,14 +905,21 @@ connectToServer ( perror ("malloc"); exit (LDAP_NO_MEMORY); } - +#if defined(USE_OPENLDAP) + ret = ldap_sasl_interactive_bind_s( tttctx->ldapCtx, mctx.bindDN, mctx.sasl_mech, + NULL, NULL, mctx.sasl_flags, + ldaptool_sasl_interact, defaults ); +#else ret = ldap_sasl_interactive_bind_ext_s( tttctx->ldapCtx, mctx.bindDN, mctx.sasl_mech, NULL, NULL, mctx.sasl_flags, ldaptool_sasl_interact, defaults, NULL ); +#endif if (ret != LDAP_SUCCESS ) { tttctx->binded = 0; - if (!(mctx.mode & QUIET)) - ldap_perror( tttctx->ldapCtx, "Bind Error" ); + if (!(mctx.mode & QUIET)) { + fprintf(stderr, "Error: could not bind: %d:%s\n", + ret, my_ldap_err2string(ret)); + } if (addErrorStat (ret) < 0) return (-1); } else { @@ -868,15 +931,17 @@ connectToServer ( if (((mctx.bindDN != NULL) || (mctx.mod2 & M2_RNDBINDFILE)) && /*03-05-01*/ ((!(tttctx->binded)) || (mctx.mode & BIND_EACH_OPER))) { + struct berval *servercredp = NULL; + if (buildNewBindDN (tttctx) < 0) /*JLS 05-01-01*/ return (-1); /*JLS 05-01-01*/ if (mctx.mode & VERY_VERBOSE) printf ("ldclt[%d]: T%03d: Before ldap_simple_bind_s (%s, %s)\n", mctx.pid, tttctx->thrdNum, tttctx->bufBindDN, mctx.passwd?tttctx->bufPasswd:"NO PASSWORD PROVIDED"); - ret = ldap_simple_bind_s (tttctx->ldapCtx, - tttctx->bufBindDN, /*JLS 05-01-01*/ - mctx.passwd?tttctx->bufPasswd:"NO PASSWORD PROVIDED"); + ret = ldap_sasl_bind_s (tttctx->ldapCtx, tttctx->bufBindDN, LDAP_SASL_SIMPLE, + &cred, NULL, NULL, &servercredp); /*JLS 05-01-01*/ + ber_bvfree(servercredp); if (mctx.mode & VERY_VERBOSE) printf ("ldclt[%d]: T%03d: After ldap_simple_bind_s (%s, %s)\n", mctx.pid, tttctx->thrdNum, tttctx->bufBindDN, @@ -1821,9 +1886,31 @@ createMissingNodes ( */ if (cnx == NULL) { + const char *mech = LDAP_SASL_SIMPLE; + const char *binddn = NULL; + const char *passwd = NULL; + struct berval cred = {0, NULL}; +#if defined(USE_OPENLDAP) + char *ldapurl = NULL; +#endif + if (mctx.mode & VERY_VERBOSE) /*JLS 14-12-00*/ printf ("ldclt[%d]: T%03d: must connect to the server.\n", mctx.pid, tttctx->thrdNum); +#if defined(USE_OPENLDAP) + ldapurl = PR_smprintf("ldap%s://%s:%d/", + (mctx.mode & SSL) ? "s" : "", + mctx.hostname, mctx.port); + if ((ret = ldap_initialize(&tttctx->ldapCtx, ldapurl))) { + printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n", + mctx.pid, tttctx->thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret)); + fflush (stdout); + PR_smprintf_free(ldapurl); + return (-1); + } + PR_smprintf_free(ldapurl); + ldapurl = NULL; +#else /* !USE_OPENLDAP */ /* * SSL is enabled ? */ @@ -1879,6 +1966,18 @@ createMissingNodes ( return (-1); } } +#endif /* !USE_OPENLDAP */ + + if (mctx.mode & CLTAUTH) { + mech = "EXTERNAL"; + binddn = ""; + passwd = NULL; + } else { + binddn = tttctx->bufBindDN; + passwd = tttctx->bufPasswd; + cred.bv_val = (char *)passwd; + cred.bv_len = strlen(passwd); + } if (mctx.mode & LDAP_V2) v2v3 = LDAP_VERSION2; @@ -1897,30 +1996,15 @@ createMissingNodes ( /* * Bind to the server */ - /* - * for SSL client authentication, SASL BIND is used - */ - if (mctx.mode & CLTAUTH) - { - ret = ldap_sasl_bind_s (tttctx->ldapCtx, "", "EXTERNAL", NULL, NULL, NULL, + ret = ldap_sasl_bind_s (tttctx->ldapCtx, binddn, mech, &cred, NULL, NULL, NULL); if (ret != LDAP_SUCCESS) { - printf ("ldclt[%d]: T%03d: Cannot ldap_sasl_bind_s, error=%d (%s)\n", - mctx.pid, tttctx->thrdNum, ret, my_ldap_err2string (ret)); - fflush (stdout); - tttctx->exitStatus = EXIT_NOBIND; - if (addErrorStat (ret) < 0) - return (-1); - return (-1); - } - } else { - ret = ldap_simple_bind_s (cnx, tttctx->bufBindDN, tttctx->bufPasswd); - if (ret != LDAP_SUCCESS) - { - printf ("ldclt[%d]: T%03d: Cannot ldap_simple_bind_s (%s, %s), error=%d (%s)\n", + printf ("ldclt[%d]: T%03d: Cannot bind using mech [%s] (%s, %s), error=%d (%s)\n", mctx.pid, tttctx->thrdNum, - tttctx->bufBindDN, tttctx->bufPasswd, + mech ? mech : "SIMPLE", + tttctx->bufBindDN ? tttctx->bufBindDN : "", + tttctx->bufPasswd ? tttctx->bufPasswd : "", ret, my_ldap_err2string (ret)); fflush (stdout); tttctx->exitStatus = EXIT_NOBIND; /*JLS 25-08-00*/ @@ -1929,7 +2013,6 @@ createMissingNodes ( return (-1); } } - } /* * Create the entry @@ -1951,7 +2034,7 @@ createMissingNodes ( * Add the entry * If it doesn't work, we will recurse on the nodeDN */ - ret = ldap_add_s (cnx, nodeDN, attrs); + ret = ldap_add_ext_s (cnx, nodeDN, attrs, NULL, NULL); if ((ret != LDAP_SUCCESS) && (ret != LDAP_ALREADY_EXISTS)) { if (ret == LDAP_NO_SUCH_OBJECT) @@ -2015,7 +2098,7 @@ createMissingNodes ( if (freeAttrib (attrs) < 0) return (-1); - ret = ldap_unbind (cnx); + ret = ldap_unbind_ext (cnx, NULL, NULL); if (ret != LDAP_SUCCESS) { fprintf (stderr, "ldclt[%d]: T%03d: cannot ldap_unbind(), error=%d (%s)\n", @@ -2775,7 +2858,7 @@ doAddEntry ( retry = 1; while (retry) { - ret = ldap_add_s (tttctx->ldapCtx, newDn, attrs); + ret = ldap_add_ext_s (tttctx->ldapCtx, newDn, attrs, NULL, NULL); if (ret != LDAP_SUCCESS) { if (!((mctx.mode & QUIET) && ignoreError (ret))) @@ -2871,6 +2954,8 @@ doAddEntry ( } else { + int msgid = 0; + if ((mctx.mode & VERBOSE) && (tttctx->asyncHit == 1) && (!(mctx.mode & SUPER_QUIET))) @@ -2887,7 +2972,7 @@ doAddEntry ( if (buildNewEntry (tttctx, newDn, attrs) < 0) return (-1); - ret = ldap_add (tttctx->ldapCtx, newDn, attrs); + ret = ldap_add_ext (tttctx->ldapCtx, newDn, attrs, NULL, NULL, &msgid); if (ret < 0) { if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0) @@ -2929,7 +3014,7 @@ doAddEntry ( /* * Memorize the operation */ - if (msgIdAdd (tttctx, ret, newDn, newDn, attrs) < 0) + if (msgIdAdd (tttctx, msgid, newDn, newDn, attrs) < 0) return (-1); if (incrementNbOpers (tttctx) < 0) return (-1); @@ -3160,7 +3245,7 @@ doDeleteEntry ( strcat (delDn, ","); strcat (delDn, tttctx->bufBaseDN); - ret = ldap_delete_s (tttctx->ldapCtx, delDn); + ret = ldap_delete_ext_s (tttctx->ldapCtx, delDn, NULL, NULL); if (ret != LDAP_SUCCESS) { if (!((mctx.mode & QUIET) && ignoreError (ret))) @@ -3223,6 +3308,8 @@ doDeleteEntry ( } else { + int msgid = 0; + if ((mctx.mode & VERBOSE) && (tttctx->asyncHit == 1) && (!(mctx.mode & SUPER_QUIET))) @@ -3243,7 +3330,7 @@ doDeleteEntry ( strcat (delDn, ","); strcat (delDn, tttctx->bufBaseDN); - ret = ldap_delete (tttctx->ldapCtx, delDn); + ret = ldap_delete_ext (tttctx->ldapCtx, delDn, NULL, NULL, &msgid); if (ret < 0) { if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0) @@ -3389,9 +3476,9 @@ doExactSearch ( */ if (!(mctx.mode & ASYNC)) { - ret = ldap_search_s (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope, + ret = ldap_search_ext_s (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope, tttctx->bufFilter, attrlist, /*JLS 15-03-01*/ - mctx.attrsonly, &res); /*JLS 03-01-01*/ + mctx.attrsonly, NULL, NULL, NULL, -1, &res); /*JLS 03-01-01*/ if (ret != LDAP_SUCCESS) { if (!((mctx.mode & QUIET) && ignoreError (ret))) @@ -3493,6 +3580,8 @@ doExactSearch ( } else { + int msgid = 0; + if ((mctx.mode & VERBOSE) && (tttctx->asyncHit == 1) && (!(mctx.mode & SUPER_QUIET))) @@ -3503,9 +3592,9 @@ doExactSearch ( fflush (stdout); } - ret = ldap_search (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope, + ret = ldap_search_ext (tttctx->ldapCtx, tttctx->bufBaseDN, mctx.scope, tttctx->bufFilter, attrlist, /*JLS 15-03-01*/ - mctx.attrsonly); /*JLS 03-01-01*/ + mctx.attrsonly, NULL, NULL, NULL, -1, &msgid); /*JLS 03-01-01*/ if (ret < 0) { if (ldap_get_option (tttctx->ldapCtx, LDAP_OPT_ERROR_NUMBER, &ret) < 0) @@ -3699,7 +3788,7 @@ doAbandon (thread_context *tttctx) if (msgid >= 0) { /* ABANDON the search request immediately */ - (void) ldap_abandon(tttctx->ldapCtx, msgid); + (void) ldap_abandon_ext(tttctx->ldapCtx, msgid, NULL, NULL); } /* diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.c b/ldap/servers/slapd/tools/ldclt/ldclt.c index 5346e241..f98233cc 100644 --- a/ldap/servers/slapd/tools/ldclt/ldclt.c +++ b/ldap/servers/slapd/tools/ldclt/ldclt.c @@ -281,7 +281,9 @@ dd/mm/yy | Author | Comments #include <time.h> /* ctime(), etc... */ /*JLS 18-08-00*/ #include <lber.h> /* ldap C-API BER decl. */ #include <ldap.h> /* ldap C-API decl. */ +#if !defined(USE_OPENLDAP) #include <ldap_ssl.h> /* ldapssl_init(), etc... */ +#endif #ifdef LDAP_H_FROM_QA_WKA #include <proto-ldap.h> /* ldap C-API prototypes */ #endif @@ -1547,6 +1549,7 @@ basicInit (void) } } +#if !defined(USE_OPENLDAP) /* * SSL is enabled ? */ @@ -1577,6 +1580,7 @@ basicInit (void) } } } +#endif /* !defined(USE_OPENLDAP) */ /* * Specific scenarios initialization... diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.h b/ldap/servers/slapd/tools/ldclt/ldclt.h index 0ed8ef8e..8fa03d8b 100644 --- a/ldap/servers/slapd/tools/ldclt/ldclt.h +++ b/ldap/servers/slapd/tools/ldclt/ldclt.h @@ -327,20 +327,54 @@ dd/mm/yy | Author | Comments #ifdef SOLARIS_LIBLDAP /*JLS 19-09-00*/ #define WORKAROUND_4197228 1 /*JLS 19-09-00*/ #else /*JLS 19-09-00*/ +#ifndef LDAP_REQ_BIND #define LDAP_REQ_BIND 0x60 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_UNBIND #define LDAP_REQ_UNBIND 0x42 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_SEARCH #define LDAP_REQ_SEARCH 0x63 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_MODIFY #define LDAP_REQ_MODIFY 0x66 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_ADD #define LDAP_REQ_ADD 0x68 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_DELETE #define LDAP_REQ_DELETE 0x4a /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_MODRDN #define LDAP_REQ_MODRDN 0x6c /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_COMPARE #define LDAP_REQ_COMPARE 0x6e /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_ABANDON #define LDAP_REQ_ABANDON 0x50 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_EXTENDED #define LDAP_REQ_EXTENDED 0x77 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_UNBIND_30 #define LDAP_REQ_UNBIND_30 0x62 /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_DELETE_30 #define LDAP_REQ_DELETE_30 0x6a /*JLS 19-09-00*/ +#endif +#ifndef LDAP_REQ_ABANDON_30 #define LDAP_REQ_ABANDON_30 0x70 /*JLS 19-09-00*/ #endif /*JLS 19-09-00*/ +#endif + +#ifndef LBER_SOCKET +#ifdef LBER_SOCKET_T +#define LBER_SOCKET LBER_SOCKET_T +#else +#define LBER_SOCKET int +#endif +#endif /* * This structure is the internal representation of an image diff --git a/ldap/servers/slapd/tools/ldclt/scalab01.c b/ldap/servers/slapd/tools/ldclt/scalab01.c index 3dc2bda8..595df0ff 100644 --- a/ldap/servers/slapd/tools/ldclt/scalab01.c +++ b/ldap/servers/slapd/tools/ldclt/scalab01.c @@ -91,8 +91,10 @@ dd/mm/yy | Author | Comments #include <lber.h> /* ldap C-API BER declarations */ #include <ldap.h> /* ldap C-API declarations */ +#if !defined(USE_OPENLDAP) #include <ldap_ssl.h> /* ldapssl_init(), etc... */ - +#endif +#include <prprf.h> #include "port.h" /* Portability definitions */ #include "ldclt.h" /* This tool's include file */ #include "utils.h" /* Utilities functions */ @@ -509,8 +511,28 @@ scalab01_connectSuperuser (void) { int ret; /* Return value */ int v2v3; /* LDAP version used */ - char bindDN [MAX_DN_LENGTH]; /* To bind */ + char bindDN [MAX_DN_LENGTH] = {0}; /* To bind */ + const char *mech = LDAP_SASL_SIMPLE; + struct berval cred = {0, NULL}; + struct berval *servercredp = NULL; +#if defined(USE_OPENLDAP) + char *ldapurl = NULL; +#endif +#if defined(USE_OPENLDAP) + ldapurl = PR_smprintf("ldap%s://%s:%d/", + (mctx.mode & SSL) ? "s" : "", + mctx.hostname, mctx.port); + if ((ret = ldap_initialize(&s1ctx.ldapCtx, ldapurl))) { + printf ("ldclt[%d]: ctrl: Cannot ldap_initialize (%s), errno=%d ldaperror=%d:%s\n", + mctx.pid, ldapurl, errno, ret, my_ldap_err2string(ret)); + fflush (stdout); + PR_smprintf_free(ldapurl); + return (-1); + } + PR_smprintf_free(ldapurl); + ldapurl = NULL; +#else /* !USE_OPENLDAP */ /* * Create the LDAP context */ @@ -571,6 +593,17 @@ scalab01_connectSuperuser (void) return (-1); } } +#endif /* !USE_OPENLDAP */ + + if (mctx.mode & CLTAUTH) { + mech = "EXTERNAL"; + } else { + strcpy (bindDN, SCALAB01_SUPER_USER_RDN); + strcat (bindDN, ","); + strcat (bindDN, mctx.baseDN); + cred.bv_val = SCALAB01_SUPER_USER_PASSWORD; + cred.bv_len = strlen(cred.bv_val); + } /* * Set the LDAP version and other options... @@ -590,49 +623,21 @@ scalab01_connectSuperuser (void) } /*JLS 14-03-01*/ - /* - * Now we could bind - */ - /* - * for SSL client authentication, SASL BIND is used - */ - if (mctx.mode & CLTAUTH) - { - if (mctx.mode & VERY_VERBOSE) - printf ("ldclt[%d]: ctrl: Before ldap_sasl_bind_s\n", mctx.pid); - ret = ldap_sasl_bind_s (s1ctx.ldapCtx, "", "EXTERNAL", NULL, NULL, NULL, - NULL); - if (mctx.mode & VERY_VERBOSE) - printf ("ldclt[%d]: ctrl: After ldap_sasl_bind_s\n", mctx.pid); - if (ret != LDAP_SUCCESS) - { - printf ("ldclt[%d]: ctrl: Cannot ldap_sasl_bind_s, error=%d (%s)\n", - mctx.pid, ret, my_ldap_err2string (ret)); - fflush (stdout); - return (-1); - } - } - else + if (mctx.mode & VERY_VERBOSE) + printf ("ldclt[%d]: ctrl: Before bind mech %s (%s , %s)\n", + mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD); + ret = ldap_sasl_bind_s (s1ctx.ldapCtx, bindDN, mech, &cred, NULL, NULL, &servercredp); + ber_bvfree(servercredp); + if (mctx.mode & VERY_VERBOSE) + printf ("ldclt[%d]: ctrl: After bind mech %s (%s, %s)\n", + mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD); + if (ret != LDAP_SUCCESS) { - strcpy (bindDN, SCALAB01_SUPER_USER_RDN); - strcat (bindDN, ","); - strcat (bindDN, mctx.baseDN); - if (mctx.mode & VERY_VERBOSE) - printf ("ldclt[%d]: ctrl: Before ldap_simple_bind_s (%s , %s)\n", - mctx.pid, bindDN, SCALAB01_SUPER_USER_PASSWORD); - ret = ldap_simple_bind_s (s1ctx.ldapCtx, - bindDN, SCALAB01_SUPER_USER_PASSWORD); - if (mctx.mode & VERY_VERBOSE) - printf ("ldclt[%d]: ctrl: After ldap_simple_bind_s (%s, %s)\n", - mctx.pid, bindDN, SCALAB01_SUPER_USER_PASSWORD); - if (ret != LDAP_SUCCESS) - { - printf("ldclt[%d]: ctrl: Cannot ldap_simple_bind_s (%s, %s), error=%d (%s)\n", - mctx.pid, bindDN, SCALAB01_SUPER_USER_PASSWORD, - ret, my_ldap_err2string (ret)); - fflush (stdout); - return (-1); - } + printf("ldclt[%d]: ctrl: Cannot bind mech %s (%s, %s), error=%d (%s)\n", + mctx.pid, mech ? mech : "SIMPLE", bindDN, SCALAB01_SUPER_USER_PASSWORD, + ret, my_ldap_err2string (ret)); + fflush (stdout); + return (-1); } /* @@ -676,7 +681,6 @@ readAttrValue ( LDAPMessage *cur; /* Current message */ BerElement *ber; /* To decode the response */ char *aname; /* Current attribute name */ - char **vals; /* Attribute value returned */ char *filter; /* Filter used for searching */ /* @@ -686,8 +690,8 @@ readAttrValue ( attrs[1] = NULL; filter = (char *)malloc((4+strlen(attname))*sizeof(char)); sprintf(filter, "(%s=*)", attname); - ret = ldap_search_s (ldapCtx, dn, LDAP_SCOPE_BASE, - filter, attrs, 0, &res); + ret = ldap_search_ext_s (ldapCtx, dn, LDAP_SCOPE_BASE, + filter, attrs, 0, NULL, NULL, NULL, -1, &res); if (filter != NULL) free(filter); if (ret != LDAP_SUCCESS) { @@ -712,7 +716,8 @@ readAttrValue ( */ if (!strcmp (aname, attname)) { - vals = ldap_get_values (ldapCtx, cur, aname); + struct berval **vals; + vals = ldap_get_values_len (ldapCtx, cur, aname); if (vals == NULL) { printf ("ldclt[%d]: %s: no value for %s in %s\n", @@ -720,8 +725,9 @@ readAttrValue ( fflush (stdout); return (-1); } - strcpy (value, vals[0]); - ldap_value_free (vals); + strncpy (value, vals[0]->bv_val, vals[0]->bv_len); + value[vals[0]->bv_len] = '\0'; + ldap_value_free_len (vals); } /* @@ -736,7 +742,7 @@ readAttrValue ( * Next entry - shouldn't happen in theory */ if (ber != NULL) - ldap_ber_free (ber, 0); + ber_free (ber, 0); cur = ldap_next_entry (ldapCtx, cur); } ldap_msgfree (res); /* Free the response */ diff --git a/ldap/servers/slapd/tools/ldif.c b/ldap/servers/slapd/tools/ldif.c index bf100539..892b6ee2 100644 --- a/ldap/servers/slapd/tools/ldif.c +++ b/ldap/servers/slapd/tools/ldif.c @@ -42,6 +42,7 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include <memory.h> #include <sys/types.h> #if defined( _WINDOWS ) || defined( _WIN32 ) @@ -58,6 +59,24 @@ int ldap_syslog; int ldap_syslog_level; +#if defined(USE_OPENLDAP) +static char * +ldif_type_and_value(const char *type, const char *val, int vlen) +{ + char *buf, *p; + int tlen; + + tlen = strlen( type ); + if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) != + NULL ) { + p = buf; + ldif_sput( &p, LDIF_PUT_VALUE, type, val, vlen ); + *p = '\0'; + } + + return( buf ); +} +#endif static void display_usage( char *name ) diff --git a/ldap/servers/slapd/tools/pwenc.c b/ldap/servers/slapd/tools/pwenc.c index dba107a3..c03cfdec 100644 --- a/ldap/servers/slapd/tools/pwenc.c +++ b/ldap/servers/slapd/tools/pwenc.c @@ -61,7 +61,6 @@ #include <ctype.h> #include <stdlib.h> #include "ldap.h" -#include "ldif.h" #include "../slapi-plugin.h" #include "../slap.h" #include <nspr.h> diff --git a/ldap/servers/slapd/tools/rsearch/addthread.c b/ldap/servers/slapd/tools/rsearch/addthread.c index d87c5a53..417a4c19 100644 --- a/ldap/servers/slapd/tools/rsearch/addthread.c +++ b/ldap/servers/slapd/tools/rsearch/addthread.c @@ -53,6 +53,13 @@ #include "addthread.h" #include "infadd.h" +#ifndef LBER_SOCKET +#ifdef LBER_SOCKET_T +#define LBER_SOCKET LBER_SOCKET_T +#else +#define LBER_SOCKET int +#endif +#endif /* local data for a search thread */ struct _addthread { diff --git a/ldap/servers/slapd/tools/rsearch/searchthread.c b/ldap/servers/slapd/tools/rsearch/searchthread.c index 443419c0..38d5d593 100644 --- a/ldap/servers/slapd/tools/rsearch/searchthread.c +++ b/ldap/servers/slapd/tools/rsearch/searchthread.c @@ -57,6 +57,14 @@ #include "rsearch.h" #include "searchthread.h" +#ifndef LBER_SOCKET +#ifdef LBER_SOCKET_T +#define LBER_SOCKET LBER_SOCKET_T +#else +#define LBER_SOCKET int +#endif +#endif + /* local data for a search thread */ struct _searchthread { PRUint32 searchCount; diff --git a/ldap/servers/slapd/utf8.c b/ldap/servers/slapd/utf8.c new file mode 100644 index 00000000..df092024 --- /dev/null +++ b/ldap/servers/slapd/utf8.c @@ -0,0 +1,310 @@ +/** BEGIN COPYRIGHT BLOCK + * This Program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA. + * + * In addition, as a special exception, Red Hat, Inc. gives You the additional + * right to link the code of this Program with code not covered under the GNU + * General Public License ("Non-GPL Code") and to distribute linked combinations + * including the two, subject to the limitations in this paragraph. Non-GPL Code + * permitted under this exception must only link to the code of this Program + * through those well defined interfaces identified in the file named EXCEPTION + * found in the source code files (the "Approved Interfaces"). The files of + * Non-GPL Code may instantiate templates or use macros or inline functions from + * the Approved Interfaces without causing the resulting work to be covered by + * the GNU General Public License. Only Red Hat, Inc. may make changes or + * additions to the list of Approved Interfaces. You must obey the GNU General + * Public License in all respects for all of the Program code and other code used + * in conjunction with the Program except the Non-GPL Code covered by this + * exception. If you modify this file, you may extend this exception to your + * version of the file, but you are not obligated to do so. If you do not wish to + * provide this exception without modification, you must delete this exception + * statement from your version and license this file solely under the GPL without + * exception. + * + * + * END COPYRIGHT BLOCK **/ +/* ***** BEGIN LICENSE BLOCK ***** + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * June 25, 2009 - copied from Mozilla LDAP C SDK - relicensed to use GPLv2 + * with directory server plug-in exception as per the above paragraph + * + * ***** END LICENSE BLOCK ***** */ + +/* the openldap library has utf8 string handling functions, but they + are somewhat different, and not exposed/exported for use outside + of the library - therefore, we just copy these from mozldap when + using openldap +*/ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(USE_OPENLDAP) + +/* uft8.c - misc. utf8 "string" functions. */ +#include "slapi-plugin.h" + +static char UTF8len[64] += {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6}; + +int +ldap_utf8len (const char* s) + /* Return the number of char's in the character at *s. */ +{ + return ldap_utf8next((char*)s) - s; +} + +char* +ldap_utf8next (char* s) + /* Return a pointer to the character immediately following *s. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register unsigned char* next = (unsigned char*)s; + switch (UTF8len [(*next >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + case 6: if ((*++next & 0xC0) != 0x80) break; + case 5: if ((*++next & 0xC0) != 0x80) break; + case 4: if ((*++next & 0xC0) != 0x80) break; + case 3: if ((*++next & 0xC0) != 0x80) break; + case 2: if ((*++next & 0xC0) != 0x80) break; + case 1: ++next; + } + return (char*) next; +} + +char* +ldap_utf8prev (char* s) + /* Return a pointer to the character immediately preceding *s. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register unsigned char* prev = (unsigned char*)s; + unsigned char* limit = prev - 6; + while (((*--prev & 0xC0) == 0x80) && (prev != limit)) { + ; + } + return (char*) prev; +} + +int +ldap_utf8copy (char* dst, const char* src) + /* Copy a character from src to dst; return the number of char's copied. + Handle any valid UTF-8 character, including '\0' and ASCII. + Try to handle a misaligned pointer or a malformed character. + */ +{ + register const unsigned char* s = (const unsigned char*)src; + switch (UTF8len [(*s >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + case 6: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 5: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 4: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 3: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 2: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break; + case 1: *dst = *s++; + } + return s - (const unsigned char*)src; +} + +size_t +ldap_utf8characters (const char* src) + /* Return the number of UTF-8 characters in the 0-terminated array s. */ +{ + register char* s = (char*)src; + size_t n; + for (n = 0; *s; LDAP_UTF8INC(s)) ++n; + return n; +} + +unsigned long +ldap_utf8getcc( const char** src ) +{ + register unsigned long c = 0; + register const unsigned char* s = (const unsigned char*)*src; + switch (UTF8len [(*s >> 2) & 0x3F]) { + case 0: /* erroneous: s points to the middle of a character. */ + c = (*s++) & 0x3F; goto more5; + case 1: c = (*s++); break; + case 2: c = (*s++) & 0x1F; goto more1; + case 3: c = (*s++) & 0x0F; goto more2; + case 4: c = (*s++) & 0x07; goto more3; + case 5: c = (*s++) & 0x03; goto more4; + case 6: c = (*s++) & 0x01; goto more5; + more5: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more4: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more3: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more2: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + more1: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F); + break; + } + *src = (const char*)s; + return c; +} + +char* +ldap_utf8strtok_r( char* sp, const char* brk, char** next) +{ + const char *bp; + unsigned long sc, bc; + char *tok; + + if (sp == NULL && (sp = *next) == NULL) + return NULL; + + /* Skip leading delimiters; roughly, sp += strspn(sp, brk) */ + cont: + sc = LDAP_UTF8GETC(sp); + for (bp = brk; (bc = LDAP_UTF8GETCC(bp)) != 0;) { + if (sc == bc) + goto cont; + } + + if (sc == 0) { /* no non-delimiter characters */ + *next = NULL; + return NULL; + } + tok = LDAP_UTF8PREV(sp); + + /* Scan token; roughly, sp += strcspn(sp, brk) + * Note that brk must be 0-terminated; we stop if we see that, too. + */ + while (1) { + sc = LDAP_UTF8GETC(sp); + bp = brk; + do { + if ((bc = LDAP_UTF8GETCC(bp)) == sc) { + if (sc == 0) { + *next = NULL; + } else { + *next = sp; + *(LDAP_UTF8PREV(sp)) = 0; + } + return tok; + } + } while (bc != 0); + } + /* NOTREACHED */ +} + +int +ldap_utf8isalnum( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= 'A' && c <= 'Z') return 1; + if (c >= 'a' && c <= 'z') return 1; + if (c >= '0' && c <= '9') return 1; + return 0; +} + +int +ldap_utf8isalpha( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= 'A' && c <= 'Z') return 1; + if (c >= 'a' && c <= 'z') return 1; + return 0; +} + +int +ldap_utf8isdigit( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= '0' && c <= '9') return 1; + return 0; +} + +int +ldap_utf8isxdigit( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return 0; + if (c >= '0' && c <= '9') return 1; + if (c >= 'A' && c <= 'F') return 1; + if (c >= 'a' && c <= 'f') return 1; + return 0; +} + +int +ldap_utf8isspace( char* s ) +{ + register unsigned char *c = (unsigned char*)s; + int len = ldap_utf8len(s); + + if (len == 0) { + return 0; + } else if (len == 1) { + switch (*c) { + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x20: + return 1; + default: + return 0; + } + } else if (len == 2) { + if (*c == 0xc2) { + return *(c+1) == 0x80; + } + } else if (len == 3) { + if (*c == 0xE2) { + c++; + if (*c == 0x80) { + c++; + return (*c>=0x80 && *c<=0x8a); + } + } else if (*c == 0xE3) { + return (*(c+1)==0x80) && (*(c+2)==0x80); + } else if (*c==0xEF) { + return (*(c+1)==0xBB) && (*(c+2)==0xBF); + } + return 0; + } + + /* should never reach here */ + return 0; +} + +#endif /* USE_OPENLDAP */ diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c index 672eff1d..2f55ee49 100644 --- a/ldap/servers/slapd/util.c +++ b/ldap/servers/slapd/util.c @@ -55,8 +55,6 @@ #include "prtime.h" #include "prinrval.h" #include "snmp_collator.h" -#include <ldap_ssl.h> -#include <ldappr.h> #define UTIL_ESCAPE_NONE 0 #define UTIL_ESCAPE_HEX 1 @@ -836,1235 +834,3 @@ slapd_comp_path(char *p0, char *p1) slapi_ch_free_string(&norm_p1); return rval; } - -#ifdef MEMPOOL_EXPERIMENTAL -void _free_wrapper(void *ptr) -{ - slapi_ch_free(&ptr); -} -#endif - -/* - * Function: slapi_ldap_unbind() - * Purpose: release an LDAP session obtained from a call to slapi_ldap_init(). - */ -void -slapi_ldap_unbind( LDAP *ld ) -{ - if ( ld != NULL ) { - ldap_unbind( ld ); - } -} - -const char * -slapi_urlparse_err2string( int err ) -{ - const char *s="internal error"; - - switch( err ) { - case 0: - s = "no error"; - break; - case LDAP_URL_ERR_NOTLDAP: - s = "missing ldap:// or ldaps:// or ldapi://"; - break; - case LDAP_URL_ERR_NODN: - s = "missing suffix"; - break; - case LDAP_URL_ERR_BADSCOPE: - s = "invalid search scope"; - break; - case LDAP_URL_ERR_MEM: - s = "unable to allocate memory"; - break; - case LDAP_URL_ERR_PARAM: - s = "bad parameter to an LDAP URL function"; - break; - } - - return( s ); -} - -#include <sasl.h> - -/* - Perform LDAP init and return an LDAP* handle. If ldapurl is given, - that is used as the basis for the protocol, host, port, and whether - to use starttls (given on the end as ldap://..../?????starttlsOID - If hostname is given, LDAP or LDAPS is assumed, and this will override - the hostname from the ldapurl, if any. If port is > 0, this is the - port number to use. It will override the port in the ldapurl, if any. - If no port is given in port or ldapurl, the default will be used based - on the secure setting (389 for ldap, 636 for ldaps, 389 for starttls) - secure takes 1 of 3 values - 0 means regular ldap, 1 means ldaps, 2 - means regular ldap with starttls. - filename is the ldapi file name - if this is given, and no other options - are given, ldapi is assumed. - */ -/* util_sasl_path: the string argument for putenv. - It must be a global or a static */ -char util_sasl_path[MAXPATHLEN]; - -LDAP * -slapi_ldap_init_ext( - const char *ldapurl, /* full ldap url */ - const char *hostname, /* can also use this to override - host in url */ - int port, /* can also use this to override port in url */ - int secure, /* 0 for ldap, 1 for ldaps, 2 for starttls - - override proto in url */ - int shared, /* if true, LDAP* will be shared among multiple threads */ - const char *filename /* for ldapi */ -) -{ - LDAPURLDesc *ludp = NULL; - LDAP *ld = NULL; - int rc = 0; - - /* We need to provide a sasl path used for client connections, especially - if the server is not set up to be a sasl server - since mozldap provides - no way to override the default path programatically, we set the sasl - path to the environment variable SASL_PATH. */ - char *configpluginpath = config_get_saslpath(); - char *pluginpath = configpluginpath; - char *pp = NULL; - - if (NULL == pluginpath || (*pluginpath == '\0')) { - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", - "configpluginpath == NULL\n"); - if (!(pluginpath = getenv("SASL_PATH"))) { -#if defined(LINUX) && defined(__LP64__) - pluginpath = "/usr/lib64/sasl2"; -#else - pluginpath = "/usr/lib/sasl2"; -#endif - } - } - if ('\0' == util_sasl_path[0] || /* first time */ - NULL == (pp = strchr(util_sasl_path, '=')) || /* invalid arg for putenv */ - (0 != strcmp(++pp, pluginpath)) /* sasl_path has been updated */ ) { - PR_snprintf(util_sasl_path, sizeof(util_sasl_path), - "SASL_PATH=%s", pluginpath); - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", - "putenv(%s)\n", util_sasl_path); - putenv(util_sasl_path); - } - slapi_ch_free_string(&configpluginpath); - - /* if ldapurl is given, parse it */ - if (ldapurl && ((rc = ldap_url_parse_no_defaults(ldapurl, &ludp, 0)) || - !ludp)) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", - "Could not parse given LDAP URL [%s] : error [%s]\n", - ldapurl ? ldapurl : "NULL", - slapi_urlparse_err2string(rc)); - goto done; - } - - /* use url host if no host given */ - if (!hostname && ludp && ludp->lud_host) { - hostname = ludp->lud_host; - } - - /* use url port if no port given */ - if (!port && ludp && ludp->lud_port) { - port = ludp->lud_port; - } - - /* use secure setting from url if none given */ - if (!secure && ludp) { - if (ludp->lud_options & LDAP_URL_OPT_SECURE) { - secure = 1; - } else if (0/* starttls option - not supported yet in LDAP URLs */) { - secure = 2; - } - } - - /* ldap_url_parse doesn't yet handle ldapi */ - /* - if (!filename && ludp && ludp->lud_file) { - filename = ludp->lud_file; - } - */ - -#ifdef MEMPOOL_EXPERIMENTAL - { - /* - * slapi_ch_malloc functions need to be set to LDAP C SDK - */ - struct ldap_memalloc_fns memalloc_fns; - memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc; - memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc; - memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc; - memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper; - } - /* - * MEMPOOL_EXPERIMENTAL: - * These LDAP C SDK init function needs to be revisited. - * In ldap_init called via ldapssl_init and prldap_init initializes - * options and set default values including memalloc_fns, then it - * initializes as sasl client by calling sasl_client_init. In - * sasl_client_init, it creates mechlist using the malloc function - * available at the moment which could mismatch the malloc/free functions - * set later. - */ -#endif - if (filename) { - /* ldapi in mozldap client is not yet supported */ - } else if (secure == 1) { - ld = ldapssl_init(hostname, port, secure); - } else { /* regular ldap and/or starttls */ - /* - * Leverage the libprldap layer to take care of all the NSPR - * integration. - * Note that ldapssl_init() uses libprldap implicitly. - */ - ld = prldap_init(hostname, port, shared); - } - - /* Update snmp interaction table */ - if (hostname) { - if (ld == NULL) { - set_snmp_interaction_row((char *)hostname, port, -1); - } else { - set_snmp_interaction_row((char *)hostname, port, 0); - } - } - - if ((ld != NULL) && !filename) { - /* - * Set the outbound LDAP I/O timeout based on the server config. - */ - int io_timeout_ms = config_get_outbound_ldap_io_timeout(); - if (io_timeout_ms > 0) { - if (prldap_set_session_option(ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT, - io_timeout_ms) != LDAP_SUCCESS) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", - "failed: unable to set outbound I/O " - "timeout to %dms\n", - io_timeout_ms); - slapi_ldap_unbind(ld); - ld = NULL; - goto done; - } - } - - /* - * Set SSL strength (server certificate validity checking). - */ - if (secure > 0) { - int ssl_strength = 0; - LDAP *myld = NULL; - - if (config_get_ssl_check_hostname()) { - /* check hostname against name in certificate */ - ssl_strength = LDAPSSL_AUTH_CNCHECK; - } else { - /* verify certificate only */ - ssl_strength = LDAPSSL_AUTH_CERT; - } - - /* we can only use the set functions below with a real - LDAP* if it has already gone through ldapssl_init - - so, use NULL if using starttls */ - if (secure == 1) { - myld = ld; - } - - if ((rc = ldapssl_set_strength(myld, ssl_strength)) || - (rc = ldapssl_set_option(myld, SSL_ENABLE_SSL2, PR_FALSE)) || - (rc = ldapssl_set_option(myld, SSL_ENABLE_SSL3, PR_TRUE)) || - (rc = ldapssl_set_option(myld, SSL_ENABLE_TLS, PR_TRUE))) { - int prerr = PR_GetError(); - - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext", - "failed: unable to set SSL options (" - SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - prerr, slapd_pr_strerror(prerr)); - - } - if (secure == 1) { - /* tell bind code we are using SSL */ - ldap_set_option(ld, LDAP_OPT_SSL, LDAP_OPT_ON); - } - } - } - - if (ld && (secure == 2)) { - /* We don't have a way to stash context data with the LDAP*, so we - stash the information in the client controls (currently unused). - We don't want to open the connection in ldap_init, since that's - not the semantic - the connection is not usually opened until - the first operation is sent, which is usually the bind - or - in this case, the start_tls - so we stash the start_tls so - we can do it in slapi_ldap_bind - note that this will get - cleaned up when the LDAP* is disposed of - */ - LDAPControl start_tls_dummy_ctrl; - LDAPControl **clientctrls = NULL; - - /* returns copy of controls */ - ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls); - - start_tls_dummy_ctrl.ldctl_oid = slapi_ch_strdup(START_TLS_OID); - start_tls_dummy_ctrl.ldctl_value.bv_val = NULL; - start_tls_dummy_ctrl.ldctl_value.bv_len = 0; - start_tls_dummy_ctrl.ldctl_iscritical = 0; - slapi_add_control_ext(&clientctrls, &start_tls_dummy_ctrl, 1); - /* set option frees old list and copies the new list */ - ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, clientctrls); - ldap_controls_free(clientctrls); /* free the copy */ - } - - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_init_ext", - "Success: set up conn to [%s:%d]%s\n", - hostname, port, - (secure == 2) ? " using startTLS" : - ((secure == 1) ? " using SSL" : "")); -done: - ldap_free_urldesc(ludp); - - return( ld ); -} - -/* - * Function: slapi_ldap_init() - * Description: just like ldap_ssl_init() but also arranges for the LDAP - * session handle returned to be safely shareable by multiple threads - * if "shared" is non-zero. - * Returns: - * an LDAP session handle (NULL if some local error occurs). - */ -LDAP * -slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared ) -{ - return slapi_ldap_init_ext(NULL, ldaphost, ldapport, secure, shared, NULL); -} - -/* - * Does the correct bind operation simple/sasl/cert depending - * on the arguments passed in. If the user specified to use - * starttls in init, this will do the starttls first. If using - * ssl or client cert auth, this will initialize the client side - * of that. - */ -int -slapi_ldap_bind( - LDAP *ld, /* ldap connection */ - const char *bindid, /* usually a bind DN for simple bind */ - const char *creds, /* usually a password for simple bind */ - const char *mech, /* name of mechanism */ - LDAPControl **serverctrls, /* additional controls to send */ - LDAPControl ***returnedctrls, /* returned controls */ - struct timeval *timeout, /* timeout */ - int *msgidp /* pass in non-NULL for async handling */ -) -{ - int rc = LDAP_SUCCESS; - LDAPControl **clientctrls = NULL; - int secure = 0; - struct berval bvcreds = {0, NULL}; - LDAPMessage *result = NULL; - struct berval *servercredp = NULL; - - /* do starttls if requested - NOTE - starttls is an extop, not a control, but we don't have - a place we can stash this information in the LDAP*, other - than the currently unused clientctrls */ - ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls); - if (clientctrls && clientctrls[0] && - slapi_control_present(clientctrls, START_TLS_OID, NULL, NULL)) { - secure = 2; - } else { - ldap_get_option(ld, LDAP_OPT_SSL, &secure); - } - - if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) { - /* SSL connections will use the server's security context - and cert for client auth */ - rc = slapd_SSL_client_auth(ld); - - if (rc != 0) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not configure the server for cert " - "auth - error %d - make sure the server is " - "correctly configured for SSL/TLS\n", rc); - goto done; - } else { - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", - "Set up conn to use client auth\n"); - } - bvcreds.bv_val = NULL; /* ignore username and passed in creds */ - bvcreds.bv_len = 0; /* for external auth */ - bindid = NULL; - } else { /* other type of auth */ - bvcreds.bv_val = (char *)creds; - bvcreds.bv_len = creds ? strlen(creds) : 0; - } - - if (secure == 2) { /* send start tls */ - rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL); - if (LDAP_SUCCESS != rc) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not send startTLS request: " - "error %d (%s)\n", - rc, ldap_err2string(rc)); - goto done; - } - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", - "startTLS started on connection\n"); - } - - /* The connection has been set up - now do the actual bind, depending on - the mechanism and arguments */ - if (!mech || (mech == LDAP_SASL_SIMPLE) || - !strcmp(mech, LDAP_SASL_EXTERNAL)) { - int mymsgid = 0; - - slapi_log_error(SLAPI_LOG_SHELL, "slapi_ldap_bind", - "attempting %s bind with id [%s] creds [%s]\n", - mech ? mech : "SIMPLE", - bindid, creds); - if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, - NULL /* clientctrls */, &mymsgid))) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not send bind request for id " - "[%s] mech [%s]: error %d (%s) %d (%s) %d (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc), - PR_GetError(), slapd_pr_strerror(PR_GetError()), - errno, slapd_system_strerror(errno)); - goto done; - } - - if (msgidp) { /* let caller process result */ - *msgidp = mymsgid; - } else { /* process results */ - rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result); - if (-1 == rc) { /* error */ - rc = ldap_get_lderrno(ld, NULL, NULL); - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error reading bind response for id " - "[%s] mech [%s]: error %d (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc)); - goto done; - } else if (rc == 0) { /* timeout */ - rc = LDAP_TIMEOUT; - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: timeout after [%ld.%ld] seconds reading " - "bind response for [%s] mech [%s]\n", - timeout ? timeout->tv_sec : 0, - timeout ? timeout->tv_usec : 0, - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE"); - goto done; - } - /* if we got here, we were able to read success result */ - /* Get the controls sent by the server if requested */ - if (returnedctrls) { - if ((rc = ldap_parse_result(ld, result, &rc, NULL, NULL, - NULL, returnedctrls, - 0)) != LDAP_SUCCESS) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not bind id " - "[%s] mech [%s]: error %d (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc)); - goto done; - } - } - - /* parse the bind result and get the ldap error code */ - if ((rc = ldap_parse_sasl_bind_result(ld, result, &servercredp, - 0)) || - (rc = ldap_result2error(ld, result, 0))) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not read bind results for id " - "[%s] mech [%s]: error %d (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc)); - goto done; - } - } - } else { - /* a SASL mech - set the sasl ssf to 0 if using TLS/SSL */ - if (secure) { - sasl_ssf_t max_ssf = 0; - ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf); - } - rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech, - serverctrls, returnedctrls, - msgidp); - if (LDAP_SUCCESS != rc) { - slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", - "Error: could not perform interactive bind for id " - "[%s] mech [%s]: error %d (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc)); - } - } - -done: - slapi_ch_bvfree(&servercredp); - ldap_msgfree(result); - - return rc; -} - -/* the following implements the client side of sasl bind, for LDAP server - -> LDAP server SASL */ - -typedef struct { - char *mech; - char *authid; - char *username; - char *passwd; - char *realm; -} ldapSaslInteractVals; - -#ifdef HAVE_KRB5 -static void set_krb5_creds( - const char *authid, - const char *username, - const char *passwd, - const char *realm, - ldapSaslInteractVals *vals -); -#endif - -static void * -ldap_sasl_set_interact_vals(LDAP *ld, const char *mech, const char *authid, - const char *username, const char *passwd, - const char *realm) -{ - ldapSaslInteractVals *vals = NULL; - char *idprefix = ""; - - vals = (ldapSaslInteractVals *) - slapi_ch_calloc(1, sizeof(ldapSaslInteractVals)); - - if (!vals) { - return NULL; - } - - if (mech) { - vals->mech = slapi_ch_strdup(mech); - } else { - ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &vals->mech); - } - - if (vals->mech && !strcasecmp(vals->mech, "DIGEST-MD5")) { - idprefix = "dn:"; /* prefix name and id with this string */ - } - - if (authid) { /* use explicit passed in value */ - vals->authid = slapi_ch_smprintf("%s%s", idprefix, authid); - } else { /* use option value if any */ - ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &vals->authid); - if (!vals->authid) { -/* get server user id? */ - vals->authid = slapi_ch_strdup(""); - } - } - - if (username) { /* use explicit passed in value */ - vals->username = slapi_ch_smprintf("%s%s", idprefix, username); - } else { /* use option value if any */ - ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &vals->username); - if (!vals->username) { /* use default sasl value */ - vals->username = slapi_ch_strdup(""); - } - } - - if (passwd) { - vals->passwd = slapi_ch_strdup(passwd); - } else { - vals->passwd = slapi_ch_strdup(""); - } - - if (realm) { - vals->realm = slapi_ch_strdup(realm); - } else { - ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &vals->realm); - if (!vals->realm) { /* use default sasl value */ - vals->realm = slapi_ch_strdup(""); - } - } - -#ifdef HAVE_KRB5 - if (mech && !strcmp(mech, "GSSAPI")) { - set_krb5_creds(authid, username, passwd, realm, vals); - } -#endif /* HAVE_KRB5 */ - - return vals; -} - -static void -ldap_sasl_free_interact_vals(void *defaults) -{ - ldapSaslInteractVals *vals = defaults; - - if (vals) { - slapi_ch_free_string(&vals->mech); - slapi_ch_free_string(&vals->authid); - slapi_ch_free_string(&vals->username); - slapi_ch_free_string(&vals->passwd); - slapi_ch_free_string(&vals->realm); - slapi_ch_free(&defaults); - } -} - -static int -ldap_sasl_get_val(ldapSaslInteractVals *vals, sasl_interact_t *interact, unsigned flags) -{ - const char *defvalue = interact->defresult; - int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing */ - - if (vals != NULL) { - switch(interact->id) { - case SASL_CB_AUTHNAME: - defvalue = vals->authid; - slapi_log_error(authtracelevel, "ldap_sasl_get_val", - "Using value [%s] for SASL_CB_AUTHNAME\n", - defvalue ? defvalue : "(null)"); - break; - case SASL_CB_USER: - defvalue = vals->username; - slapi_log_error(authtracelevel, "ldap_sasl_get_val", - "Using value [%s] for SASL_CB_USER\n", - defvalue ? defvalue : "(null)"); - break; - case SASL_CB_PASS: - defvalue = vals->passwd; - slapi_log_error(authtracelevel, "ldap_sasl_get_val", - "Using value [%s] for SASL_CB_PASS\n", - defvalue ? defvalue : "(null)"); - break; - case SASL_CB_GETREALM: - defvalue = vals->realm; - slapi_log_error(authtracelevel, "ldap_sasl_get_val", - "Using value [%s] for SASL_CB_GETREALM\n", - defvalue ? defvalue : "(null)"); - break; - } - } - - if (defvalue != NULL) { - interact->result = defvalue; - if ((char *)interact->result == NULL) - return (LDAP_NO_MEMORY); - interact->len = strlen((char *)(interact->result)); - } - return (LDAP_SUCCESS); -} - -static int -ldap_sasl_interact_cb(LDAP *ld, unsigned flags, void *defaults, void *prompts) -{ - sasl_interact_t *interact = NULL; - ldapSaslInteractVals *sasldefaults = defaults; - int rc; - - if (prompts == NULL) { - return (LDAP_PARAM_ERROR); - } - - for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) { - /* Obtain the default value */ - if ((rc = ldap_sasl_get_val(sasldefaults, interact, flags)) != LDAP_SUCCESS) { - return (rc); - } - } - - return (LDAP_SUCCESS); -} - -/* figure out from the context and this error if we should - attempt to retry the bind */ -static int -can_retry_bind(LDAP *ld, const char *mech, const char *bindid, - const char *creds, int rc, const char *errmsg) -{ - int localrc = 0; - if (errmsg && strstr(errmsg, "Ticket expired")) { - localrc = 1; - } - - return localrc; -} - -int -slapd_ldap_sasl_interactive_bind( - LDAP *ld, /* ldap connection */ - const char *bindid, /* usually a bind DN for simple bind */ - const char *creds, /* usually a password for simple bind */ - const char *mech, /* name of mechanism */ - LDAPControl **serverctrls, /* additional controls to send */ - LDAPControl ***returnedctrls, /* returned controls */ - int *msgidp /* pass in non-NULL for async handling */ -) -{ - int rc = LDAP_SUCCESS; - int tries = 0; - - while (tries < 2) { - void *defaults = ldap_sasl_set_interact_vals(ld, mech, bindid, bindid, - creds, NULL); - /* have to first set the defaults used by the callback function */ - /* call the bind function */ - rc = ldap_sasl_interactive_bind_ext_s(ld, bindid, mech, serverctrls, - NULL, LDAP_SASL_QUIET, - ldap_sasl_interact_cb, defaults, - returnedctrls); - ldap_sasl_free_interact_vals(defaults); - if (LDAP_SUCCESS != rc) { - char *errmsg = NULL; - rc = ldap_get_lderrno(ld, NULL, &errmsg); - slapi_log_error(SLAPI_LOG_FATAL, "slapd_ldap_sasl_interactive_bind", - "Error: could not perform interactive bind for id " - "[%s] mech [%s]: error %d (%s) (%s)\n", - bindid ? bindid : "(anon)", - mech ? mech : "SIMPLE", - rc, ldap_err2string(rc), errmsg); - if (can_retry_bind(ld, mech, bindid, creds, rc, errmsg)) { - ; /* pass through to retry one time */ - } else { - break; /* done - fail - cannot retry */ - } - } else { - break; /* done - success */ - } - tries++; - } - - return rc; -} - -#ifdef HAVE_KRB5 -#include <krb5.h> - -/* for some reason this is not in the public API? - but it is documented e.g. man kinit */ -#ifndef KRB5_ENV_CCNAME -#define KRB5_ENV_CCNAME "KRB5CCNAME" -#endif - -static void -show_one_credential(int authtracelevel, - krb5_context ctx, krb5_creds *cred) -{ - char *logname = "show_one_credential"; - krb5_error_code rc; - char *name = NULL, *sname = NULL; - char startts[BUFSIZ], endts[BUFSIZ], renewts[BUFSIZ]; - - if ((rc = krb5_unparse_name(ctx, cred->client, &name))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get client name from credential: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - if ((rc = krb5_unparse_name(ctx, cred->server, &sname))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get server name from credential: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - if (!cred->times.starttime) { - cred->times.starttime = cred->times.authtime; - } - krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.starttime, - startts, sizeof(startts), NULL); - krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.endtime, - endts, sizeof(endts), NULL); - krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.renew_till, - renewts, sizeof(renewts), NULL); - - slapi_log_error(authtracelevel, logname, - "\tKerberos credential: client [%s] server [%s] " - "start time [%s] end time [%s] renew time [%s] " - "flags [0x%x]\n", name, sname, startts, endts, - renewts, (uint32_t)cred->ticket_flags); - -cleanup: - krb5_free_unparsed_name(ctx, name); - krb5_free_unparsed_name(ctx, sname); - - return; -} - -/* - * Call this after storing the credentials in the cache - */ -static void -show_cached_credentials(int authtracelevel, - krb5_context ctx, krb5_ccache cc, - krb5_principal princ) -{ - char *logname = "show_cached_credentials"; - krb5_error_code rc = 0; - krb5_creds creds; - krb5_cc_cursor cur; - char *princ_name = NULL; - - if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get principal name from principal: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - - slapi_log_error(authtracelevel, logname, - "Ticket cache: %s:%s\nDefault principal: %s\n\n", - krb5_cc_get_type(ctx, cc), - krb5_cc_get_name(ctx, cc), princ_name); - - if ((rc = krb5_cc_start_seq_get(ctx, cc, &cur))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get cursor to iterate cached credentials: " - "%d (%s)\n", rc, error_message(rc)); - goto cleanup; - } - - while (!(rc = krb5_cc_next_cred(ctx, cc, &cur, &creds))) { - show_one_credential(authtracelevel, ctx, &creds); - krb5_free_cred_contents(ctx, &creds); - } - if (rc == KRB5_CC_END) { - if ((rc = krb5_cc_end_seq_get(ctx, cc, &cur))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not close cached credentials cursor: " - "%d (%s)\n", rc, error_message(rc)); - goto cleanup; - } - } - -cleanup: - krb5_free_unparsed_name(ctx, princ_name); - - return; -} - -static int -looks_like_a_dn(const char *username) -{ - return (username && strchr(username, '=')); -} - -static int -credentials_are_valid( - krb5_context ctx, - krb5_ccache cc, - krb5_principal princ, - const char *princ_name, - int *rc -) -{ - char *logname = "credentials_are_valid"; - int myrc = 0; - krb5_creds mcreds; /* match these values */ - krb5_creds creds; /* returned creds */ - char *tgs_princ_name = NULL; - krb5_timestamp currenttime; - int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing */ - int realm_len; - char *realm_str; - int time_buffer = 30; /* seconds - go ahead and renew if creds are - about to expire */ - - memset(&mcreds, 0, sizeof(mcreds)); - memset(&creds, 0, sizeof(creds)); - *rc = 0; - if (!cc) { - /* ok - no error */ - goto cleanup; - } - - /* have to construct the tgs server principal in - order to set mcreds.server required in order - to use krb5_cc_retrieve_creds() */ - /* get default realm first */ - realm_len = krb5_princ_realm(ctx, princ)->length; - realm_str = krb5_princ_realm(ctx, princ)->data; - tgs_princ_name = slapi_ch_smprintf("%s/%*s@%*s", KRB5_TGS_NAME, - realm_len, realm_str, - realm_len, realm_str); - - if ((*rc = krb5_parse_name(ctx, tgs_princ_name, &mcreds.server))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could parse principal [%s]: %d (%s)\n", - tgs_princ_name, *rc, error_message(*rc)); - goto cleanup; - } - - mcreds.client = princ; - if ((*rc = krb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds))) { - if (*rc == KRB5_CC_NOTFOUND) { - /* ok - no creds for this princ in the cache */ - *rc = 0; - } - goto cleanup; - } - - /* have the creds - now look at the timestamp */ - if ((*rc = krb5_timeofday(ctx, ¤ttime))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get current time: %d (%s)\n", - *rc, error_message(*rc)); - goto cleanup; - } - - if (currenttime > (creds.times.endtime + time_buffer)) { - slapi_log_error(authtracelevel, logname, - "Credentials for [%s] have expired or will soon " - "expire - now [%d] endtime [%d]\n", princ_name, - currenttime, creds.times.endtime); - goto cleanup; - } - - myrc = 1; /* credentials are valid */ -cleanup: - krb5_free_cred_contents(ctx, &creds); - slapi_ch_free_string(&tgs_princ_name); - if (mcreds.server) { - krb5_free_principal(ctx, mcreds.server); - } - - return myrc; -} - -/* - * This implementation assumes that we want to use the - * keytab from the default keytab env. var KRB5_KTNAME - * as. This code is very similar to kinit -k -t. We - * get a krb context, get the default keytab, get - * the credentials from the keytab, authenticate with - * those credentials, create a ccache, store the - * credentials in the ccache, and set the ccache - * env var to point to those credentials. - */ -static void -set_krb5_creds( - const char *authid, - const char *username, - const char *passwd, - const char *realm, - ldapSaslInteractVals *vals -) -{ - char *logname = "set_krb5_creds"; - const char *cc_type = "MEMORY"; /* keep cred cache in memory */ - krb5_context ctx = NULL; - krb5_ccache cc = NULL; - krb5_principal princ = NULL; - char *princ_name = NULL; - krb5_error_code rc = 0; - krb5_creds creds; - krb5_keytab kt = NULL; - char *cc_name = NULL; - char ktname[MAX_KEYTAB_NAME_LEN]; - static char cc_env_name[1024+32]; /* size from ccdefname.c */ - int new_ccache = 0; - int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing - not sure what shell was - used for, does not - appear to be used - currently */ - - /* probably have to put a mutex around this whole thing, to avoid - problems with reentrancy, since we are setting a "global" - variable via an environment variable */ - - /* wipe this out so we can safely free it later if we - short circuit */ - memset(&creds, 0, sizeof(creds)); - - /* initialize the kerberos context */ - if ((rc = krb5_init_context(&ctx))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not init Kerberos context: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - - /* see if there is already a ccache, and see if there are - creds in the ccache */ - /* grab the default ccache - note: this does not open the cache */ - if ((rc = krb5_cc_default(ctx, &cc))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get default Kerberos ccache: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - - /* use this cache - construct the full cache name */ - cc_name = slapi_ch_smprintf("%s:%s", krb5_cc_get_type(ctx, cc), - krb5_cc_get_name(ctx, cc)); - - /* grab the principal from the ccache - will fail if there - is no ccache */ - if ((rc = krb5_cc_get_principal(ctx, cc, &princ))) { - if (KRB5_FCC_NOFILE == rc) { /* no cache - ok */ - slapi_log_error(authtracelevel, logname, - "The default credentials cache [%s] not found: " - "will create a new one.\n", cc_name); - /* close the cache - we will create a new one below */ - krb5_cc_close(ctx, cc); - cc = NULL; - slapi_ch_free_string(&cc_name); - /* fall through to the keytab auth code below */ - } else { /* fatal */ - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not open default Kerberos ccache [%s]: " - "%d (%s)\n", cc_name, rc, error_message(rc)); - goto cleanup; - } - } else { /* have a valid ccache && found principal */ - if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Unable to get name of principal from ccache [%s]: " - "%d (%s)\n", cc_name, rc, error_message(rc)); - goto cleanup; - } - slapi_log_error(authtracelevel, logname, - "Using principal [%s] from ccache [%s]\n", - princ_name, cc_name); - } - - /* if this is not our type of ccache, there is nothing more we can - do - just punt and let sasl/gssapi take it's course - this - usually means there has been an external kinit e.g. in the - start up script, and it is the responsibility of the script to - renew those credentials or face lots of sasl/gssapi failures - This means, however, that the caller MUST MAKE SURE THERE IS NO - DEFAULT CCACHE FILE or the server will attempt to use it (and - likely fail) - THERE MUST BE NO DEFAULT CCACHE FILE IF YOU WANT - THE SERVER TO AUTHENTICATE WITH THE KEYTAB - NOTE: cc types are case sensitive and always upper case */ - if (cc && strcmp(cc_type, krb5_cc_get_type(ctx, cc))) { - static int errmsgcounter = 0; - int loglevel = SLAPI_LOG_FATAL; - if (errmsgcounter) { - loglevel = authtracelevel; - } - /* make sure we log this message once, in case the user has - done something unintended, we want to make sure they know - about it. However, if the user knows what he/she is doing, - by using an external ccache file, they probably don't want - to be notified with an error every time. */ - slapi_log_error(loglevel, logname, - "The server will use the external SASL/GSSAPI " - "credentials cache [%s:%s]. If you want the " - "server to automatically authenticate with its " - "keytab, you must remove this cache. If you " - "did not intend to use this cache, you will likely " - "see many SASL/GSSAPI authentication failures.\n", - krb5_cc_get_type(ctx, cc), krb5_cc_get_name(ctx, cc)); - errmsgcounter++; - goto cleanup; - } - - /* need to figure out which principal to use - 1) use the one from the ccache - 2) use username - 3) construct one in the form ldap/fqdn@REALM - */ - if (!princ && username && !looks_like_a_dn(username) && - (rc = krb5_parse_name(ctx, username, &princ))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Error: could not convert [%s] into a kerberos " - "principal: %d (%s)\n", username, - rc, error_message(rc)); - goto cleanup; - } - - /* if still no principal, construct one */ - if (!princ && - (rc = krb5_sname_to_principal(ctx, NULL, "ldap", - KRB5_NT_SRV_HST, &princ))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Error: could not construct ldap service " - "principal: %d (%s)\n", rc, error_message(rc)); - goto cleanup; - } - - if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Unable to get name of principal: " - "%d (%s)\n", rc, error_message(rc)); - goto cleanup; - } - - slapi_log_error(authtracelevel, logname, - "Using principal named [%s]\n", princ_name); - - /* grab the credentials from the ccache, if any - - if the credentials are still valid, we do not have - to authenticate again */ - if (credentials_are_valid(ctx, cc, princ, princ_name, &rc)) { - slapi_log_error(authtracelevel, logname, - "Credentials for principal [%s] are still " - "valid - no auth is necessary.\n", - princ_name); - goto cleanup; - } else if (rc) { /* some error other than "there are no credentials" */ - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Unable to verify cached credentials for " - "principal [%s]: %d (%s)\n", princ_name, - rc, error_message(rc)); - goto cleanup; - } - - /* find our default keytab */ - if ((rc = krb5_kt_default(ctx, &kt))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Unable to get default keytab: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - - /* get name of keytab for debugging purposes */ - if ((rc = krb5_kt_get_name(ctx, kt, ktname, sizeof(ktname)))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Unable to get name of default keytab: %d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - - slapi_log_error(authtracelevel, logname, - "Using keytab named [%s]\n", ktname); - - /* now do the actual kerberos authentication using - the keytab, and get the creds */ - rc = krb5_get_init_creds_keytab(ctx, &creds, princ, kt, - 0, NULL, NULL); - if (rc) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not get initial credentials for principal [%s] " - "in keytab [%s]: %d (%s)\n", - princ_name, ktname, rc, error_message(rc)); - goto cleanup; - } - - /* completely done with the keytab now, close it */ - krb5_kt_close(ctx, kt); - kt = NULL; /* no double free */ - - /* we now have the creds and the principal to which the - creds belong - use or allocate a new memory based - cache to hold the creds */ - if (!cc_name) { -#if HAVE_KRB5_CC_NEW_UNIQUE - /* krb5_cc_new_unique is a new convenience function which - generates a new unique name and returns a memory - cache with that name */ - if ((rc = krb5_cc_new_unique(ctx, cc_type, NULL, &cc))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not create new unique memory ccache: " - "%d (%s)\n", - rc, error_message(rc)); - goto cleanup; - } - cc_name = slapi_ch_smprintf("%s:%s", cc_type, - krb5_cc_get_name(ctx, cc)); -#else - /* store the cache in memory - krb5_init_context uses malloc - to create the ctx, so the address should be unique enough - for our purposes */ - if (!(cc_name = slapi_ch_smprintf("%s:%p", cc_type, ctx))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could create Kerberos memory ccache: " - "out of memory\n"); - rc = 1; - goto cleanup; - } -#endif - slapi_log_error(authtracelevel, logname, - "Generated new memory ccache [%s]\n", cc_name); - new_ccache = 1; /* need to set this in env. */ - } else { - slapi_log_error(authtracelevel, logname, - "Using existing ccache [%s]\n", cc_name); - } - - /* krb5_cc_resolve is basically like an init - - this creates the cache structure, and creates a slot - for the cache in the static linked list in memory, if - there is not already a slot - - see cc_memory.c for details - cc could already have been created by new_unique above - */ - if (!cc && (rc = krb5_cc_resolve(ctx, cc_name, &cc))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not create ccache [%s]: %d (%s)\n", - cc_name, rc, error_message(rc)); - goto cleanup; - } - - /* wipe out previous contents of cache for this principal, if any */ - if ((rc = krb5_cc_initialize(ctx, cc, princ))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not initialize ccache [%s] for the new " - "credentials for principal [%s]: %d (%s)\n", - cc_name, princ_name, rc, error_message(rc)); - goto cleanup; - } - - /* store the credentials in the cache */ - if ((rc = krb5_cc_store_cred(ctx, cc, &creds))) { - slapi_log_error(SLAPI_LOG_FATAL, logname, - "Could not store the credentials in the " - "ccache [%s] for principal [%s]: %d (%s)\n", - cc_name, princ_name, rc, error_message(rc)); - goto cleanup; - } - - /* now, do a "klist" to show the credential information, and log it */ - show_cached_credentials(authtracelevel, ctx, cc, princ); - - /* set the CC env var to the value of the cc cache name */ - /* since we can't pass krb5 context up and out of here - and down through the ldap sasl layer, we set this - env var so that calls to krb5_cc_default_name will - use this */ - if (new_ccache) { - PR_snprintf(cc_env_name, sizeof(cc_env_name), - "%s=%s", KRB5_ENV_CCNAME, cc_name); - PR_SetEnv(cc_env_name); - slapi_log_error(authtracelevel, logname, - "Set new env for ccache: [%s]\n", - cc_env_name); - } - -cleanup: - /* use NULL as username and authid */ - slapi_ch_free_string(&vals->username); - slapi_ch_free_string(&vals->authid); - - krb5_free_unparsed_name(ctx, princ_name); - if (kt) { /* NULL not allowed */ - krb5_kt_close(ctx, kt); - } - if (creds.client == princ) { - creds.client = NULL; - } - krb5_free_cred_contents(ctx, &creds); - slapi_ch_free_string(&cc_name); - krb5_free_principal(ctx, princ); - if (cc) { - krb5_cc_close(ctx, cc); - } - if (ctx) { /* cannot pass NULL to free context */ - krb5_free_context(ctx); - } - return; -} - -#endif /* HAVE_KRB5 */ diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c index 89732faf..5b2ad68a 100644 --- a/ldap/servers/snmp/main.c +++ b/ldap/servers/snmp/main.c @@ -47,6 +47,7 @@ #include <signal.h> #include <sys/stat.h> #include "ldap-agent.h" +#include "ldap.h" #include "ldif.h" static char *agentx_master = NULL; @@ -245,7 +246,12 @@ load_config(char *conf_path) { server_instance *serv_p = NULL; FILE *conf_file = NULL; +#if defined(USE_OPENLDAP) + LDIFFP *dse_fp = NULL; + int buflen; +#else FILE *dse_fp = NULL; +#endif char line[MAXLINE]; char *p = NULL; int error = 0; @@ -371,7 +377,12 @@ load_config(char *conf_path) } /* Open dse.ldif */ - if ((dse_fp = fopen(serv_p->dse_ldif, "r")) == NULL) { +#if defined(USE_OPENLDAP) + dse_fp = ldif_open(serv_p->dse_ldif, "r"); +#else + dse_fp = fopen(serv_p->dse_ldif, "r"); +#endif + if (dse_fp == NULL) { printf("ldap-agent: Error opening server config file: %s\n", serv_p->dse_ldif); error = 1; @@ -386,12 +397,20 @@ load_config(char *conf_path) * the pointer that is passed to it, so we need to save a * pointer to the beginning of the entry so we can free it * later. */ - while ((entry = ldif_get_entry(dse_fp, &lineno)) != NULL) { +#if defined(USE_OPENLDAP) + while (ldif_read_record(dse_fp, &lineno, &entry, &buflen)) +#else + while ((entry = ldif_get_entry(dse_fp, &lineno)) != NULL) +#endif + { char *entryp = entry; char *attr = NULL; char *val = NULL; +#if defined(USE_OPENLDAP) + ber_len_t vlen; +#else int vlen; - +#endif /* Check if this is the cn=config entry */ ldif_parse_line(ldif_getline(&entryp), &attr, &val, &vlen); if ((strcmp(attr, "dn") == 0) && @@ -470,8 +489,13 @@ load_config(char *conf_path) close_and_exit: if (conf_file) fclose(conf_file); - if (dse_fp) + if (dse_fp) { +#if defined(USE_OPENLDAP) + ldif_close(dse_fp); +#else fclose(dse_fp); +#endif + } if (error) exit(error); } |