ITS#537: lber io rewrite from Gambor Gombas.

Copyright 2000 Gábor Gombás. All rights reserved.
This is free software. You may redistribute and use it under the same
terms as OpenLDAP itself.
This commit is contained in:
Kurt Zeilenga 2000-06-01 20:59:21 +00:00
parent 1605a04509
commit 2e0912622b
27 changed files with 1554 additions and 1325 deletions

View file

@ -123,11 +123,26 @@ typedef struct lber_memory_fns {
BER_MEMFREE_FN bmf_free;
} BerMemoryFunctions;
/* LBER Sockbuf options */
#define LBER_TO_FILE 0x01 /* to a file referenced by sb_fd */
#define LBER_TO_FILE_ONLY 0x02 /* only write to file, not network */
#define LBER_MAX_INCOMING_SIZE 0x04 /* impose limit on incoming stuff */
#define LBER_NO_READ_AHEAD 0x08 /* read only as much as requested */
/* LBER Sockbuf_IO options */
#define LBER_SB_OPT_GET_FD 1
#define LBER_SB_OPT_SET_FD 2
#define LBER_SB_OPT_HAS_IO 3
#define LBER_SB_OPT_SET_NONBLOCK 4
#define LBER_SB_OPT_UDP_GET_SRC 5
#define LBER_SB_OPT_UDP_SET_DST 6
#define LBER_SB_OPT_GET_SSL 7
#define LBER_SB_OPT_DATA_READY 8
#define LBER_SB_OPT_SET_READAHEAD 9
#define LBER_SB_OPT_DRAIN 10
#define LBER_SB_OPT_NEEDS_READ 11
#define LBER_SB_OPT_NEEDS_WRITE 12
/* Largest option used by the library */
#define LBER_SB_OPT_OPT_MAX 12
/* LBER IO operations stacking levels */
#define LBER_SBIOD_LEVEL_PROVIDER 10
#define LBER_SBIOD_LEVEL_TRANSPORT 20
#define LBER_SBIOD_LEVEL_APPLICATION 30
/* get/set options for Sockbuf */
#define LBER_OPT_SOCKBUF_DESC 0x1000
@ -145,6 +160,43 @@ typedef struct berelement BerElement;
typedef struct sockbuf Sockbuf;
typedef struct seqorset Seqorset;
typedef struct sockbuf_io Sockbuf_IO;
/* Structure for LBER IO operarion descriptor */
typedef struct sockbuf_io_desc {
int sbiod_level;
Sockbuf *sbiod_sb;
Sockbuf_IO *sbiod_io;
void *sbiod_pvt;
struct sockbuf_io_desc *sbiod_next;
} Sockbuf_IO_Desc;
/* Structure for LBER IO operation functions */
struct sockbuf_io {
int (*sbi_setup)( Sockbuf_IO_Desc *sbiod, void *arg );
int (*sbi_remove)( Sockbuf_IO_Desc *sbiod );
int (*sbi_ctrl)( Sockbuf_IO_Desc *sbiod, int opt, void *arg);
ber_slen_t (*sbi_read)( Sockbuf_IO_Desc *sbiod, void *buf,
ber_len_t len );
ber_slen_t (*sbi_write)( Sockbuf_IO_Desc *sbiod, void *buf,
ber_len_t len );
int (*sbi_close)( Sockbuf_IO_Desc *sbiod );
};
/* Helper macros for LBER IO functions */
#define LBER_SBIOD_READ_NEXT( sbiod, buf, len ) \
( (sbiod)->sbiod_next->sbiod_io->sbi_read( (sbiod)->sbiod_next, \
buf, len ) )
#define LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ) \
( (sbiod)->sbiod_next->sbiod_io->sbi_write( (sbiod)->sbiod_next, \
buf, len ) )
#define LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ) \
( (sbiod)->sbiod_next ? \
( (sbiod)->sbiod_next->sbiod_io->sbi_ctrl( \
(sbiod)->sbiod_next, opt, arg ) ) : 0 )
/* structure for returning a sequence of octet strings + length */
typedef struct berval {
ber_len_t bv_len;
@ -428,16 +480,38 @@ ber_set_option LDAP_P((
* LBER sockbuf.c
*/
LIBLBER_F( Sockbuf * )
ber_sockbuf_alloc( void );
LIBLBER_F( Sockbuf * )
ber_sockbuf_alloc_fd(
ber_socket_t fd );
ber_sockbuf_alloc LDAP_P((
void ));
LIBLBER_F( void )
ber_sockbuf_free(
Sockbuf *sb );
ber_sockbuf_free LDAP_P((
Sockbuf *sb ));
LIBLBER_F( int )
ber_sockbuf_add_io LDAP_P((
Sockbuf *sb,
Sockbuf_IO *sbio,
int layer,
void *arg ));
LIBLBER_F( int )
ber_sockbuf_remove_io LDAP_P((
Sockbuf *sb,
Sockbuf_IO *sbio,
int layer ));
LIBLBER_F( int )
ber_sockbuf_ctrl LDAP_P((
Sockbuf *sb,
int opt,
void *arg ));
LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_tcp;
LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_udp;
LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_readahead;
LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_fd;
LIBLBER_F( Sockbuf_IO ) ber_sockbuf_io_debug;
/*
* LBER memory.c

View file

@ -20,6 +20,13 @@
LDAP_BEGIN_DECL
typedef struct sockbuf_buf {
ber_len_t buf_size;
ber_len_t buf_ptr;
ber_len_t buf_end;
char *buf_base;
} Sockbuf_Buf;
/*
* bprint.c
*/
@ -32,6 +39,27 @@ ber_pvt_log_printf LDAP_P((
const char *fmt,
... )) LDAP_GCCATTR((format(printf, 3, 4)));
/*
* sockbuf.c
*/
LIBLBER_F( ber_slen_t )
ber_pvt_sb_do_write LDAP_P(( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ));
LIBLBER_F( void )
ber_pvt_sb_buf_init LDAP_P(( Sockbuf_Buf *buf ));
LIBLBER_F( void )
ber_pvt_sb_buf_destroy LDAP_P(( Sockbuf_Buf *buf ));
LIBLBER_F( int )
ber_pvt_sb_grow_buffer LDAP_P(( Sockbuf_Buf *buf, ber_len_t minsize ));
LIBLBER_F( ber_len_t )
ber_pvt_sb_copy_out LDAP_P(( Sockbuf_Buf *sbb, char *buf, ber_len_t len ));
LIBLBER_F( int )
ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb ));
LDAP_END_DECL
#endif

View file

@ -47,6 +47,7 @@ main( int argc, char **argv )
BerElement *ber;
Sockbuf *sb;
int fd;
/* enable debugging */
int ival = -1;
@ -62,7 +63,10 @@ main( int argc, char **argv )
cshow( stdout );
#endif
sb = ber_sockbuf_alloc_fd( fileno(stdin) );
sb = ber_sockbuf_alloc();
fd = fileno( stdin );
ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER,
(void *)&fd );
if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
perror( "ber_alloc_t" );

View file

