Commit 8153a403 authored by Bart Hartgers's avatar Bart Hartgers
Browse files

The new&improved Sockbuf. This adds the infrastructure on which

support for TLS and SASL will be build.

Please inform me of any problems.
parent e0fdd894
......@@ -205,9 +205,9 @@ lber_set_option LDAP_P((void *item, int option, void *invalue));
/*
* LBER Sockbuf functions
*/
LDAP_F Sockbuf *lber_sockbuf_alloc LDAP_P((void));
LDAP_F Sockbuf *lber_sockbuf_alloc_fd LDAP_P((int fd));
LDAP_F void lber_sockbuf_free LDAP_P((Sockbuf *sb));
LDAP_F Sockbuf *lber_pvt_sockbuf_alloc LDAP_P((void));
LDAP_F Sockbuf *lber_pvt_sockbuf_alloc_fd LDAP_P((int fd));
LDAP_F void lber_pvt_sockbuf_free LDAP_P((Sockbuf *sb));
LDAP_END_DECL
......
......@@ -443,13 +443,6 @@ typedef struct ldap_friendly {
char *lf_friendly;
} LDAPFriendlyMap;
/*
* handy macro to check whether LDAP struct is set up for CLDAP or not
*/
#define LDAP_IS_CLDAP( ld ) ( (ld)->ld_sb.sb_naddr > 0 )
/*
* types for ldap URL handling
*/
......
......@@ -7,8 +7,8 @@
LIBRARY = liblber.la
XLIBRARY = ../liblber.a
SRCS= decode.c encode.c io.c bprint.c options.c
OBJS= decode.lo encode.lo io.lo bprint.lo options.lo
SRCS= decode.c encode.c io.c bprint.c options.c sockbuf.c
OBJS= decode.lo encode.lo io.lo bprint.lo options.lo sockbuf.lo
XSRCS= version.c
PROGRAMS= dtest etest idtest
......
......@@ -49,7 +49,7 @@ main( int argc, char **argv )
cshow( stdout );
#endif /* MACOS */
sb = lber_sockbuf_alloc_fd( fileno(stdin) );
sb = lber_pvt_sb_alloc_fd( fileno(stdin) );
if( (ber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
perror( "ber_alloc_t" );
......@@ -68,6 +68,6 @@ main( int argc, char **argv )
}
printf( "got int %ld\n", i );
lber_sockbuf_free( sb );
lber_pvt_sb_free( sb );
return( 0 );
}
......@@ -58,7 +58,7 @@ main( int argc, char **argv )
fd = fileno(stdout);
#endif /* MACOS */
sb = lber_sockbuf_alloc_fd( fd );
sb = lber_pvt_sb_alloc_fd( fd );
if ( (ber = ber_alloc()) == NULLBER ) {
perror( "ber_alloc" );
......@@ -171,6 +171,6 @@ main( int argc, char **argv )
#endif
lber_sockbuf_free( sb );
lber_pvt_sb_free( sb );
return( 0 );
}
......@@ -32,130 +32,11 @@
#include "lber-int.h"
static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len ));
static int ber_filbuf LDAP_P(( Sockbuf *sb, long len ));
static long BerRead LDAP_P(( Sockbuf *sb, char *buf, long len ));
#ifdef PCNFS
static int BerWrite LDAP_P(( Sockbuf *sb, char *buf, long len ));
#endif /* PCNFS */
#define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \
(unsigned char)*sb->sb_ber.ber_ptr++ : \
ber_filbuf( sb, len ))
#ifdef MACOS
/*
* MacTCP/OpenTransport
*/
#define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL )
#define MAX_WRITE 65535
#define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE )
#else /* MACOS */
#ifdef DOS
#ifdef PCNFS
/*
* PCNFS (under DOS)
*/
#define read( s, b, l ) recv( s, b, l, 0 )
#define BerWrite( s, b, l ) send( s->sb_sd, b, (int) l, 0 )
#endif /* PCNFS */
#ifdef NCSA
/*
* NCSA Telnet TCP/IP stack (under DOS)
*/
#define read( s, b, l ) nread( s, b, l )
#define BerWrite( s, b, l ) netwrite( s->sb_sd, b, l )
#endif /* NCSA */
#ifdef WINSOCK
/*
* Windows Socket API (under DOS/Windows 3.x)
*/
#define read( s, b, l ) recv( s, b, l, 0 )
#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
#endif /* WINSOCK */
#else /* DOS */
#ifdef _WIN32
/*
* 32-bit Windows Socket API (under Windows NT or Windows 95)
*/
#define read( s, b, l ) recv( s, b, l, 0 )
#define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
#else /* _WIN32 */
#ifdef VMS
/*
* VMS -- each write must be 64K or smaller
*/
#define MAX_WRITE 65535
#define BerWrite( sb, b, l ) write( sb->sb_sd, b, (l<MAX_WRITE)? l : MAX_WRITE)
#else /* VMS */
/*
* everything else (Unix/BSD 4.3 socket API)
*/
#define BerWrite( sb, b, l ) write( sb->sb_sd, b, l )
#endif /* VMS */
#define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \
(struct sockaddr *)sb->sb_fromaddr, \
(al = sizeof(struct sockaddr), &al))
#define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \
(struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr))
#endif /* _WIN32 */
#endif /* DOS */
#endif /* MACOS */
#ifndef udp_read
#define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED
#define udp_write( sb, b, l ) CLDAP NOT SUPPORTED
#endif /* udp_read */
static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len ));
#define EXBUFSIZ 1024
static int
ber_filbuf( Sockbuf *sb, long len )
{
short rc;
#ifdef LDAP_CONNECTIONLESS
int addrlen;
#endif /* LDAP_CONNECTIONLESS */
if ( sb->sb_ber.ber_buf == NULL ) {
if ( (sb->sb_ber.ber_buf = (char *) malloc( READBUFSIZ )) ==
NULL )
return( -1 );
sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf;
sb->sb_ber.ber_end = sb->sb_ber.ber_buf;
}
if ( sb->sb_naddr > 0 ) {
#ifdef LDAP_CONNECTIONLESS
rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen );
if ( sb->sb_debug ) {
lber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
"ber_filbuf udp_read %d bytes\n",
rc );
if ( rc > 0 )
lber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
sb->sb_ber.ber_buf, rc );
}
#else /* LDAP_CONNECTIONLESS */
rc = -1;
#endif /* LDAP_CONNECTIONLESS */
} else {
rc = read( sb->sb_sd, sb->sb_ber.ber_buf,
((sb->sb_options & LBER_NO_READ_AHEAD) && (len < READBUFSIZ)) ?
len : READBUFSIZ );
}
if ( rc > 0 ) {
sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1;
sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc;
return( (unsigned char)*sb->sb_ber.ber_buf );
}
return( -1 );
}
static long
BerRead( Sockbuf *sb, char *buf, long len )
{
......@@ -163,20 +44,19 @@ BerRead( Sockbuf *sb, char *buf, long len )
long nread = 0;
while ( len > 0 ) {
if ( (c = bergetc( sb, len )) < 0 ) {
if ( (c = lber_pvt_sb_read( sb, buf, len )) <= 0 ) {
if ( nread > 0 )
break;
return( c );
}
*buf++ = (char) c;
nread++;
len--;
buf+= c;
nread+=c;
len-=c;
}
return( nread );
}
long
ber_read( BerElement *ber, char *buf, unsigned long len )
{
......@@ -271,7 +151,7 @@ ber_free( BerElement *ber, int freebuf )
int
ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
{
long nwritten, towrite, rc;
long nwritten, towrite, rc;
if ( ber->ber_rwptr == NULL ) {
ber->ber_rwptr = ber->ber_buf;
......@@ -289,37 +169,18 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
#if !defined(MACOS) && !defined(DOS)
if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
rc = write( sb->sb_fd, ber->ber_buf, towrite );
rc = write( sb->sb_fd, ber->ber_rwptr, towrite );
if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
return( (int)rc );
}
}
#endif
nwritten = 0;
do {
if (sb->sb_naddr > 0) {
#ifdef LDAP_CONNECTIONLESS
rc = udp_write( sb, ber->ber_buf + nwritten,
(size_t)towrite );
#else /* LDAP_CONNECTIONLESS */
rc = -1;
#endif /* LDAP_CONNECTIONLESS */
if ( rc <= 0 )
return( -1 );
/* fake error if write was not atomic */
if (rc < towrite) {
#ifdef EMSGSIZE
errno = EMSGSIZE;
#endif
return( -1 );
}
} else {
if ( (rc = BerWrite( sb, ber->ber_rwptr,
(size_t) towrite )) <= 0 ) {
return( -1 );
}
rc = lber_pvt_sb_write( sb, ber->ber_rwptr, towrite );
if (rc<=0) {
return -1;
}
towrite -= rc;
nwritten += rc;
......@@ -477,7 +338,7 @@ get_tag( Sockbuf *sb )
char *tagp;
unsigned int i;
if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
if ( lber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
......@@ -486,7 +347,7 @@ get_tag( Sockbuf *sb )
tagp = (char *) &tag;
tagp[0] = xbyte;
for ( i = 1; i < sizeof(long); i++ ) {
if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
if ( lber_pvt_sb_read( sb, (char *) &xbyte, 1 ) != 1 )
return( LBER_DEFAULT );
tagp[i] = xbyte;
......@@ -553,7 +414,7 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
*/
*len = netlen = 0;
if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) {
if ( lber_pvt_sb_read( sb, (char *) &lc, 1 ) != 1 ) {
return( LBER_DEFAULT );
}
if ( lc & 0x80 ) {
......@@ -582,12 +443,12 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
return( LBER_DEFAULT );
}
#endif /* DOS && !_WIN32 */
#ifdef DEADWOOD
if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) &&
*len > (unsigned long) sb->sb_max_incoming ) {
return( LBER_DEFAULT );
}
#endif
if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) {
return( LBER_DEFAULT );
}
......@@ -598,7 +459,7 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
toread = (unsigned long)ber->ber_end - (unsigned long)ber->ber_rwptr;
do {
if ( (rc = BerRead( sb, ber->ber_rwptr, (long)toread )) <= 0 ) {
if ( (rc = lber_pvt_sb_read( sb, ber->ber_rwptr, (long)toread )) <= 0 ) {
return( LBER_DEFAULT );
}
......@@ -619,34 +480,34 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
return( ber->ber_tag );
}
Sockbuf *lber_sockbuf_alloc( void )
Sockbuf *lber_pvt_sb_alloc( void )
{
Sockbuf *sb = calloc(1, sizeof(Sockbuf));
sb->sb_debug = lber_int_debug;
lber_pvt_sb_init( sb );
return sb;
}
Sockbuf *lber_sockbuf_alloc_fd( int fd )
Sockbuf *lber_pvt_sb_alloc_fd( int fd )
{
Sockbuf *sb = lber_sockbuf_alloc();
sb->sb_sd = fd;
Sockbuf *sb = lber_pvt_sb_alloc();
lber_pvt_sb_set_desc( sb, fd );
lber_pvt_sb_set_io( sb, &lber_pvt_sb_io_tcp, NULL );
return sb;
}
void lber_sockbuf_free( Sockbuf *sb )
void lber_pvt_sb_free( Sockbuf *sb )
{
if(sb == NULL) return;
lber_pvt_sb_destroy( sb );
free(sb);
}
int lber_sockbuf_get_option( Sockbuf *sb, int opt, void *outvalue )
int lber_pvt_sb_get_option( Sockbuf *sb, int opt, void *outvalue )
{
return LBER_OPT_ERROR;
}
int lber_sockbuf_set_option( Sockbuf *sb, int opt, void *invalue )
int lber_pvt_sb_set_option( Sockbuf *sb, int opt, void *invalue )
{
return LBER_OPT_ERROR;
}
......@@ -50,28 +50,90 @@ struct berelement {
};
#define NULLBER ((BerElement *) 0)
struct sockbuf;
struct sockbuf_io {
int (*sbi_setup)( struct sockbuf * sb, void *arg );
int (*sbi_remove)( struct sockbuf *sb );
long (*sbi_read)( struct sockbuf *sb, void *buf, long len );
long (*sbi_write)( struct sockbuf *sb, void *buf, long 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
{
long buf_size;
long buf_ptr;
long buf_end;
char *buf_base;
};
typedef struct sockbuf_io Sockbuf_IO;
typedef struct sockbuf_sec Sockbuf_Sec;
typedef struct sockbuf_buf Sockbuf_Buf;
#define lber_pvt_sb_get_desc( sb ) ((sb)->sb_sd)
#define lber_pvt_sb_set_desc( sb, val ) ((sb)->sb_sd =(val))
#define lber_pvt_sb_in_use( sb ) ((sb)->sb_sd!=-1)
#ifdef USE_SASL
#define lber_pvt_sb_data_ready( sb ) \
(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready) || ((sb)->sb_sec_ready))
#else
#define lber_pvt_sb_data_ready( sb ) \
(((sb)->sb_buf_ready) || ((sb)->sb_trans_ready))
#endif
struct sockbuf {
short sb_item_type; /* always LBER_ITEM_SOCKBUF */
short sb_options; /* to support copying ber elements */
int sb_debug;
int sb_fd;
int sb_debug:1;
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;
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
#ifndef MACOS
int sb_sd;
#else /* MACOS */
void *sb_sd;
#endif /* MACOS */
#ifdef DEADWOOD
long sb_max_incoming;
BerElement sb_ber;
int sb_naddr; /* > 0 implies using CLDAP (UDP) */
void *sb_useaddr; /* pointer to sockaddr to use next */
void *sb_fromaddr; /* pointer to message source sockaddr */
void **sb_addrs; /* actually an array of pointers to
sockaddrs */
#endif
Sockbuf_Buf sb_buf;
#ifdef LDAP_SASL
Sockbuf_Buf sb_sec_buf_in;
Sockbuf_Buf sb_sec_buf_out;
long sb_sec_prev_len;
#endif
};
#define READBUFSIZ 8192
struct seqorset {
......@@ -104,4 +166,25 @@ LDAP_F int lber_log_sos_dump LDAP_P((
int loglvl,
Seqorset *sos ));
/* sockbuf.c */
LDAP_F int lber_pvt_sb_init LDAP_P(( Sockbuf *sb ));
LDAP_F int lber_pvt_sb_destroy LDAP_P(( Sockbuf *sb ));
#ifdef USE_SASL
LDAP_F int lber_pvt_sb_set_sec LDAP_P(( Sockbuf *sb, Sockbuf_Sec *sec, void *arg ));
LDAP_F int lber_pvt_sb_clear_sec LDAP_P(( Sockbuf *sb ));
#endif
LDAP_F int lber_pvt_sb_set_io LDAP_P(( Sockbuf *sb, Sockbuf_IO *layer, void *arg ));
LDAP_F int lber_pvt_sb_clear_io LDAP_P(( Sockbuf *sb ));
LDAP_F int lber_pvt_sb_close LDAP_P((Sockbuf *sb ));
LDAP_F int lber_pvt_sb_set_nonblock LDAP_P(( Sockbuf *sb, int nb ));
LDAP_F int lber_pvt_sb_set_readahead LDAP_P(( Sockbuf *sb, int rh ));
LDAP_F long lber_pvt_sb_read LDAP_P(( Sockbuf *sb, void *buf, long len ));
LDAP_F long lber_pvt_sb_write LDAP_P(( Sockbuf *sb, void *buf, long len ));
LDAP_F int lber_pvt_sb_udp_set_dst LDAP_P((Sockbuf *sb, void *addr ));
LDAP_F void *lber_pvt_sb_udp_get_src LDAP_P((Sockbuf *sb ));
extern Sockbuf_IO lber_pvt_sb_io_tcp;
extern Sockbuf_IO lber_pvt_sb_io_udp;
#endif /* _LBER_INT_H */
This diff is collapsed.
......@@ -98,7 +98,7 @@ do_abandon( LDAP *ld, int origid, int msgid )
ld->ld_errno = LDAP_NO_MEMORY;
} else {
#ifdef LDAP_CONNECTIONLESS
if ( ld->ld_sb.sb_naddr > 0 ) {
if ( ld->ld_cldapnaddr > 0 ) {
err = ber_printf( ber, "{isti}",
++ld->ld_msgid, ld->ld_cldapdn,
LDAP_REQ_ABANDON, msgid );
......
......@@ -84,19 +84,19 @@ cldap_open( char *host, int port )
close( s );
return( NULL );
}
if (( ld = ldap_init( host, port )) == NULL ) {
close( s );
return( NULL );
}
if ( (ld->ld_sb.sb_fromaddr = (void *) calloc( 1,
sizeof( struct sockaddr ))) == NULL ) {
ld->ld_cldapnaddr = 0;
ld->ld_cldapaddrs = NULL;
ldap_ld_free(ld, 1);
return( NULL );
}
ld->ld_sb.sb_sd = s;
ld->ld_sb.sb_naddr = 0;
if (lber_pvt_sb_set_io( &(ld->ld_sb), &lber_pvt_sb_io_udp, NULL )<0) {
ldap_ld_free(ld, 1 );
return NULL;
}
ld->ld_version = LDAP_VERSION;
sock.sin_family = AF_INET;
......@@ -155,7 +155,7 @@ cldap_open( char *host, int port )
}
}
if ( ld->ld_sb.sb_addrs == NULL
if ( ld->ld_cldapaddrs == NULL
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
|| ( ld->ld_defconn = ldap_new_connection( ld, NULL, 1,0,0 )) == NULL
#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
......@@ -164,15 +164,16 @@ cldap_open( char *host, int port )
DO_RETURN( NULL );
}
ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ 0 ];
lber_pvt_sb_udp_set_dst( &ld->ld_sb, ld->ld_cldapaddrs[0] );
cldap_setretryinfo( ld, 0, 0 );
#ifdef LDAP_DEBUG
putchar( '\n' );
for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
for ( i = 0; i < ld->ld_cldapnaddr; ++i ) {
Debug( LDAP_DEBUG_TRACE, "end of cldap_open address %d is %s\n",
i, inet_ntoa( ((struct sockaddr_in *)
ld->ld_sb.sb_addrs[ i ])->sin_addr ), 0 );
ld->ld_cldapaddrs[ i ])->sin_addr ), 0 );
}
#endif
......@@ -217,11 +218,13 @@ cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
if ( cri.cri_try != 0 ) {
--ld->ld_msgid; /* use same id as before */
}
ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ cri.cri_useaddr ];
lber_pvt_sb_udp_set_dst( &(ld->ld_sb),
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 *)
ld->ld_sb.sb_useaddr)->sin_addr ), 0 );
ld->ld_cldapaddrs[ cri.cri_useaddr ])->sin_addr), 0 );
if ( (msgid = ldap_search( ld, base, scope, filter, attrs,
attrsonly )) == -1 ) {
......@@ -253,12 +256,12 @@ add_addr( LDAP *ld, struct sockaddr *sap )
ld->ld_errno = LDAP_NO_MEMORY;
return( -1 );
}
if ( ld->ld_sb.sb_naddr == 0 ) {
if ( ld->ld_cldapnaddr == 0 ) {
addrs = (struct sockaddr **)malloc( sizeof(struct sockaddr *));
} else {
addrs = (struct sockaddr **)realloc( ld->ld_sb.sb_addrs,
( ld->ld_sb.sb_naddr + 1 ) * sizeof(struct sockaddr *));
addrs = (struct sockaddr **)realloc( ld->ld_cldapaddrs,
( ld->ld_cldapnaddr + 1 ) * sizeof(struct sockaddr *));
}
if ( addrs == NULL ) {
......@@ -268,8 +271,8 @@ add_addr( LDAP *ld, struct sockaddr *sap )
}
SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr ));
addrs[ ld->ld_sb.sb_naddr++ ] = newsap;
ld->ld_sb.sb_addrs = (void **)addrs;
addrs[ ld->ld_cldapnaddr++ ] = newsap;
ld->ld_cldapaddrs = (void **)addrs;
return( 0 );
}