struct sockbuf; /* avoid pulling in <lber.h> */
LDAP_F (int) ldap_pvt_sasl_install LDAP_P(( struct sockbuf *, void * ));
+LDAP_F (int) ldap_pvt_sasl_remove LDAP_P(( struct sockbuf * ));
#endif /* HAVE_CYRUS_SASL */
#define LDAP_PVT_SASL_LOCAL_SSF 71 /* SSF for Unix Domain Sockets */
return LDAP_SUCCESS;
}
+void ldap_pvt_sasl_remove( Sockbuf *sb )
+{
+ ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_sasl,
+ LBER_SBIOD_LEVEL_APPLICATION );
+#ifdef LDAP_DEBUG
+ ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
+ LBER_SBIOD_LEVEL_APPLICATION );
+#endif
+}
+
static int
sasl_err2ldap( int saslerr )
{
/* If we already have a context, shut it down */
if( ctx ) {
+ int msgid;
+ LDAPMessage *result;
/* Do an anonymous bind to kill the server's context */
- rc = ldap_simple_bind_s( ld, "", NULL );
+ msgid = ldap_simple_bind( ld, "", NULL );
/* dispose of the old context */
ldap_int_sasl_close( ld, ld->ld_defconn );
+ ldap_pvt_sasl_remove( ld->ld_sb );
+
+ /* The reply is sent in the clear, we can't read it
+ * until after the context and sockbuf are torn down
+ */
+ rc = ldap_result( ld, msgid, 1, NULL, &result );
+ ldap_msgfree( result );
}
rc = ldap_int_sasl_open( ld, ld->ld_defconn,
int rc;
switch (saslerr) {
+ case SASL_OK:
+ rc = LDAP_SUCCESS;
+ break;
case SASL_CONTINUE:
rc = LDAP_SASL_BIND_IN_PROGRESS;
break;
int slap_sasl_reset( Connection *conn )
{
-#ifdef HAVE_CYRUS_SASL
+ int rc = LDAP_SUCCESS;
sasl_conn_t *ctx = conn->c_sasl_context;
-
- if( ctx != NULL ) {
+ slap_ssf_t ssf = 0;
+ const char *authid = NULL;
+#ifdef HAVE_CYRUS_SASL
+#if SASL_VERSION_MAJOR >= 2
+ sasl_getprop( ctx, SASL_SSF_EXTERNAL, &ssf );
+ sasl_getprop( ctx, SASL_AUTH_EXTERNAL, &authid );
+ if ( authid ) authid = ch_strdup( authid );
+#else
+ /* we can't retrieve the external properties from SASL 1.5.
+ * we can get it again from the underlying TLS or IPC connection,
+ * but it's simpler just to ignore it since 1.5 is obsolete.
+ */
+#endif
+ rc = slap_sasl_close( conn );
+ ldap_pvt_sasl_remove( conn->c_sb );
+ if ( rc == LDAP_SUCCESS ) {
+ rc = slap_sasl_open( conn );
}
+ if ( rc == LDAP_SUCCESS ) {
+ rc = slap_sasl_external( conn, ssf, authid );
+ }
+ if ( authid ) ch_free( authid );
#endif
- /* must return "anonymous" */
- return LDAP_SUCCESS;
+ return rc;
}
char ** slap_sasl_mechs( Connection *conn )