@ -75,7 +75,9 @@ main( int argc, char **argv )
fd = fileno(stdout);
#endif
sb = ber_sockbuf_alloc_fd( fd );
sb = ber_sockbuf_alloc();
ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd, LBER_SBIOD_LEVEL_PROVIDER,
(void *)&fd );
if( sb == NULL ) {
perror( "ber_sockbuf_alloc_fd" );

View file

@ -64,7 +64,7 @@ BerRead(
assert( SOCKBUF_VALID( sb ) );
while ( len > 0 ) {
if ( (c = ber_pvt_sb_read( sb, buf, len )) <= 0 ) {
if ( (c = ber_int_sb_read( sb, buf, len )) <= 0 ) {
if ( nread > 0 )
break;
return( c );
@ -232,26 +232,15 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
if ( sb->sb_debug ) {
ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
"ber_flush: %ld bytes to sd %ld%s\n", towrite,
(long) sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
: "" );
(long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ?
" (re-flush)" : "" );
ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
ber->ber_rwptr, towrite );
}
#if HAVE_WRITE
if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
rc = write( sb->sb_fd, ber->ber_rwptr, towrite );
if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
if ( freeit )
ber_free( ber, 1 );
return( (int)rc );
}
}
#endif
nwritten = 0;
do {
rc = ber_pvt_sb_write( sb, ber->ber_rwptr, towrite );
rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
if (rc<=0) {
return -1;
}
@ -446,7 +435,7 @@ get_tag( Sockbuf *sb )
assert( sb != NULL );
assert( SOCKBUF_VALID( sb ) );
if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
if ( ber_int_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
@ -455,7 +444,7 @@ get_tag( Sockbuf *sb )
tagp = (char *) &tag;
tagp[0] = xbyte;
for ( i = 1; i < sizeof(ber_tag_t); i++ ) {
if ( ber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
if ( ber_int_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
tagp[i] = xbyte;
@ -522,7 +511,7 @@ ber_get_next(
if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag)) {
if (ber->ber_rwptr == (char *) &ber->ber_tag) {
if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0)
return LBER_DEFAULT;
if ((ber->ber_rwptr[0] & LBER_BIG_TAG_MASK)
!= LBER_BIG_TAG_MASK) {
@ -534,7 +523,7 @@ ber_get_next(
}
do {
/* reading the tag... */
if (ber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0)
if (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0)
return LBER_DEFAULT;
if (! (ber->ber_rwptr[0] & LBER_MORE_TAG_MASK) ) {
ber->ber_tag>>=sizeof(ber->ber_tag) -
@ -550,7 +539,7 @@ ber_get_next(
get_lenbyte:
if (ber->ber_rwptr==(char *) &ber->ber_usertag) {
unsigned char c;
if (ber_pvt_sb_read( sb, (char *) &c, 1)<=0)
if (ber_int_sb_read( sb, (char *) &c, 1)<=0)
return LBER_DEFAULT;
if (c & 0x80U) {
int len = c & 0x7fU;
@ -611,7 +600,7 @@ fill_buffer:
to_go = ber->ber_end - ber->ber_rwptr;
assert( to_go > 0 );
res = ber_pvt_sb_read( sb, ber->ber_rwptr, to_go );
res = ber_int_sb_read( sb, ber->ber_rwptr, to_go );
if (res<=0)
return LBER_DEFAULT;
ber->ber_rwptr+=res;

View file

@ -28,15 +28,15 @@ LIBLBER_F (BER_ERRNO_FN) ber_int_errno_fn;
struct lber_options {
short lbo_valid;
unsigned short lbo_options;
int lbo_debug;
};
#define LBER_UNINITIALIZED 0x0
#define LBER_INITIALIZED 0x1
#define LBER_VALID_BERELEMENT 0x2
#define LBER_VALID_SOCKBUF 0x3
unsigned short lbo_options;
int lbo_debug;
};
LIBLBER_F (struct lber_options) ber_int_options;
#define ber_int_debug ber_int_options.lbo_debug
@ -62,106 +62,21 @@ struct berelement {
};
#define BER_VALID(ber) ((ber)->ber_valid==LBER_VALID_BERELEMENT)
#define ber_pvt_ber_bytes(ber) ((ber)->ber_ptr - (ber)->ber_buf)
#define ber_pvt_ber_remaining(ber) ((ber)->ber_end - (ber)->ber_ptr)
struct sockbuf;
struct sockbuf_io {
int (*sbi_setup)( struct sockbuf * sb, void *arg );
int (*sbi_remove)( struct sockbuf *sb );
ber_slen_t (*sbi_read)( struct sockbuf *sb, void *buf, ber_len_t len );
ber_slen_t (*sbi_write)( struct sockbuf *sb, void *buf, ber_len_t len );
int (*sbi_close)( struct sockbuf *sb );
};
struct sockbuf_sec {
int (*sbs_setup)( struct sockbuf * sb, void *arg );
int (*sbs_remove)( struct sockbuf *sb );
long (*sbs_protect)( struct sockbuf *sb, char *in, long *ilen,
char *out, long olen );
long (*sbs_release)( struct sockbuf *sb, char *in, long ilen,
char *out0, long olen0, char *out1, long olen1 );
};
struct sockbuf_buf {
ber_len_t buf_size;
ber_len_t buf_ptr;
ber_len_t buf_end;
char *buf_base;
};
typedef struct sockbuf_io Sockbuf_IO;
typedef struct sockbuf_sec Sockbuf_Sec;
typedef struct sockbuf_buf Sockbuf_Buf;
LIBLBER_F( Sockbuf_IO ) ber_pvt_sb_io_tcp;
LIBLBER_F( Sockbuf_IO ) ber_pvt_sb_io_udp;
struct sockbuf {
struct lber_options sb_opts;
Sockbuf_IO_Desc *sb_iod; /* I/O functions */
#define sb_valid sb_opts.lbo_valid
#define sb_options sb_opts.lbo_options
#define sb_debug sb_opts.lbo_debug
int sb_non_block:1;
int sb_read_ahead:1;
int sb_buf_ready:1;
int sb_trans_ready:1;
int sb_sec_ready:1;
/* these bits indicate if the transport layer
* needs to read or write
*/
ber_socket_t sb_fd;
int sb_trans_needs_read:1;
int sb_trans_needs_write:1;
int sb_fd;
void *sb_iodata; /* transport-layer data pointer */
Sockbuf_IO *sb_io; /* I/O functions */
#ifdef LDAP_SASL
void *sb_sdata; /* security-layer data pointer */
Sockbuf_Sec *sb_sec;
#endif
ber_socket_t sb_sd;
#ifdef DEADWOOD
long sb_max_incoming;
#endif
Sockbuf_Buf sb_buf;
#ifdef LDAP_SASL
Sockbuf_Buf sb_sec_buf_in;
Sockbuf_Buf sb_sec_buf_out;
ber_len_t sb_sec_prev_len;
#endif
};
#define SOCKBUF_VALID(ber) ((sb)->sb_valid==LBER_VALID_SOCKBUF)
/* these should be internal ie: ber_int_* */
#define ber_pvt_sb_get_desc( sb ) ((sb)->sb_sd)
#define ber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val))
#define ber_pvt_sb_in_use( sb ) ((sb)->sb_sd != AC_SOCKET_INVALID)
#ifdef USE_SASL
#define ber_pvt_sb_data_ready( sb ) \
(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready))
#else
#define ber_pvt_sb_data_ready( sb ) \
(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready))
#endif
#define ber_pvt_sb_needs_read( sb ) \
((sb)->sb_trans_needs_read)
#define ber_pvt_sb_needs_write( sb ) \
((sb)->sb_trans_needs_write)
#define SOCKBUF_VALID( sb ) ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
#define READBUFSIZ 8192
@ -245,51 +160,20 @@ LIBLBER_F (BerMemoryFunctions *) ber_int_memory_fns;
/* sockbuf.c */
/* these should be ber_int*() functions */
LIBLBER_F( int )
ber_int_sb_init LDAP_P(( Sockbuf *sb ));
LIBLBER_F( int )
ber_pvt_sb_init LDAP_P(( Sockbuf *sb ));
ber_int_sb_close LDAP_P(( Sockbuf *sb ));
LIBLBER_F( int )
ber_pvt_sb_destroy LDAP_P(( Sockbuf *sb ));
#ifdef USE_SASL
LIBLBER_F( int )
ber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg ));
LIBLBER_F( int )
ber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb ));
#endif
LIBLBER_F( int )
ber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg ));
LIBLBER_F( int )
ber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb ));
LIBLBER_F( int )
ber_pvt_sb_close LDAP_P((Sockbuf *sb ));
LIBLBER_F( int )
ber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb ));
LIBLBER_F( int )
ber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh ));
ber_int_sb_destroy LDAP_P(( Sockbuf *sb ));
LIBLBER_F( ber_slen_t )
ber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
LIBLBER_F( ber_slen_t )
ber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
LIBLBER_F( int )
ber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr ));
LIBLBER_F( void * )
ber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb ));
LIBLBER_F( int )
ber_pvt_socket_set_nonblock LDAP_P(( ber_socket_t sd, int nb ));
ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
LDAP_END_DECL

File diff suppressed because it is too large Load diff

View file

