ldap_pvt_thread_mutex_t ldap_int_sasl_mutex;
#endif
-#ifdef HAVE_CYRUS_SASL2
+#ifdef HAVE_SASL_SASL_H
#include <sasl/sasl.h>
-#define SASL_CONST const
#else
#include <sasl.h>
+#endif
+
+#if SASL_VERSION_MAJOR >= 2
+#define SASL_CONST const
+#else
#define SASL_CONST
#endif
{ SASL_CB_LIST_END, NULL, NULL }
};
+#ifdef HAVE_SASL_VERSION
+#define SASL_BUILD_VERSION ((SASL_VERSION_MAJOR << 24) |\
+ (SASL_VERSION_MINOR << 16) | SASL_VERSION_STEP)
+
+ { int rc;
+ sasl_version( NULL, &rc );
+ if ( ((rc >> 16) != ((SASL_VERSION_MAJOR << 8)|SASL_VERSION_MINOR)) ||
+ (rc & 0xffff) < SASL_VERSION_STEP) {
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( TRANSPORT, INFO,
+ "ldap_int_sasl_init: SASL version mismatch, got %x, wanted %x.\n",
+ rc, SASL_BUILD_VERSION, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "ldap_int_sasl_init: SASL version mismatch, got %x, wanted %x.\n",
+ rc, SASL_BUILD_VERSION, 0 );
+#endif
+ return -1;
+ }
+ }
+#endif
if ( sasl_initialized ) {
return 0;
}
struct sb_sasl_data {
sasl_conn_t *sasl_context;
+ unsigned *sasl_maxbuf;
Sockbuf_Buf sec_buf_in;
Sockbuf_Buf buf_in;
Sockbuf_Buf buf_out;
ber_pvt_sb_buf_init( &p->buf_in );
ber_pvt_sb_buf_init( &p->buf_out );
if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, SASL_MIN_BUFF_SIZE ) < 0 ) {
+ LBER_FREE( p );
errno = ENOMEM;
return -1;
}
+ sasl_getprop( p->sasl_context, SASL_MAXOUTBUF,
+ (SASL_CONST void **) &p->sasl_maxbuf );
sbiod->sbiod_pvt = p;
assert( sbiod != NULL );
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
/*
* SASLv2 encode/decode buffers are managed by
* libsasl2. Ensure they are not freed by liblber.
}
static ber_len_t
-sb_sasl_pkt_length( const unsigned char *buf, int debuglevel )
+sb_sasl_pkt_length( const unsigned char *buf, unsigned max, int debuglevel )
{
ber_len_t size;
| buf[2] << 8
| buf[3];
- /* we really should check against actual buffer size set
- * in the secopts.
- */
if ( size > SASL_MAX_BUFF_SIZE ) {
/* somebody is trying to mess me up. */
ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
"sb_sasl_pkt_length: received illegal packet length "
"of %lu bytes\n", (unsigned long)size );
size = 16; /* this should lead to an error. */
+ } else if ( size > max ) {
+ ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
+ "sb_sasl_pkt_length: received packet length "
+ "of %lu exceeds negotiated max of %lu bytes\n", (unsigned long)size, (unsigned long)max );
}
return size + 4; /* include the size !!! */
/* Drop a processed packet from the input buffer */
static void
-sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
+sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, unsigned max, int debuglevel )
{
ber_slen_t len;
if ( len >= 4 ) {
sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
- debuglevel);
+ max, debuglevel);
}
else {
sec_buf_in->buf_end = 0;
if ( len == 0 )
return bufptr;
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
ber_pvt_sb_buf_init( &p->buf_in );
#else
ber_pvt_sb_buf_destroy( &p->buf_in );
/* The new packet always starts at p->sec_buf_in.buf_base */
ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
- sbiod->sbiod_sb->sb_debug );
+ *p->sasl_maxbuf, sbiod->sbiod_sb->sb_debug );
/* Grow the packet buffer if neccessary */
if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) &&
p->sec_buf_in.buf_end,
(SASL_CONST char **)&p->buf_in.buf_base,
(unsigned *)&p->buf_in.buf_end );
+
+ /* Drop the packet from the input buffer */
+ sb_sasl_drop_packet( &p->sec_buf_in,
+ *p->sasl_maxbuf, sbiod->sbiod_sb->sb_debug );
+
if ( ret != SASL_OK ) {
ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
"sb_sasl_read: failed to decode packet: %s\n",
sasl_errstring( ret, NULL, NULL ) );
- sb_sasl_drop_packet( &p->sec_buf_in,
- sbiod->sbiod_sb->sb_debug );
errno = EIO;
return -1;
}
- /* Drop the packet from the input buffer */
- sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
-
p->buf_in.buf_size = p->buf_in.buf_end;
bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
}
/* now encode the next packet. */
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
ber_pvt_sb_buf_init( &p->buf_out );
#else
ber_pvt_sb_buf_destroy( &p->buf_out );
#endif
+ if ( len > *p->sasl_maxbuf - 100 )
+ len = *p->sasl_maxbuf - 100; /* For safety margin */
ret = sasl_encode( p->sasl_context, buf, len,
(SASL_CONST char **)&p->buf_out.buf_base,
(unsigned *)&p->buf_out.buf_size );
int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
{
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, ENTRY, "ldap_pvt_sasl_install\n", 0, 0, 0 );
+#else
Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n",
0, 0, 0 );
+#endif
/* don't install the stuff unless security has been negotiated */
int rc;
sasl_conn_t *ctx;
- sasl_callback_t *session_callbacks =
- LDAP_CALLOC( 2, sizeof( sasl_callback_t ) );
-
- if( session_callbacks == NULL ) return LDAP_NO_MEMORY;
-
- session_callbacks[0].id = SASL_CB_USER;
- session_callbacks[0].proc = NULL;
- session_callbacks[0].context = ld;
-
- session_callbacks[1].id = SASL_CB_LIST_END;
- session_callbacks[1].proc = NULL;
- session_callbacks[1].context = NULL;
-
assert( lc->lconn_sasl_ctx == NULL );
if ( host == NULL ) {
return ld->ld_errno;
}
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
rc = sasl_client_new( "ldap", host, NULL, NULL,
- session_callbacks, 0, &ctx );
+ NULL, 0, &ctx );
#else
- rc = sasl_client_new( "ldap", host, session_callbacks,
+ rc = sasl_client_new( "ldap", host, NULL,
SASL_SECURITY_LAYER, &ctx );
#endif
- LDAP_FREE( session_callbacks );
if ( rc != SASL_OK ) {
ld->ld_errno = sasl_err2ldap( rc );
return ld->ld_errno;
}
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, DETAIL1, "ldap_int_sasl_open: host=%s\n",
+ host, 0, 0 );
+#else
Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: host=%s\n",
host, 0, 0 );
+#endif
lc->lconn_sasl_ctx = ctx;
if( ssf ) {
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
(void) sasl_setprop( ctx, SASL_SSF_EXTERNAL,
(void *) &ssf );
#else
(void) sasl_setprop( ctx, SASL_SSF_EXTERNAL,
(void *) &extprops );
#endif
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "ldap_int_sasl_open: ssf=%ld\n", (long) ssf, 0, 0 );
+#else
Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: ssf=%ld\n",
(long) ssf, 0, 0 );
+#endif
}
return LDAP_SUCCESS;
struct berval ccred;
ber_socket_t sd;
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, ARGS, "ldap_int_sasl_bind: %s\n",
+ mechs ? mechs : "<null>", 0, 0 );
+#else
Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n",
mechs ? mechs : "<null>", 0, 0 );
+#endif
/* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
if (ld->ld_version < LDAP_VERSION3) {
do {
saslrc = sasl_client_start( ctx,
mechs,
-#ifndef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR < 2
NULL,
#endif
&prompts,
}
}
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
/* XXX the application should free interact results. */
if ( prompts != NULL && prompts->result != NULL ) {
LDAP_FREE( (void *)prompts->result );
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
ld->ld_errno = sasl_err2ldap( saslrc );
+#if SASL_VERSION_MAJOR >= 2
+ ld->ld_error = (char *)sasl_errdetail( ctx );
+#endif
return ld->ld_errno;
}
rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred );
if ( ccred.bv_val != NULL ) {
-#ifndef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR < 2
LDAP_FREE( ccred.bv_val );
#endif
ccred.bv_val = NULL;
if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
if( scred && scred->bv_len ) {
/* and server provided us with data? */
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
+ rc, saslrc, scred->bv_len );
+#else
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
+#endif
ber_bvfree( scred );
}
return ld->ld_errno;
/* we're done, no need to step */
if( scred && scred->bv_len ) {
/* but server provided us with data! */
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
+ rc, saslrc, scred->bv_len );
+#else
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
+#endif
ber_bvfree( scred );
return ld->ld_errno = LDAP_LOCAL_ERROR;
}
(SASL_CONST char **)&ccred.bv_val,
&credlen );
- Debug( LDAP_DEBUG_TRACE, "sasl_client_start: %d\n",
+#ifdef NEW_LOGGING
+ LDAP_LOG ( TRANSPORT, DETAIL1,
+ "ldap_int_sasl_bind: sasl_client_step: %d\n", saslrc,0,0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "sasl_client_step: %d\n",
saslrc, 0, 0 );
+#endif
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
/* XXX the application should free interact results. */
if ( prompts != NULL && prompts->result != NULL ) {
LDAP_FREE( (void *)prompts->result );
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
ld->ld_errno = sasl_err2ldap( saslrc );
+#if SASL_VERSION_MAJOR >= 2
+ ld->ld_error = (char *)sasl_errdetail( ctx );
+#endif
return ld->ld_errno;
}
} while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
}
if ( saslrc != SASL_OK ) {
+#if SASL_VERSION_MAJOR >= 2
+ ld->ld_error = (char *)sasl_errdetail( ctx );
+#endif
return ld->ld_errno = sasl_err2ldap( saslrc );
}
fprintf( stderr, "SASL username: %s\n", data );
}
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
saslrc = sasl_getprop( ctx, SASL_DEFUSERREALM, (SASL_CONST void **) &data );
#else
saslrc = sasl_getprop( ctx, SASL_REALM, (SASL_CONST void **) &data );
{
int sc;
sasl_conn_t *ctx;
-#ifndef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR < 2
sasl_external_properties_t extprops;
#endif
return LDAP_LOCAL_ERROR;
}
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, &ssf );
+ if ( sc == SASL_OK )
+ sc = sasl_setprop( ctx, SASL_AUTH_EXTERNAL, authid );
#else
memset( &extprops, '\0', sizeof(extprops) );
extprops.ssf = ssf;
} else if( !strncasecmp(props[i],
"minssf=", sizeof("minssf")) )
{
- if( isdigit( props[i][sizeof("minssf")] ) ) {
+ if( isdigit( (unsigned char) props[i][sizeof("minssf")] ) ) {
got_min_ssf++;
min_ssf = atoi( &props[i][sizeof("minssf")] );
} else {
} else if( !strncasecmp(props[i],
"maxssf=", sizeof("maxssf")) )
{
- if( isdigit( props[i][sizeof("maxssf")] ) ) {
+ if( isdigit( (unsigned char) props[i][sizeof("maxssf")] ) ) {
got_max_ssf++;
max_ssf = atoi( &props[i][sizeof("maxssf")] );
} else {
} else if( !strncasecmp(props[i],
"maxbufsize=", sizeof("maxbufsize")) )
{
- if( isdigit( props[i][sizeof("maxbufsize")] ) ) {
+ if( isdigit( (unsigned char) props[i][sizeof("maxbufsize")] ) ) {
got_maxbufsize++;
maxbufsize = atoi( &props[i][sizeof("maxbufsize")] );
} else {
case LDAP_OPT_X_SASL_SSF_EXTERNAL: {
int sc;
-#ifndef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR < 2
sasl_external_properties_t extprops;
#endif
sasl_conn_t *ctx;
return -1;
}
-#ifdef HAVE_CYRUS_SASL2
+#if SASL_VERSION_MAJOR >= 2
sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL, arg);
#else
memset(&extprops, 0L, sizeof(extprops));