فهرست منبع

Resolves: bug 469261
Bug Description: Support server-to-server SASL - part 2
Reviewed by: nhosoi (Thanks!)
Fix Description: This part focuses on chaining backend - allowing the mux server to use SASL to connect to the farm server, and allowing SASL authentication to chain. I had to add two new config parameters for chaining:
nsUseStartTLS - on or off - tell connection to use startTLS - default is off
nsBindMechanism - if absent, will just use simple auth. If present, this must be one of the supported mechanisms (EXTERNAL, GSSAPI, DIGEST-MD5) - default is absent (simple bind)
The chaining code uses a timeout, so I had to add a timeout to slapi_ldap_bind, and correct the replication code to pass in a NULL for the timeout parameter.
Fixed a bug in the starttls code in slapi_ldap_init_ext.
The sasl code uses an internal search to find the entry corresponding to the sasl user id. This search could not be chained due to the way it was coded. So I added a new chainable component called cn=sasl and changed the sasl internal search code to use this component ID. This allows the sasl code to work with a chained backend. In order to use chaining with sasl, this component must be set in the chaining configuration nsActiveChainingComponents. I also discovered that password policy must be configured too, in order for the sasl code to determine if the account is locked out.
I fixed a bug in the sasl mapping debug trace code.
Still to come - sasl mappings to work with all of this new code - kerberos code improvements - changes to pta and dna
Platforms tested: Fedora 8, Fedora 9
Flag Day: yes
Doc impact: yes

Rich Megginson 17 سال پیش
والد
کامیت
16c994ace5

+ 3 - 0
ldap/ldif/template-dse.ldif.in

@@ -752,6 +752,9 @@ nsTransmittedControls: 1.2.840.113556.1.4.473
 nsTransmittedControls: 1.3.6.1.4.1.1466.29539.12
 nsPossibleChainingComponents: cn=resource limits,cn=components,cn=config
 nsPossibleChainingComponents: cn=certificate-based authentication,cn=components,cn=config
+nsPossibleChainingComponents: cn=password policy,cn=components,cn=config
+nsPossibleChainingComponents: cn=sasl,cn=components,cn=config
+nsPossibleChainingComponents: cn=roles,cn=components,cn=config
 nsPossibleChainingComponents: cn=ACL Plugin,cn=plugins,cn=config
 nsPossibleChainingComponents: cn=old plugin,cn=plugins,cn=config
 nsPossibleChainingComponents: cn=referential integrity postoperation,cn=plugins,cn=config

+ 6 - 0
ldap/servers/plugins/chainingdb/cb.h

@@ -114,8 +114,10 @@
 #define CB_CONFIG_SIZELIMIT			"nsslapd-sizelimit"
 #define CB_CONFIG_TIMELIMIT			"nsslapd-timelimit"
 #define CB_CONFIG_HOSTURL			"nsFarmServerURL"
+#define CB_CONFIG_STARTTLS			"nsUseStartTLS"
 
 #define CB_CONFIG_BINDUSER			"nsMultiplexorBindDn"	
+#define CB_CONFIG_BINDMECH			"nsBindMechanism"
 #define CB_CONFIG_USERPASSWORD			"nsMultiplexorCredentials"	
 #define CB_CONFIG_MAXBINDCONNECTIONS		"nsBindConnectionsLimit"
 #define CB_CONFIG_MAXCONNECTIONS		"nsOperationConnectionsLimit"
@@ -163,6 +165,8 @@
 #define CB_DEF_HOPLIMIT				"10"	/* CB_CONFIG_HOPLIMIT */
 #define CB_DEF_MAX_IDLE_TIME			"60"	/* CB_CONFIG_MAX_IDLE_TIME */
 #define CB_DEF_MAX_TEST_TIME			"15"	/* CB_CONFIG_MAX_TEST_TIME */
+#define CB_DEF_STARTTLS			"off"	/* CB_CONFIG_STARTTLS */
+#define CB_DEF_BINDMECH			LDAP_SASL_SIMPLE	/* CB_CONFIG_BINDMECH */
 
 typedef void *cb_config_get_fn_t(void *arg);
 typedef int cb_config_set_fn_t(void *arg, void *value, char *errorbuf, int phase, int apply);