@ -180,7 +180,7 @@ do_abandon(
if ( lr != NULL ) {
sb = lr->lr_conn->lconn_sb;
} else {
sb = &ld->ld_sb;
sb = ld->ld_sb;
}
if ( ber_flush( sb, ber, 1 ) != 0 ) {

View file

@ -94,10 +94,20 @@ cldap_open( LDAP_CONST char *host, int port )
ld->ld_cldapnaddr = 0;
ld->ld_cldapaddrs = NULL;
if (ber_pvt_sb_set_io( &(ld->ld_sb), &ber_pvt_sb_io_udp, NULL )<0) {
if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_udp,
LBER_SBIOD_LEVEL_PROVIDER, (void *)&s ) < 0 ) {
ldap_ld_free(ld, 1, NULL, NULL );
tcp_close( s );
return NULL;
}
if ( ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_readahead,
LBER_SBIOD_LEVEL_PROVIDER, NULL ) < 0 ) {
ldap_ld_free( ld, 1, NULL, NULL );
return NULL;
}
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( ld->ld_sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
#endif
ld->ld_version = LDAP_VERSION2;
@ -168,7 +178,8 @@ cldap_open( LDAP_CONST char *host, int port )
DO_RETURN( NULL );
}
ber_pvt_sb_udp_set_dst( &ld->ld_sb, ld->ld_cldapaddrs[0] );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
ld->ld_cldapaddrs[0] );
cldap_setretryinfo( ld, 0, 0 );
@ -229,8 +240,8 @@ cldap_search_s( LDAP *ld,
--ld->ld_msgid; /* use same id as before */
}
ber_pvt_sb_udp_set_dst( &(ld->ld_sb),
ld->ld_cldapaddrs[ cri.cri_useaddr ] );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)ld->ld_cldapaddrs[cri.cri_useaddr] );
Debug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n",
cri.cri_try, inet_ntoa( ((struct sockaddr_in *)
@ -287,7 +298,6 @@ static int
cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
struct cldap_retinfo *crip, const char *base )
{
Sockbuf *sb = &ld->ld_sb;
BerElement ber;
char *logdn;
int ret, fromaddr, i;
@ -365,7 +375,7 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
* got a result: determine which server it came from
* decode into ldap message chain
*/
src = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( sb );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_GET_SRC, (void *)&src );
for ( fromaddr = 0; fromaddr < ld->ld_cldapnaddr; ++fromaddr ) {
if ( memcmp( &((struct sockaddr_in *)
@ -401,7 +411,8 @@ cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
if ( i == fromaddr ) {
continue;
}
ber_pvt_sb_udp_set_dst( sb, ld->ld_cldapaddrs[i] );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)ld->ld_cldapaddrs[i] );
Debug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n",
msgid, inet_ntoa( ((struct sockaddr_in *)

View file

@ -273,7 +273,7 @@ ldap_get_kerberosv4_credentials(
return( NULL );
}
if( ! ber_pvt_sb_in_use( &ld->ld_sb ) ) {
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );

View file

@ -20,12 +20,13 @@
#include "../liblber/lber-int.h"
#define ldap_debug (ldap_int_global_options.ldo_debug)
#include "ldap_log.h"
#undef Debug
#define Debug( level, fmt, arg1, arg2, arg3 ) \
ldap_log_printf( NULL, (level), (fmt), (arg1), (arg2), (arg3) )
#include "ldap_log.h"
#include "ldap.h"
#include "ldap_pvt.h"
@ -230,7 +231,7 @@ typedef struct ldapreqinfo {
*/
struct ldap {
Sockbuf ld_sb; /* socket descriptor & buffer */
Sockbuf *ld_sb; /* socket descriptor & buffer */
struct ldapoptions ld_options;
@ -391,8 +392,6 @@ LIBLDAP_F (int) ldap_int_tblsize;
LIBLDAP_F (int) ldap_int_timeval_dup( struct timeval **dest, const struct timeval *tm );
LIBLDAP_F (int) ldap_connect_to_host( LDAP *ld, Sockbuf *sb, const char *host, unsigned long address, int port, int async );
LIBLDAP_F (void) ldap_close_connection( Sockbuf *sb );
#if defined(LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND) || defined(HAVE_TLS) || defined(HAVE_CYRUS_SASL)
LIBLDAP_F (char *) ldap_host_connected_to( Sockbuf *sb );
#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */

View file

@ -161,7 +161,13 @@ ldap_create( LDAP **ldp )
#endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
#endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
ber_pvt_sb_init( &(ld->ld_sb) );
ld->ld_sb = ber_sockbuf_alloc( );
if ( ld->ld_sb == NULL ) {
ldap_free_urllist( ld->ld_options.ldo_defludp );
LDAP_FREE( (char*) ld );
WSACleanup( );
return LDAP_NO_MEMORY;
}
*ldp = ld;
return LDAP_SUCCESS;
@ -283,24 +289,41 @@ open_ldap_connection( LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
switch ( srv->lud_protocol ) {
case LDAP_PROTO_TCP:
rc = ldap_connect_to_host( ld, sb, srv->lud_host,
addr, port, async );
if ( rc == -1 )
return rc;
ber_sockbuf_add_io( sb, &ber_sockbuf_io_tcp,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
break;
case LDAP_PROTO_UDP:
rc = ldap_connect_to_host( ld, sb, srv->lud_host, addr, port, async );
rc = ldap_connect_to_host( ld, sb, srv->lud_host,
addr, port, async );
if ( rc == -1 )
return rc;
ber_sockbuf_add_io( sb, &ber_sockbuf_io_udp,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
break;
#ifdef LDAP_PF_LOCAL
case LDAP_PROTO_LOCAL:
rc = ldap_connect_to_path( ld, sb, srv->lud_host, async );
rc = ldap_connect_to_path( ld, sb, srv->lud_host,
async );
if ( rc == -1 )
return rc;
ber_sockbuf_add_io( sb, &ber_sockbuf_io_fd,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
break;
#endif /* LDAP_PF_LOCAL */
default:
rc = -1;
return -1;
break;
}
if ( rc == -1 ) {
return( rc );
}
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
ber_sockbuf_add_io( sb, &ber_sockbuf_io_readahead,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
#endif
#ifdef HAVE_TLS
if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||

View file

@ -151,12 +151,12 @@ ldap_get_option(
} break;
case LDAP_OPT_DESC:
if(ld == NULL) {
if( ld == NULL || ld->ld_sb == NULL ) {
/* bad param */
break;
}
* (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
return LDAP_OPT_SUCCESS;
case LDAP_OPT_TIMEOUT:

View file

@ -337,7 +337,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
rc = ldap_pvt_connect(ld, s, &sin, async);
if ( (rc == 0) || (rc == -2) ) {
ber_pvt_sb_set_desc( sb, s );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s );
break;
}
@ -350,13 +350,6 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, const char *host,
return rc;
}
void
ldap_close_connection( Sockbuf *sb )
{
ber_pvt_sb_close( sb );
}
#if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND ) || defined( HAVE_TLS ) || defined( HAVE_CYRUS_SASL )
char *
ldap_host_connected_to( Sockbuf *sb )
@ -369,12 +362,14 @@ ldap_host_connected_to( Sockbuf *sb )
struct hostent he_buf;
int local_h_errno;
char *ha_buf=NULL;
ber_socket_t sd;
#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
(void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
len = sizeof( sin );
if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
return( NULL );
}
@ -414,11 +409,13 @@ void
ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) {
FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
if ( !FD_ISSET( sd, &sip->si_writefds )) {
FD_SET( sd, &sip->si_writefds );
}
}
@ -427,11 +424,13 @@ void
ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) {
FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
if ( !FD_ISSET( sd, &sip->si_readfds )) {
FD_SET( sd, &sip->si_readfds );
}
}
@ -440,11 +439,13 @@ void
ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds );
FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
FD_CLR( sd, &sip->si_writefds );
FD_CLR( sd, &sip->si_readfds );
}
@ -452,10 +453,12 @@ int
ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds ));
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
return( FD_ISSET( sd, &sip->si_use_writefds ));
}
@ -463,10 +466,12 @@ int
ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
{
struct selectinfo *sip;
ber_socket_t sd;
sip = (struct selectinfo *)ld->ld_selectinfo;
return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds ));
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
return( FD_ISSET( sd, &sip->si_use_readfds ));
}

View file

@ -208,7 +208,7 @@ ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async)
rc = ldap_pvt_connect(ld, s, &server, async);
if (rc == 0) {
ber_pvt_sb_set_desc( sb, s );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, (void *)&s );
} else {
ldap_pvt_close_socket(ld, s);
}

View file

@ -100,7 +100,7 @@ ldap_send_initial_request(
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
if ( ! ber_pvt_sb_in_use(&ld->ld_sb ) ) {
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );
@ -293,7 +293,7 @@ ldap_new_connection( LDAP *ld, LDAPURLDesc *srvlist, int use_ldsb,
return( NULL );
}
lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
lc->lconn_sb = ( use_ldsb ) ? ld->ld_sb : sb;
if ( connect ) {
for ( srv = srvlist; srv != NULL; srv = srv->lud_next ) {
@ -433,10 +433,6 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
}
}
/* force closure */
ldap_close_connection( lc->lconn_sb );
ber_pvt_sb_destroy( lc->lconn_sb );
if( lc->lconn_ber != NULL ) {
ber_free( lc->lconn_ber, 1 );
}
@ -458,7 +454,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
if ( lc->lconn_krbinstance != NULL ) {
LDAP_FREE( lc->lconn_krbinstance );
}
if ( lc->lconn_sb != &ld->ld_sb ) {
if ( lc->lconn_sb != ld->ld_sb ) {
ber_sockbuf_free( lc->lconn_sb );
}
if( lc->lconn_rebind_queue != NULL) {
@ -493,7 +489,7 @@ ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
( lc->lconn_server->lud_host == NULL ) ? "(null)"
: lc->lconn_server->lud_host,
lc->lconn_server->lud_port, ( lc->lconn_sb ==
&ld->ld_sb ) ? " (default)" : "" );
ld->ld_sb ) ? " (default)" : "" );
}
fprintf( stderr, " refcnt: %d status: %s\n", lc->lconn_refcnt,
( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?

View file

@ -218,7 +218,8 @@ wait4msg(
}
#endif /* LDAP_DEBUG */
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
if ( ber_pvt_sb_data_ready(lc->lconn_sb) ) {
if ( ber_sockbuf_ctrl( lc->lconn_sb,
LBER_SB_OPT_DATA_READY, NULL ) ) {
rc = try_read1msg( ld, msgid, all, lc->lconn_sb,
lc, result );
break;
@ -888,14 +889,16 @@ cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber )
int rc;
ber_tag_t tag;
ber_len_t len;
ber_socket_t sd;
if ( ! ber_pvt_sb_data_ready(&ld->ld_sb) ) {
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
if ( sd != AC_SOCKET_INVALID ) {
/* restored from ldap_select1() in result.c version 1.24 */
fd_set readfds;
if ( ldap_int_tblsize == 0 )
ldap_int_ip_init();
FD_ZERO( &readfds );
FD_SET( ber_pvt_sb_get_desc(&ld->ld_sb), &readfds );
FD_SET( sd, &readfds );
rc = select( ldap_int_tblsize, &readfds, 0, 0, timeout );
if ( rc == -1 || rc == 0 ) {
@ -906,7 +909,7 @@ cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber )
}
/* get the next message */
if ( (tag = ber_get_next( &ld->ld_sb, &len, ber ))
if ( (tag = ber_get_next( ld->ld_sb, &len, ber ))
!= LDAP_TAG_MESSAGE ) {
ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
LDAP_LOCAL_ERROR);

View file

@ -32,6 +32,7 @@
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/errno.h>
#include "ldap-int.h"
@ -349,22 +350,8 @@ ldap_parse_sasl_bind_result(
* Various Cyrus SASL related stuff.
*/
static int sasl_setup( Sockbuf *sb, void *arg );
static int sasl_remove( Sockbuf *sb );
static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t len );
static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len );
static int sasl_close( Sockbuf *sb );
static Sockbuf_IO sasl_io=
{
sasl_setup,
sasl_remove,
sasl_read,
sasl_write,
sasl_close
};
#define HAS_SASL( sb ) ((sb)->sb_io==&sasl_io)
#define MAX_BUFF_SIZE 65536
#define MIN_BUFF_SIZE 4096
static char *
array2str( char **a )
@ -424,79 +411,259 @@ int ldap_pvt_sasl_init( void )
return -1;
}
/*
* SASL encryption support for LBER Sockbufs
*/
struct sb_sasl_data {
sasl_conn_t *sasl_context;
Sockbuf_Buf sec_buf_in;
Sockbuf_Buf buf_in;
Sockbuf_Buf buf_out;
};
static int
sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
struct sb_sasl_data *p;
assert( sbiod != NULL );
p = LBER_MALLOC( sizeof( *p ) );
if ( p == NULL )
return -1;
p->sasl_context = (sasl_conn_t *)arg;
ber_pvt_sb_buf_init( &p->sec_buf_in );
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, MIN_BUFF_SIZE ) < 0 ) {
errno = ENOMEM;
return -1;
}
sbiod->sbiod_pvt = p;
return 0;
}
static int
sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
{
struct sb_sasl_data *p;
assert( sbiod != NULL );
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
ber_pvt_sb_buf_destroy( &p->sec_buf_in );
ber_pvt_sb_buf_destroy( &p->buf_in );
ber_pvt_sb_buf_destroy( &p->buf_out );
LBER_FREE( p );
sbiod->sbiod_pvt = NULL;
return 0;
}
static ber_len_t
sb_sasl_pkt_length( const char *buf, int debuglevel )
{
ber_len_t size;
long tmp;
assert( buf != NULL );
tmp = *((long *)buf);
size = ntohl( tmp );
if ( size > 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. */
}
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 )
{
ber_slen_t len;
len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
if ( len > 0 )
memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
sec_buf_in->buf_end, len );
if ( len >= 4 ) {
sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
debuglevel);
}
else {
sec_buf_in->buf_end = 0;
}
sec_buf_in->buf_ptr = len;
}
static ber_slen_t
sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct sb_sasl_data *p;
ber_slen_t ret, bufptr;
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
/* Are there anything left in the buffer? */
ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
bufptr = ret;
len -= ret;
if ( len == 0 )
return bufptr;
ber_pvt_sb_buf_destroy( &p->buf_in );
/* Read the length of the packet */
while ( p->sec_buf_in.buf_ptr < 4 ) {
ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
4 - p->sec_buf_in.buf_ptr );
#ifdef EINTR
if ( ( ret < 0 ) && ( errno == EINTR ) )
continue;
#endif
if ( ret <= 0 )
return ret;
p->sec_buf_in.buf_ptr += ret;
}
/* 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 );
/* Grow the packet buffer if neccessary */
if ( ( p->sec_buf_in.buf_size < ret ) &&
ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) {
errno = ENOMEM;
return -1;
}
p->sec_buf_in.buf_end = ret;
/* Did we read the whole encrypted packet? */
while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
/* No, we have got only a part of it */
ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
p->sec_buf_in.buf_ptr, ret );
#ifdef EINTR
if ( ( ret < 0 ) && ( errno == EINTR ) )
continue;
#endif
if ( ret <= 0 )
return ret;
p->sec_buf_in.buf_ptr += ret;
}
/* Decode the packet */
ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
p->sec_buf_in.buf_end, &p->buf_in.buf_base,
(unsigned *)&p->buf_in.buf_end );
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, buf + bufptr, len );
return bufptr;
}
static ber_slen_t
sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct sb_sasl_data *p;
int ret;
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
/* Are there anything left in the buffer? */
if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
if ( ret <= 0 )
return ret;
}
/* now encode the next packet. */
ber_pvt_sb_buf_destroy( &p->buf_out );
ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
(unsigned *)&p->buf_out.buf_size );
if ( ret != SASL_OK ) {
ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
"sb_sasl_write: failed to encode packet: %s\n",
sasl_errstring( ret, NULL, NULL ) );
return -1;
}
p->buf_out.buf_end = p->buf_out.buf_size;
ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
if ( ret <= 0 )
return ret;
return len;
}
static int
sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
{
struct sb_sasl_data *p;
p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
if ( opt == LBER_SB_OPT_DATA_READY ) {
if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
return 1;
}
return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
}
Sockbuf_IO ldap_pvt_sockbuf_io_sasl =
{
sb_sasl_setup, /* sbi_setup */
sb_sasl_remove, /* sbi_remove */
sb_sasl_ctrl, /* sbi_ctrl */
sb_sasl_read, /* sbi_read */
sb_sasl_write, /* sbi_write */
NULL /* sbi_close */
};
int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
{
/* don't install the stuff unless security has been negotiated */
if ( !HAS_SASL( sb ) ) {
ber_pvt_sb_clear_io( sb );
ber_pvt_sb_set_io( sb, &sasl_io, ctx_arg );
}
if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
&ldap_pvt_sockbuf_io_sasl ) )
ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
return 0;
}
static int sasl_setup( Sockbuf *sb, void *arg )
{
sb->sb_iodata = arg;
return 0;
}
static int sasl_remove( Sockbuf *sb )
{
return 0;
}
static ber_slen_t sasl_read( Sockbuf *sb, void *buf, ber_len_t buflen )
{
char *recv_tok;
unsigned recv_tok_len;
sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
if ((ber_pvt_sb_io_tcp.sbi_read)( sb, buf, buflen ) != buflen ) {
return -1;
}
if ( sasl_decode( conn, buf, buflen, &recv_tok, &recv_tok_len ) != SASL_OK ) {
return -1;
}
if ( recv_tok_len > buflen ) {
LDAP_FREE( recv_tok );
return -1;
}
memcpy( buf, recv_tok, recv_tok_len );
LDAP_FREE( recv_tok );
return recv_tok_len;
}
static ber_slen_t sasl_write( Sockbuf *sb, void *buf, ber_len_t len )
{
char *wrapped_tok;
unsigned wrapped_tok_len;
sasl_conn_t *conn = (sasl_conn_t *)sb->sb_iodata;
if ( sasl_encode( conn, (const char *)buf, len,
&wrapped_tok, &wrapped_tok_len ) != SASL_OK ) {
return -1;
}
if ((ber_pvt_sb_io_tcp.sbi_write)( sb, wrapped_tok, wrapped_tok_len ) != wrapped_tok_len ) {
LDAP_FREE( wrapped_tok );
return -1;
}
LDAP_FREE( wrapped_tok );
return len;
}
static int sasl_close( Sockbuf *sb )
{
return (ber_pvt_sb_io_tcp.sbi_close)( sb );
return LDAP_SUCCESS;
}
static int
@ -598,11 +765,16 @@ ldap_pvt_sasl_bind(
LDAPControl **cctrls )
{
const char *mech;
int saslrc, rc, ssf = 0;
int saslrc, rc;
sasl_ssf_t *ssf = NULL;
unsigned credlen;
struct berval ccred, *scred;
char *host;
sasl_interact_t *client_interact = NULL;
struct sockaddr_in sin;
socklen_t len;
sasl_security_properties_t secprops;
ber_socket_t sd;
Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
@ -612,15 +784,18 @@ ldap_pvt_sasl_bind(
return ld->ld_errno;
}
if( ! ber_pvt_sb_in_use( &ld->ld_sb ) ) {
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
if ( sd == AC_SOCKET_INVALID ) {
/* not connected yet */
int rc = ldap_open_defconn( ld );
if( rc < 0 ) return ld->ld_errno;
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
}
/* XXX this doesn't work with PF_LOCAL hosts */
host = ldap_host_connected_to( &ld->ld_sb );
host = ldap_host_connected_to( ld->ld_sb );
if ( host == NULL ) {
ld->ld_errno = LDAP_UNAVAILABLE;
@ -631,16 +806,42 @@ ldap_pvt_sasl_bind(
sasl_dispose( &ld->ld_sasl_context );
}
saslrc = sasl_client_new( "ldap", host, callbacks, 0, &ld->ld_sasl_context );
saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER,
&ld->ld_sasl_context );
LDAP_FREE( host );
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
ld->ld_errno = sasl_err2ldap( rc );
ld->ld_errno = sasl_err2ldap( saslrc );
sasl_dispose( &ld->ld_sasl_context );
return ld->ld_errno;
}
len = sizeof( sin );
if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n",
0, 0, 0 );
ld->ld_errno = LDAP_OPERATIONS_ERROR;
return ld->ld_errno;
}
sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin );
len = sizeof( sin );
if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n",
0, 0, 0 );
ld->ld_errno = LDAP_OPERATIONS_ERROR;
return ld->ld_errno;
}
sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin );
memset( &secprops, 0, sizeof( secprops ) );
secprops.min_ssf = ld->ld_options.ldo_sasl_minssf;
secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf;
secprops.security_flags = SASL_SECURITY_LAYER;
secprops.maxbufsize = 65536;
sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops );
ccred.bv_val = NULL;
ccred.bv_len = 0;
@ -702,8 +903,8 @@ ldap_pvt_sasl_bind(
assert ( rc == LDAP_SUCCESS );
if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
== SASL_OK && ssf ) {
ldap_pvt_sasl_install( &ld->ld_sb, ld->ld_sasl_context );
== SASL_OK && ssf && *ssf ) {
ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context );
}
return rc;

View file

@ -235,6 +235,9 @@ bind_prompt( LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
char *dnp;
int authmethod;
printf("rebind for request=%d msgid=%ld url=%s\n",
request, (long) msgid, url );
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
getline( dn, sizeof(dn), stdin,
"re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " );
@ -321,12 +324,12 @@ main( int argc, char **argv )
case 't': /* copy ber's to given file */
copyfname = strdup( optarg );
copyoptions = LBER_TO_FILE;
/* copyoptions = LBER_TO_FILE; */
break;
case 'T': /* only output ber's to given file */
copyfname = strdup( optarg );
copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY);
/* copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */
break;
default:
@ -362,12 +365,12 @@ main( int argc, char **argv )
}
if ( copyfname != NULL ) {
if ( (ld->ld_sb.sb_fd = open( copyfname, O_WRONLY | O_CREAT,
if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY | O_CREAT,
0600 )) == -1 ) {
perror( copyfname );
exit ( EXIT_FAILURE );
}
ld->ld_sb.sb_options = copyoptions;
ld->ld_sb->sb_options = copyoptions;
}
bound = 0;

View file

@ -41,24 +41,11 @@ static char *tls_opt_cacertdir = NULL;
static int tls_opt_require_cert = 0;
static char *tls_opt_ciphersuite = NULL;
#define HAS_TLS( sb ) ((sb)->sb_io==&tls_io)
#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \
(void *)&ldap_pvt_sockbuf_io_tls )
static int tls_setup( Sockbuf *sb, void *arg );
static int tls_remove( Sockbuf *sb );
static ber_slen_t tls_read( Sockbuf *sb, void *buf, ber_len_t len );
static ber_slen_t tls_write( Sockbuf *sb, void *buf, ber_len_t len );
static int tls_close( Sockbuf *sb );
static void tls_report_error( void );
static Sockbuf_IO tls_io=
{
tls_setup,
tls_remove,
tls_read,
tls_write,
tls_close
};
static void tls_info_cb( SSL *ssl, int where, int ret );
static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
@ -243,9 +230,8 @@ get_ca_list( char * bundle, char * dir )
}
static SSL *
alloc_handle( Sockbuf *sb, void *ctx_arg )
alloc_handle( void *ctx_arg )
{
int err;
SSL_CTX *ctx;
SSL *ssl;
@ -266,8 +252,6 @@ alloc_handle( Sockbuf *sb, void *ctx_arg )
if ( tls_opt_trace ) {
SSL_set_info_callback( ssl, tls_info_cb );
}
sb->sb_iodata = ssl;
SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) );
return ssl;
}
@ -293,6 +277,252 @@ update_flags( Sockbuf *sb, SSL * ssl, int rc )
return 0;
}
/*
* TLS support for LBER Sockbufs
*/
struct tls_data {
SSL *ssl;
Sockbuf_IO_Desc *sbiod;
};
extern BIO_METHOD ldap_pvt_sb_bio_method;
static int
sb_tls_setup( Sockbuf_IO_Desc *sbiod, void *arg )
{
struct tls_data *p;
BIO *bio;
assert( sbiod != NULL );
p = LBER_MALLOC( sizeof( *p ) );
if ( p == NULL )
return -1;
p->ssl = (SSL *)arg;
p->sbiod = sbiod;
bio = BIO_new( &ldap_pvt_sb_bio_method );
bio->ptr = (void *)p;
SSL_set_bio( p->ssl, bio, bio );
sbiod->sbiod_pvt = p;
return 0;
}
static int
sb_tls_remove( Sockbuf_IO_Desc *sbiod )
{
struct tls_data *p;
assert( sbiod != NULL );
assert( sbiod->sbiod_pvt != NULL );
p = (struct tls_data *)sbiod->sbiod_pvt;
SSL_free( p->ssl );
LBER_FREE( sbiod->sbiod_pvt );
sbiod->sbiod_pvt = NULL;
return 0;
}
static int
sb_tls_close( Sockbuf_IO_Desc *sbiod )
{
struct tls_data *p;
assert( sbiod != NULL );
assert( sbiod->sbiod_pvt != NULL );
p = (struct tls_data *)sbiod->sbiod_pvt;
SSL_shutdown( p->ssl );
return 0;
}
static int
sb_tls_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
{
struct tls_data *p;
assert( sbiod != NULL );
assert( sbiod->sbiod_pvt != NULL );
p = (struct tls_data *)sbiod->sbiod_pvt;
if ( opt == LBER_SB_OPT_GET_SSL ) {
*((SSL **)arg) = p->ssl;
return 1;
}
return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
}
static ber_slen_t
sb_tls_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct tls_data *p;
ber_slen_t ret;
int err;
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
p = (struct tls_data *)sbiod->sbiod_pvt;
ret = SSL_read( p->ssl, (char *)buf, len );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
err = SSL_get_error( p->ssl, ret );
if (err == SSL_ERROR_WANT_READ ) {
sbiod->sbiod_sb->sb_trans_needs_read = 1;
#ifdef WIN32
errno = EWOULDBLOCK;
#endif
}
else
sbiod->sbiod_sb->sb_trans_needs_read = 0;
return ret;
}
static ber_slen_t
sb_tls_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct tls_data *p;
ber_slen_t ret;
int err;
assert( sbiod != NULL );
assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
p = (struct tls_data *)sbiod->sbiod_pvt;
ret = SSL_write( p->ssl, (char *)buf, len );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
err = SSL_get_error( p->ssl, ret );
if (err == SSL_ERROR_WANT_WRITE ) {
sbiod->sbiod_sb->sb_trans_needs_write = 1;
#ifdef WIN32
errno = EWOULDBLOCK;
#endif
}
else
sbiod->sbiod_sb->sb_trans_needs_write = 0;
return ret;
}
Sockbuf_IO ldap_pvt_sockbuf_io_tls =
{
sb_tls_setup, /* sbi_setup */
sb_tls_remove, /* sbi_remove */
sb_tls_ctrl, /* sbi_ctrl */
sb_tls_read, /* sbi_read */
sb_tls_write, /* sbi_write */
sb_tls_close /* sbi_close */
};
static int
sb_tls_bio_create( BIO *b ) {
b->init = 1;
b->num = 0;
b->ptr = NULL;
b->flags = 0;
return 1;
}
static int
sb_tls_bio_destroy( BIO *b )
{
if ( b == NULL )
return 0;
b->ptr = NULL; /* sb_tls_remove() will free it */
b->init = 0;
b->flags = 0;
return 1;
}
static int
sb_tls_bio_read( BIO *b, char *buf, int len )
{
struct tls_data *p;
int ret;
if ( buf == NULL || len <= 0 )
return 0;
p = (struct tls_data *)b->ptr;
if ( p == NULL || p->sbiod == NULL )
return 0;
ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
BIO_clear_retry_flags( b );
if ( ret < 0 && errno == EWOULDBLOCK )
BIO_set_retry_read( b );
return ret;
}
static int
sb_tls_bio_write( BIO *b, char *buf, int len )
{
struct tls_data *p;
int ret;
if ( buf == NULL || len <= 0 )
return 0;
p = (struct tls_data *)b->ptr;
if ( p == NULL || p->sbiod == NULL )
return 0;
ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, buf, len );
BIO_clear_retry_flags( b );
if ( ret < 0 && errno == EWOULDBLOCK )
BIO_set_retry_write( b );
return ret;
}
static long
sb_tls_bio_ctrl( BIO *b, int cmd, long num, char *ptr )
{
if ( cmd == BIO_CTRL_FLUSH ) {
/* The OpenSSL library needs this */
return 1;
}
return 0;
}
static int
sb_tls_bio_gets( BIO *b, char *buf, int len )
{
return -1;
}
static int
sb_tls_bio_puts( BIO *b, char *str )
{
return sb_tls_bio_write( b, str, strlen( str ) );
}
BIO_METHOD ldap_pvt_sb_bio_method =
{
( 100 | 0x400 ), /* it's a source/sink BIO */
"sockbuf glue",
sb_tls_bio_write,
sb_tls_bio_read,
sb_tls_bio_puts,
sb_tls_bio_gets,
sb_tls_bio_ctrl,
sb_tls_bio_create,
sb_tls_bio_destroy
};
/*
* Call this to do a TLS connect on a sockbuf. ctx_arg can be
* a SSL_CTX * or NULL, in which case the default ctx is used.
@ -313,13 +543,17 @@ ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
SSL *ssl;
if ( HAS_TLS( sb ) ) {
ssl = (SSL *) sb->sb_iodata;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
ssl = alloc_handle( sb, ctx_arg );
ssl = alloc_handle( ctx_arg );
if ( ssl == NULL )
return -1;
ber_pvt_sb_clear_io( sb );
ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
#endif
ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
}
err = SSL_connect( ssl );
@ -335,8 +569,12 @@ ldap_pvt_tls_connect( LDAP *ld, Sockbuf *sb, void *ctx_arg )
ld->ld_error = ldap_strdup(ERR_error_string(err, buf));
}
Debug( LDAP_DEBUG_ANY,"TLS: can't connect.\n",0,0,0);
ber_pvt_sb_clear_io( sb );
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
LBER_SBIOD_LEVEL_TRANSPORT );
#ifdef LDAP_DEBUG
ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT );
#endif
return -1;
}
return 0;
@ -353,13 +591,17 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
SSL *ssl;
if ( HAS_TLS( sb ) ) {
ssl = (SSL *) sb->sb_iodata;
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
} else {
ssl = alloc_handle( sb, ctx_arg );
ssl = alloc_handle( ctx_arg );
if ( ssl == NULL )
return -1;
ber_pvt_sb_clear_io( sb );
ber_pvt_sb_set_io( sb, &tls_io, (void *)ssl );
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" );
#endif
ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_tls,
LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl );
}
err = SSL_accept( ssl );
@ -372,8 +614,12 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg )
return 1;
Debug( LDAP_DEBUG_ANY,"TLS: can't accept.\n",0,0,0 );
tls_report_error();
ber_pvt_sb_clear_io( sb );
ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
ber_sockbuf_remove_io( sb, &ldap_pvt_sockbuf_io_tls,
LBER_SBIOD_LEVEL_TRANSPORT );
#ifdef LDAP_DEBUG
ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
LBER_SBIOD_LEVEL_TRANSPORT );
#endif
return -1;
}
return 0;
@ -390,16 +636,19 @@ ldap_pvt_tls_inplace ( Sockbuf *sb )
void *
ldap_pvt_tls_sb_handle( Sockbuf *sb )
{
if (HAS_TLS( sb ))
return sb->sb_iodata;
else
void *p;
if (HAS_TLS( sb )) {
ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p );
return p;
}
return NULL;
}
void *
ldap_pvt_tls_get_handle( LDAP *ld )
{
return ldap_pvt_tls_sb_handle(&ld->ld_sb);
return ldap_pvt_tls_sb_handle( ld->ld_sb );
}
const char *
@ -568,60 +817,6 @@ ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg )
return LDAP_SUCCESS;
}
static int
tls_setup( Sockbuf *sb, void *arg )
{
sb->sb_iodata = arg;
return 0;
}
static int
tls_remove( Sockbuf *sb )
{
SSL_free( (SSL *) sb->sb_iodata );
return 0;
}
static ber_slen_t
tls_write( Sockbuf *sb, void *buf, ber_len_t sz )
{
int ret = SSL_write( (SSL *)sb->sb_iodata, buf, sz );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
update_flags(sb, (SSL *)sb->sb_iodata, ret );
#ifdef WIN32
if (sb->sb_trans_needs_write)
errno = EWOULDBLOCK;
#endif
return ret;
}
static ber_slen_t
tls_read( Sockbuf *sb, void *buf, ber_len_t sz )
{
int ret = SSL_read( (SSL *)sb->sb_iodata, buf, sz );
#ifdef HAVE_WINSOCK
errno = WSAGetLastError();
#endif
update_flags(sb, (SSL *)sb->sb_iodata, ret );
#ifdef WIN32
if (sb->sb_trans_needs_read)
errno = EWOULDBLOCK;
#endif
return ret;
}
static int
tls_close( Sockbuf *sb )
{
tcp_close( ber_pvt_sb_get_desc( sb ) );
return 0;
}
/* Derived from openssl/apps/s_cb.c */
static void
tls_info_cb( SSL *ssl, int where, int ret )