@@ -290,6 +294,8 @@ typedef struct  {
 
 	/* To protect the config set by LDAP */
 	PRRWLock	* rwl_config_lock;
+	int		starttls; /* use starttls with connection */
+	char		*mech; /* plain, external, or a sasl mech */
 } cb_conn_pool;
 
 

+ 32 - 77
ldap/servers/plugins/chainingdb/cb_conn_stateless.c

@@ -164,6 +164,7 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 	char 				*password,*binddn,*hostname;
 	unsigned int 		port;
 	int 				secure;
+	char 				*mech = NULL;;
 	static	char		*error1="Can't contact remote server : %s";
 	static	char		*error2="Can't bind to remote server : %s";
 	int					isMultiThread = ENABLE_MULTITHREAD_PER_CONN ; /* by default, we enable multiple operations per connection */
@@ -199,6 +200,10 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 	hostname=pool->hostname;
 	port=pool->port;
 	secure=pool->secure;
+	if (pool->starttls) {
+	    secure = 2;
+	}
+	mech=pool->mech;
 
 	PR_RWLock_Unlock(pool->rwl_config_lock);
 
@@ -348,12 +353,8 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 			/* For now, bind even if no user to detect error */
 			/* earlier					 */
                 	if (pool->bindit) {
-				int 				msgid;
-				LDAPMessage                  	*res=NULL;
-				int 				parse_rc;
 				PRErrorCode			prerr = 0;
 				LDAPControl                     **serverctrls=NULL;
-				char 				**referrals=NULL;
 				
 				char *plain = NULL;
 				int ret  = -1;
@@ -381,14 +382,21 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 				}
 
 				/* Password-based client authentication */
+				rc = slapi_ldap_bind(ld, binddn, plain, mech, NULL, &serverctrls,
+						     &bind_to, NULL);
 
-				if (( msgid = ldap_simple_bind( ld, binddn, plain)) <0) {
-					rc=ldap_get_lderrno( ld, NULL, NULL );
-					prerr=PR_GetError();
-				}
 				if ( ret == 0 ) slapi_ch_free_string(&plain); /* free plain only if it has been duplicated */
 
-				if ( rc != LDAP_SUCCESS ) {
+				if ( rc == LDAP_TIMEOUT ) {
+					if (cb_debug_on()) {
+                                	slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
+                                        	"Can't bind to server <%s> port <%d>. (%s)\n",
+                                        	hostname, port, "time-out expired");
+					}
+					rc = LDAP_CONNECT_ERROR;
+					goto unlock_and_return;
+				} else if ( rc != LDAP_SUCCESS ) {
+					prerr=PR_GetError();
 					if (cb_debug_on()) {
 						slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
 								"Can't bind to server <%s> port <%d>. "
@@ -405,67 +413,11 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 					goto unlock_and_return;
 				}
 
-				rc = ldap_result( ld, msgid, 0, &bind_to, &res );
-				switch (rc) {
-				case -1:
-					rc = ldap_get_lderrno( ld, NULL, NULL );
-					if (cb_debug_on()) {
-						slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
-							"Can't bind to server <%s> port <%d>. "
-							"(LDAP error %d - %s; "
-							SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n",
-							hostname, port, rc,
-							ldap_err2string(rc),
-							prerr, slapd_pr_strerror(prerr));
-					}
-					if ( errmsg ) {
-						*errmsg = PR_smprintf(error2,ldap_err2string(rc));
-					}
-					rc = LDAP_CONNECT_ERROR;
-					goto unlock_and_return;
-				case 0:
-					if (cb_debug_on()) {
-                                	slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
-                                        	"Can't bind to server <%s> port <%d>. (%s)\n",
-                                        	hostname, port, "time-out expired");
-					}
-					rc = LDAP_CONNECT_ERROR;
-					goto unlock_and_return;
-				default:
-
-					parse_rc = ldap_parse_result( ld, res, &rc, NULL, 
-       						NULL, &referrals, &serverctrls, 1 );
-
-      					if ( parse_rc != LDAP_SUCCESS ) {
-						if (cb_debug_on()) {
-                                		slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
-                                        		"Can't bind to server <%s> port <%d>. (%s)\n",
-                                        		hostname, port, ldap_err2string(parse_rc));
-						}
-						if ( errmsg ) {
-							*errmsg = PR_smprintf(error2,ldap_err2string(parse_rc));
-						}
-						rc = parse_rc;
-						goto unlock_and_return;
-					}
-
-				  	if ( rc != LDAP_SUCCESS ) {
-						if (cb_debug_on()) {
-                                		slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
-                                        		"Can't bind to server <%s> port <%d>. (%s)\n",
-                                        		hostname, port, ldap_err2string(rc));
-						}
-						if ( errmsg ) {
-							*errmsg = PR_smprintf(error2, ldap_err2string(rc));
-						}
-						goto unlock_and_return;
-					}
-
-					if ( serverctrls ) 
+				if ( serverctrls ) 
+				{
+					int i;
+					for( i = 0; serverctrls[ i ] != NULL; ++i ) 
 					{
-					    int i;
-					    for( i = 0; serverctrls[ i ] != NULL; ++i ) 
-					    {
 						if ( !(strcmp( serverctrls[ i ]->ldctl_oid, LDAP_CONTROL_PWEXPIRED)) )
 						{
 						    /* Bind is successful but password has expired */
@@ -487,12 +439,8 @@ int cb_get_connection(cb_conn_pool * pool, LDAP ** lld, cb_outgoing_conn ** cc,s
 									binddn, hostname, port, password_expiring);
 						    }
 						}
-					    }	
-					    ldap_controls_free(serverctrls);
-					}
-
-					if (referrals) 
-					    charray_free(referrals);
+					}	
+					ldap_controls_free(serverctrls);
 				}
 			}
 