View file

@ -145,7 +145,7 @@ ldap_ld_free(
}
#endif
ber_pvt_sb_destroy( &(ld->ld_sb) );
ber_sockbuf_free( ld->ld_sb );
LDAP_FREE( (char *) ld );

View file

@ -38,7 +38,6 @@
#include <quipu/ds_error.h>
#include "lber.h"
#include "../../libraries/liblber/lber-int.h" /* get struct sockbuf */
#include "ldap.h"
#include "common.h"
#include "lutil.h" /* Get lutil_detach() */
@ -492,7 +491,7 @@ do_queries(
fd_set readfds;
int rc;
struct timeval timeout;
Sockbuf sb;
Sockbuf *sb;
#ifdef LDAP_CONNECTIONLESS
struct sockaddr saddr, faddr;
struct sockaddr *saddrlist[ 1 ];
@ -515,10 +514,9 @@ do_queries(
conn_init();
}
ber_pvt_sb_init( &sb );
ber_pvt_sb_set_desc( &sb, clientsock );
ber_pvt_sb_set_io( &sb, (udp) ? &ber_pvt_sb_io_udp :
&ber_pvt_sb_io_tcp, NULL );
sb = ber_sockbuf_alloc( );
ber_sockbuf_add_io( sb, (udp) ? &ber_sockbuf_io_udp :
&ber_sockbuf_io_tcp, (void *)&clientsock );
timeout.tv_sec = idletime;
timeout.tv_usec = 0;
for ( ;; ) {
@ -547,7 +545,7 @@ do_queries(
* already waiting for us on the client sock.
*/
if ( ! ber_pvt_sb_data_ready( &sb ) ) {
if ( ! ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
if ( (rc = select( dtblsize, &readfds, 0, 0,
udp ? 0 : &timeout )) < 1 ) {
#ifdef LDAP_DEBUG
@ -573,9 +571,9 @@ do_queries(
}
}
if ( ber_pvt_sb_data_ready( &sb ) ||
if ( ber_sockbuf_ctrl( sb, LBER_SB_OPT_DATA_READY, NULL ) ||
FD_ISSET( clientsock, &readfds ) ) {
client_request( &sb, conns, udp );
client_request( sb, conns, udp );
} else {
if ( (dsaconn = conn_getfd( &readfds )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "No DSA activity!\n",
@ -583,7 +581,7 @@ do_queries(
continue;
}
dsa_response( dsaconn, &sb );
dsa_response( dsaconn, sb );
}
}
/* NOT REACHED */

View file

@ -28,7 +28,6 @@
#include <quipu/dua.h>
#include "lber.h"
#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
@ -89,7 +88,8 @@ client_request(
#ifdef LDAP_CONNECTIONLESS
if ( udp && dosyslog ) {
sai = (struct sockaddr_in *)ber_pvt_sb_udp_get_src( &clientsb );
ber_sockbuf_ctrl( clientsb, LBER_SB_OPT_UDP_GET_SRC,
(void *)&sai );
syslog( LOG_INFO, "UDP request from unknown (%s)",
inet_ntoa( sai->sin_addr ) );
}
@ -193,7 +193,7 @@ client_request(
free( ber.ber_buf );
return;
}
sai = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( &clientsb );
ber_sockbuf_ctrl( clientsb, LBER_SB_OPT_UDP_GET_SRC, (void *)&sai );
if ( get_cldap_msg( msgid, tag,
(struct sockaddr *)sai ) != NULL ) {

View file

@ -24,7 +24,6 @@
#include <quipu/dua.h>
#include "lber.h"
#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
@ -281,7 +280,8 @@ send_ldap_msgresult(
{
#ifdef LDAP_CONNECTIONLESS
if ( m->m_cldap ) {
ber_pvt_sb_udp_set_dst( &sb, &m->m_clientaddr );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&m->m_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
@ -306,7 +306,7 @@ send_ldap_result(
int rc;
#ifdef LDAP_CONNECTIONLESS
int cldap;
cldap = ( sb->sb_io == &ber_pvt_sb_io_udp );
cldap = ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, &ber_sockbuf_io_udp );
#endif
Debug( LDAP_DEBUG_TRACE, "send_ldap_result\n", 0, 0, 0 );

View file

@ -26,7 +26,6 @@
#include <quipu/dua.h>
#include "lber.h"
#include "../../libraries/liblber/lber-int.h" /* get struct berelement */
#include "ldap.h"
#include "common.h"
@ -701,7 +700,8 @@ search_result(
LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
return;
}
ber_pvt_sb_udp_set_dst( sb, &m->m_clientaddr );
ber_sockbuf_ctrl( sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&m->m_clientaddr );
if ( ber_flush( sb, ber, 1 ) != 0 ) {
send_ldap_msgresult( sb, SEARCHRESTAG, m,

View file

@ -16,9 +16,6 @@
#include "slap.h"
/* we need LBER internals */
#include "../../libraries/liblber/lber-int.h"
/* protected by connections_mutex */
static ldap_pvt_thread_mutex_t connections_mutex;
static Connection *connections = NULL;
@ -213,9 +210,12 @@ static Connection* connection_get( ber_socket_t s )
#else
c = NULL;
{
ber_socket_t i;
ber_socket_t i, sd;
for(i=0; i<dtblsize; i++) {
ber_sockbuf_ctrl( connections[i].c_sb,
LBER_SB_OPT_GET_FD, &sd );
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( connections[i].c_sb == 0 );
@ -224,7 +224,7 @@ static Connection* connection_get( ber_socket_t s )
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
assert( connections[i].c_conn_state == SLAP_C_INVALID );
assert( !ber_pvt_sb_in_use( connections[i].c_sb ) );
assert( sd == AC_SOCKET_INVALID );
continue;
}
@ -232,7 +232,7 @@ static Connection* connection_get( ber_socket_t s )
* so don't assert details here.
*/
if( ber_pvt_sb_get_desc( connections[i].c_sb ) == s ) {
if( sd == s ) {
c = &connections[i];
break;
}
@ -241,13 +241,16 @@ static Connection* connection_get( ber_socket_t s )
#endif
if( c != NULL ) {
ber_socket_t sd;
ldap_pvt_thread_mutex_lock( &c->c_mutex );
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if( c->c_struct_state != SLAP_C_USED ) {
/* connection must have been closed due to resched */
assert( c->c_conn_state == SLAP_C_INVALID );
assert( !ber_pvt_sb_in_use( c->c_sb ) );
assert( sd == AC_SOCKET_INVALID );
Debug( LDAP_DEBUG_TRACE,
"connection_get(%d): connection not used\n",
@ -265,7 +268,7 @@ static Connection* connection_get( ber_socket_t s )
assert( c->c_struct_state == SLAP_C_USED );
assert( c->c_conn_state != SLAP_C_INVALID );
assert( ber_pvt_sb_in_use( c->c_sb ) );
assert( sd != AC_SOCKET_INVALID );
c->c_activitytime = slap_get_time();
}
@ -323,6 +326,10 @@ long connection_init(
c = NULL;
for( i=0; i < dtblsize; i++) {
ber_socket_t sd;
ber_sockbuf_ctrl( connections[i].c_sb, LBER_SB_OPT_GET_FD, &sd );
if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
assert( connections[i].c_sb == 0 );
c = &connections[i];
@ -330,14 +337,14 @@ long connection_init(
}
if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
assert( !ber_pvt_sb_in_use( connections[i].c_sb ));
assert( sd == AC_SOCKET_INVALID );
c = &connections[i];
break;
}
assert( connections[i].c_struct_state == SLAP_C_USED );
assert( connections[i].c_conn_state != SLAP_C_INVALID );
assert( ber_pvt_sb_in_use( connections[i].c_sb ));
assert( sd != AC_SOCKET_INVALID );
}
if( c == NULL ) {
@ -418,10 +425,14 @@ long connection_init(
c->c_activitytime = c->c_starttime = slap_get_time();
ber_pvt_sb_set_desc( c->c_sb, s );
ber_pvt_sb_set_io( c->c_sb, &ber_pvt_sb_io_tcp, NULL );
if( ber_pvt_sb_set_nonblock( c->c_sb, 1 ) < 0 ) {
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp, LBER_SBIOD_LEVEL_PROVIDER,
(void *)&s );
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
LBER_SBIOD_LEVEL_PROVIDER, NULL );
#ifdef LDAP_DEBUG
ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, INT_MAX, NULL );
#endif
if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK, (void *)1 ) < 0 ) {
Debug( LDAP_DEBUG_ANY,
"connection_init(%d, %s): set nonblocking failed\n",
s, c->c_peer_name,0 );
@ -454,6 +465,7 @@ static void
connection_destroy( Connection *c )
{
/* note: connections_mutex should be locked by caller */
ber_socket_t sd;
assert( connections != NULL );
assert( c != NULL );
@ -527,18 +539,17 @@ connection_destroy( Connection *c )
c->c_currentber = NULL;
}
if ( ber_pvt_sb_in_use(c->c_sb) ) {
int sd = ber_pvt_sb_get_desc(c->c_sb);
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if ( sd != AC_SOCKET_INVALID ) {
slapd_remove( sd, 0 );
ber_pvt_sb_close( c->c_sb );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld fd=%d closed\n",
c->c_connid, sd, 0, 0, 0 );
}
ber_pvt_sb_destroy( c->c_sb );
ber_sockbuf_free( c->c_sb );
c->c_sb = ber_sockbuf_alloc( );
c->c_conn_state = SLAP_C_INVALID;
c->c_struct_state = SLAP_C_UNUSED;
@ -590,27 +601,32 @@ void connection_closing( Connection *c )
/* c_mutex must be locked by caller */
if( c->c_conn_state != SLAP_C_CLOSING ) {
ber_socket_t sd;
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"connection_closing: readying conn=%ld sd=%d for close\n",
c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
c->c_connid, sd, 0 );
/* update state to closing */
c->c_conn_state = SLAP_C_CLOSING;
/* don't listen on this port anymore */
slapd_clr_read( ber_pvt_sb_get_desc( c->c_sb ), 1 );
slapd_clr_read( sd, 1 );
/* abandon active operations */
connection_abandon( c );
/* wake write blocked operations */
slapd_clr_write( ber_pvt_sb_get_desc(c->c_sb), 1 );
slapd_clr_write( sd, 1 );
ldap_pvt_thread_cond_signal( &c->c_write_cv );
}
}
static void connection_close( Connection *c )
{
ber_socket_t sd;
assert( connections != NULL );
assert( c != NULL );
assert( c->c_struct_state == SLAP_C_USED );
@ -618,16 +634,17 @@ static void connection_close( Connection *c )
/* note: connections_mutex and c_mutex should be locked by caller */
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
if( c->c_ops != NULL ) {
Debug( LDAP_DEBUG_TRACE,
"connection_close: deferring conn=%ld sd=%d\n",
c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
c->c_connid, sd, 0 );
return;
}
Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d\n",
c->c_connid, ber_pvt_sb_get_desc( c->c_sb ), 0 );
c->c_connid, sd, 0 );
connection_destroy( c );
}
@ -893,15 +910,14 @@ int connection_read(ber_socket_t s)
* to propagate to client. */
FD_ZERO(&rfd);
FD_SET(s, &rfd);
ber_pvt_sb_set_readahead(c->c_sb, 0);
for (rc=1; rc>0;)
{
char buf[4096];
tv.tv_sec = 1;
tv.tv_usec = 0;
rc = select(s+1, &rfd, NULL, NULL, &tv);
if (rc == 1)
rc = ber_pvt_sb_read(c->c_sb, buf, sizeof(buf));
ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN,
NULL);
}
connection_close( c );
} else if ( rc == 0 ) {
@ -916,7 +932,7 @@ int connection_read(ber_socket_t s)
#define CONNECTION_INPUT_LOOP 1
#ifdef DATA_READY_LOOP
while(!rc && ber_pvt_sb_data_ready(&c->c_sb))
while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_DATA_READY, NULL ) )
#elif CONNECTION_INPUT_LOOP
while(!rc)
#endif
@ -935,9 +951,9 @@ int connection_read(ber_socket_t s)
connection_close( c );
}
if ( ber_pvt_sb_needs_read( c->c_sb ) )
if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) )
slapd_set_read( s, 1 );
if ( ber_pvt_sb_needs_write( c->c_sb ) )
if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) )
slapd_set_write( s, 1 );
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );
@ -966,16 +982,13 @@ connection_input(
!= LDAP_TAG_MESSAGE )
{
int err = errno;
ber_socket_t sd;
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"ber_get_next on fd %d failed errno=%d (%s)\n",
ber_pvt_sb_get_desc( conn->c_sb ), err, sock_errstr(err) );
Debug( LDAP_DEBUG_TRACE,
"\t*** got %ld of %lu so far\n",
(long) ( conn->c_currentber->ber_buf
? conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf
: 0 ),
(long) conn->c_currentber->ber_len, 0 );
sd, err, sock_errstr(err) );
if ( err != EWOULDBLOCK && err != EAGAIN ) {
/* log, close and send error */
@ -1043,9 +1056,12 @@ connection_resched( Connection *conn )
Operation *op;
if( conn->c_conn_state == SLAP_C_CLOSING ) {
ber_socket_t sd;
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
Debug( LDAP_DEBUG_TRACE,
"connection_resched: attempting closing conn=%ld sd=%d\n",
conn->c_connid, ber_pvt_sb_get_desc( conn->c_sb ), 0 );
conn->c_connid, sd, 0 );
connection_close( conn );
return 0;
@ -1158,9 +1174,9 @@ int connection_write(ber_socket_t s)
ldap_pvt_thread_cond_signal( &c->c_write_cv );
if ( ber_pvt_sb_needs_read( c->c_sb ) )
if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) )
slapd_set_read( s, 1 );
if ( ber_pvt_sb_needs_write( c->c_sb ) )
if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) )
slapd_set_write( s, 1 );
connection_return( c );
ldap_pvt_thread_mutex_unlock( &connections_mutex );

View file

@ -19,9 +19,6 @@
#include "slap.h"
/* we need LBER internals */
#include "../../libraries/liblber/lber-int.h"
static char *v2ref( struct berval **ref, const char *text )
{
size_t len = 0, i = 0;
@ -196,6 +193,7 @@ static long send_ldap_ber(
/* write the pdu */
while( 1 ) {
int err;
ber_socket_t sd;
if ( connection_state_closing( conn ) ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
@ -230,7 +228,8 @@ static long send_ldap_ber(
/* wait for socket to be write-ready */
conn->c_writewaiter = 1;
slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
slapd_set_write( sd, 1 );
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
conn->c_writewaiter = 0;
@ -382,7 +381,8 @@ send_ldap_disconnect(
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
@ -453,7 +453,8 @@ send_ldap_result(
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
@ -499,7 +500,8 @@ send_ldap_sasl(
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
@ -540,7 +542,8 @@ send_ldap_extended(
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),
@ -603,7 +606,8 @@ send_search_result(
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
ber_pvt_sb_udp_set_dst( conn->c_sb, &op->o_clientaddr );
ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_UDP_SET_DST,
(void *)&op->o_clientaddr );
Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
inet_ntoa(((struct sockaddr_in *)
&op->o_clientaddr)->sin_addr ),