@@ -896,6 +844,7 @@ int cb_ping_farm(cb_backend_instance *cb, cb_outgoing_conn * cnx,time_t end_time
 	LDAP 			*ld;
 	LDAPMessage		*result;
 	time_t 			now;
+	int 			secure;
 	if (cb->max_idle_time <=0)	/* Heart-beat disabled */
 		return LDAP_SUCCESS;
 
@@ -904,8 +853,12 @@ int cb_ping_farm(cb_backend_instance *cb, cb_outgoing_conn * cnx,time_t end_time
 
 	now = current_time();
 	if (end_time && ((now <= end_time) || (end_time <0))) return LDAP_SUCCESS;
-	
-	ld=slapi_ldap_init(cb->pool->hostname,cb->pool->port,cb->pool->secure,0); 
+
+	secure = cb->pool->secure;
+	if (cb->pool->starttls) {
+		secure = 2;
+	}
+	ld=slapi_ldap_init(cb->pool->hostname,cb->pool->port,secure,0); 
 	if (NULL == ld) {
 		cb_update_failed_conn_cpt( cb );
 		return LDAP_SERVER_DOWN;
@@ -914,6 +867,8 @@ int cb_ping_farm(cb_backend_instance *cb, cb_outgoing_conn * cnx,time_t end_time
 	timeout.tv_sec=cb->max_test_time;
 	timeout.tv_usec=0;
 	
+	/* NOTE: This will fail if we implement the ability to disable
+	   anonymous bind */
  	rc=ldap_search_ext_s(ld ,NULL,LDAP_SCOPE_BASE,"objectclass=*",attrs,1,NULL, 
 		NULL, &timeout, 1,&result);
 	if ( LDAP_SUCCESS != rc ) {

+ 69 - 3
ldap/servers/plugins/chainingdb/cb_instance.c

@@ -53,7 +53,9 @@
 /* Get functions */
 
 static void *cb_instance_hosturl_get(void *arg);
+static void *cb_instance_starttls_get(void *arg);
 static void *cb_instance_binduser_get(void *arg);
+static void *cb_instance_bindmech_get(void *arg);
 static void *cb_instance_userpassword_get(void *arg);
 static void *cb_instance_maxbconn_get(void *arg);
 static void *cb_instance_maxconn_get(void *arg);
@@ -77,7 +79,9 @@ static void *cb_instance_max_test_get(void *arg);
 /* Set functions */
 
 static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int phase, int apply);
+static int cb_instance_starttls_set(void *arg, void *value, char *errorbuf, int phase, int apply);
 static int cb_instance_binduser_set(void *arg, void *value, char *errorbuf, int phase, int apply);
+static int cb_instance_bindmech_set(void *arg, void *value, char *errorbuf, int phase, int apply);
 static int cb_instance_userpassword_set(void *arg, void *value, char *errorbuf, int phase, int apply);
 static int cb_instance_maxbconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
 static int cb_instance_maxconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
@@ -120,6 +124,8 @@ cb_instance_config_info cb_the_instance_config[] = {
 {CB_CONFIG_HOPLIMIT,CB_CONFIG_TYPE_INT,CB_DEF_HOPLIMIT,&cb_instance_hoplimit_get, &cb_instance_hoplimit_set,CB_ALWAYS_SHOW},
 {CB_CONFIG_MAX_IDLE_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_IDLE_TIME,&cb_instance_max_idle_get, &cb_instance_max_idle_set,CB_ALWAYS_SHOW},
 {CB_CONFIG_MAX_TEST_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_TEST_TIME,&cb_instance_max_test_get, &cb_instance_max_test_set,CB_ALWAYS_SHOW},
+{CB_CONFIG_STARTTLS,CB_CONFIG_TYPE_ONOFF,CB_DEF_STARTTLS,&cb_instance_starttls_get, &cb_instance_starttls_set,CB_ALWAYS_SHOW},
+{CB_CONFIG_BINDMECH,CB_CONFIG_TYPE_STRING,CB_DEF_BINDMECH,&cb_instance_bindmech_get, &cb_instance_bindmech_set,CB_ALWAYS_SHOW},
 {NULL, 0, NULL, NULL, NULL, 0}
 };
 
@@ -256,9 +262,9 @@ void cb_instance_free(cb_backend_instance * inst) {
 		slapi_destroy_mutex(inst->pool->conn.conn_list_mutex);
 		slapi_destroy_mutex(inst->monitor_availability.cpt_lock);
 		slapi_destroy_mutex(inst->monitor_availability.lock_timeLimit);
-		slapi_ch_free((void **) &inst->configDn);
-		slapi_ch_free((void **) &inst->monitorDn);
-		slapi_ch_free((void **) &inst->inst_name);
+		slapi_ch_free_string(&inst->configDn);
+		slapi_ch_free_string(&inst->monitorDn);
+		slapi_ch_free_string(&inst->inst_name);
 		charray_free(inst->every_attribute);
 
 		slapi_ch_free((void **) &inst->bind_pool);
@@ -1324,6 +1330,66 @@ static int cb_instance_bindretry_set(void *arg, void *value, char *errorbuf, int
 }
 
 
+static void *cb_instance_starttls_get(void *arg)
+{
+	cb_backend_instance * inst=(cb_backend_instance *) arg;
+        uintptr_t data;
+
+        PR_RWLock_Rlock(inst->rwl_config_lock);
+        data=inst->pool->starttls;
+        PR_RWLock_Unlock(inst->rwl_config_lock);
+        return (void *) data;
+}
+
+static int cb_instance_starttls_set(void *arg, void *value, char *errorbuf, int phase, int apply)
+{
+	cb_backend_instance * inst=(cb_backend_instance *) arg;
+	int rc = LDAP_SUCCESS;
+
+	if (apply) {
+	        PR_RWLock_Wlock(inst->rwl_config_lock);
+		inst->pool->starttls=(int) ((uintptr_t)value);
+	        PR_RWLock_Unlock(inst->rwl_config_lock);
+		if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
+    			( phase != CB_CONFIG_PHASE_STARTUP )) {
+		    rc=CB_REOPEN_CONN; /* reconnect with the new starttls setting */
+		}
+	}
+	return rc;
+}
+
+static void *cb_instance_bindmech_get(void *arg)
+{
+	cb_backend_instance * inst=(cb_backend_instance *) arg;
+	char * data;
+
+        PR_RWLock_Rlock(inst->rwl_config_lock);
+	data = slapi_ch_strdup(inst->pool->mech);
+        PR_RWLock_Unlock(inst->rwl_config_lock);
+	return data;
+}
+
+static int cb_instance_bindmech_set(void *arg, void *value, char *errorbuf, int phase, int apply)
+{
+	cb_backend_instance * inst=(cb_backend_instance *) arg;
+	int rc=LDAP_SUCCESS;
+
+	if (apply) {
+               	PR_RWLock_Wlock(inst->rwl_config_lock);
+		if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
+    			( phase != CB_CONFIG_PHASE_STARTUP )) {
+
+			/* Dynamic modif */
+			charray_add(&inst->pool->waste_basket,inst->pool->mech);
+			rc=CB_REOPEN_CONN;
+		}
+
+		inst->pool->mech=slapi_ch_strdup((char *) value);
+               	PR_RWLock_Unlock(inst->rwl_config_lock);
+	}
+	return rc;
+}
+
 
 
 /* Finds an entry in a config_info array with the given name.  Returns

+ 1 - 1
ldap/servers/plugins/replication/repl5_connection.c

@@ -1563,7 +1563,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
 	const char  *mech = bind_method_to_mech(conn->bindmethod);
 
 	rc = slapi_ldap_bind(conn->ld, binddn, password, mech, NULL,
-						 &ctrls, NULL);
+						 &ctrls, NULL, NULL);
 
 	if ( rc == LDAP_SUCCESS ) 
 	{

+ 7 - 1
ldap/servers/slapd/sasl_map.c

@@ -440,6 +440,8 @@ sasl_map_check(sasl_map_data *dp, char *sasl_user_and_realm, char **ldap_search_
 	}
 	if (matched) {
 		if (matched == 1) {
+			char escape_base[BUFSIZ];
+			char escape_filt[BUFSIZ];
 			/* Allocate buffers for the returned strings */
 			/* We already computed this, so we could pass it in to speed up a little */
 			size_t userrealmlen = strlen(sasl_user_and_realm); 
@@ -448,7 +450,11 @@ sasl_map_check(sasl_map_data *dp, char *sasl_user_and_realm, char **ldap_search_
 			*ldap_search_filter = (char *) slapi_ch_malloc(userrealmlen + strlen(dp->template_search_filter) + 1);
 			slapd_re_subs(dp->template_base_dn,*ldap_search_base);
 			slapd_re_subs(dp->template_search_filter,*ldap_search_filter);
-			LDAPDebug( LDAP_DEBUG_TRACE, "mapped base dn: %s, filter: %s\n", ldap_search_base, ldap_search_filter, 0 );
+			/* these values are internal regex representations with lots of
+			   unprintable control chars - escape for logging */
+			LDAPDebug( LDAP_DEBUG_TRACE, "mapped base dn: %s, filter: %s\n",
+					   escape_string( *ldap_search_base, escape_base ),
+					   escape_string( *ldap_search_filter, escape_filt ), 0 );
 			ret = 1;
 		} else {
 			LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_check : re_exec failed\n", 0, 0, 0 );

+ 32 - 8
ldap/servers/slapd/saslbind.c

@@ -81,6 +81,21 @@ void nssasl_free(void *ptr)
     slapi_ch_free(&ptr);
 }
 
+static Slapi_ComponentId *sasl_component_id = NULL;
+
+static void generate_component_id()
+{
+    if (NULL == sasl_component_id) {
+        sasl_component_id = generate_componentid(NULL /* Not a plugin */,
+                                                 COMPONENT_SASL);
+    }
+}
+
+static Slapi_ComponentId *sasl_get_component_id()
+{
+    return sasl_component_id;
+}
+
 /* 
  * sasl library callbacks
  */
@@ -238,20 +253,23 @@ static void ids_sasl_user_search(
 )
 {
     Slapi_Entry **entries = NULL;
-    Slapi_PBlock *pb;
+    Slapi_PBlock *pb = NULL;
     int i, ret;
 
     LDAPDebug(LDAP_DEBUG_TRACE, "sasl user search basedn=\"%s\" filter=\"%s\"\n", basedn, filter, 0);
 
     /* TODO: set size and time limits */
-
-    pb = slapi_search_internal(basedn, scope, filter, 
-                               ctrls, attrs, attrsonly);
-    if (pb == NULL) {
-        LDAPDebug(LDAP_DEBUG_TRACE, "null pblock from slapi_search_internal\n", 0, 0, 0);
+    pb = slapi_pblock_new();
+    if (!pb) {
+        LDAPDebug(LDAP_DEBUG_TRACE, "null pblock for search_internal_pb\n", 0, 0, 0);
         goto out;
     }
 
+    slapi_search_internal_set_pb(pb, basedn, scope, filter, attrs, attrsonly, ctrls, 
+                                 NULL, sasl_get_component_id(), 0); 
+
+    slapi_search_internal_pb(pb);
+
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
     if (ret != LDAP_SUCCESS) {
         LDAPDebug(LDAP_DEBUG_TRACE, "sasl user search failed basedn=\"%s\" "
@@ -261,7 +279,11 @@ static void ids_sasl_user_search(
     }
 
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
-    if (entries == NULL) goto out;
+    if ((entries == NULL) || (entries[0] == NULL)) {
+        LDAPDebug(LDAP_DEBUG_TRACE, "sasl user search found no entries\n",
+                  0, 0, 0);
+        goto out;
+    }
 
     for (i = 0; entries[i]; i++) {
         (*foundp)++;
@@ -546,6 +568,9 @@ int ids_sasl_init(void)
     LDAPDebug(LDAP_DEBUG_TRACE, "sasl service fqdn is: %s\n", 
                   serverfqdn, 0, 0);
 
+    /* get component ID for internal operations */
+    generate_component_id();
+
     /* Set SASL memory allocation callbacks */
     sasl_set_alloc(
         (sasl_malloc_t *)slapi_ch_malloc,
@@ -1016,4 +1041,3 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
 
     return;
 }
-

+ 1 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -1103,6 +1103,7 @@ slapi_ldap_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 */
 );
 

+ 1 - 0
ldap/servers/slapd/slapi-private.h

@@ -720,6 +720,7 @@ struct slapi_componentid * plugin_get_default_component_id();
 #define COMPONENT_RESLIMIT	"cn=resource limits,"COMPONENT_BASE_DN
 #define COMPONENT_PWPOLICY	"cn=password policy,"COMPONENT_BASE_DN
 #define COMPONENT_CERT_AUTH	"cn=certificate-based authentication,"COMPONENT_BASE_DN
+#define COMPONENT_SASL		"cn=sasl,"COMPONENT_BASE_DN
 
 /* Component names for logging */
 #define SLAPI_COMPONENT_NAME_NSPR	"Netscape Portable Runtime"

+ 26 - 5
ldap/servers/slapd/util.c

@@ -974,7 +974,17 @@ slapi_ldap_init_ext(
 		ssl_strength = LDAPSSL_AUTH_CERT;
 	    }
 
-	    if (ldapssl_set_strength(ld, ssl_strength) != 0) {
+	    /* Can only use ldapssl_set_strength on and LDAP* already
+	       initialized for SSL - this is not the case when using
+	       startTLS, so we use NULL to set the default for all
+	       new connections */
+	    if (secure == 1) {
+		rc = ldapssl_set_strength(ld, ssl_strength);
+	    } else {
+		rc = ldapssl_set_strength(NULL, ssl_strength);
+	    }
+
+	    if (rc != 0) {
 		int prerr = PR_GetError();
 
 		slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
@@ -1052,6 +1062,7 @@ slapi_ldap_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 */
 )
 {
@@ -1125,8 +1136,8 @@ slapi_ldap_bind(
 	if (msgidp) { /* let caller process result */
 	    *msgidp = mymsgid;
 	} else { /* process results */
-	    if (ldap_result(ld, mymsgid, LDAP_MSG_ALL,
-			    (struct timeval *)0, &result) == -1) {
+            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 "
@@ -1135,8 +1146,18 @@ slapi_ldap_bind(
 				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 [%d.%d] 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,